function mgcoarraylist::_overloadBracketsRightSide, isRange, $
ss1, ss2, ss3, ss4, $
ss5, ss6, ss7, ss8
compile_opt strictarr
on_error, 2
if (isRange[0]) then begin
_ss1 = ss1
if (_ss1[1] le 0L) then _ss1[1] = (_ss1[1] + self.nUsed) mod self.nUsed
return, (*self.pData)[_ss1[0]:_ss1[1]:_ss1[2]]
endif else begin
if (n_elements(ss1) gt 1) then return, (*self.pData)[ss1]
if (ss1 ge self.nUsed) then begin
message, string(ss1, format='(%"Attempt to subscript with %d is out of range")')
endif
index = ss1 mod self.nUsed
if (index lt 0) then index = (index + self.nUsed) mod self.nUsed
return, (*self.pData)[index]
endelse
end
pro mgcoarraylist::_overloadBracketsLeftSide, objref, value, isRange, $
ss1, ss2, ss3, ss4, $
ss5, ss6, ss7, ss8
compile_opt strictarr
if (isRange[0]) then begin
_ss1 = ss1
if (_ss1[1] le 0L) then _ss1[1] = (_ss1[1] + self.nUsed) mod self.nUsed
(*self.pData)[_ss1[0]:_ss1[1]:_ss1[2]] = value
endif else begin
if (ss1 + n_elements(value) gt self.nUsed) then begin
message, 'Out of range subscript encountered'
endif
index = ss1 mod self.nUsed
if (index lt 0) then index = (index + self.nUsed) mod self.nUsed
(*self.pData)[index] = value
endelse
end
function mgcoarraylist::_overloadPlus, left, right
compile_opt strictarr
on_error, 2
left->getProperty, block_size=leftBlockSize, type=leftType, $
count=leftCount, example=leftExample
right->getProperty, block_size=rightBlockSize, type=rightType, $
count=rightCount, example=rightExample
if (leftType ne rightType) then begin
message, 'cannot concatenate array lists of different types'
endif
result = obj_new('MGcoArrayList', $
type=leftType, example=leftExample, $
block_size=(leftCount > rightCount) > (leftBlockSize > rightBlockSize))
if (leftCount gt 0L) then result->add, left->get(/all)
if (rightCount gt 0L) then result->add, right->get(/all)
return, result
end
function mgcoarraylist::_repeatNumeric, elements, mult
compile_opt strictarr
n = n_elements(elements)
return, reform(rebin(reform(elements, n, 1), n, mult), n * mult)
end
function mgcoarraylist::_repeatNonNumeric, elements, mult
compile_opt strictarr
n = n_elements(elements)
result = make_array(n * mult, type=size(elements, /type))
for i = 0L, mult - 1L do result[i * n] = elements
return, result
end
function mgcoarraylist::_repeatStructure, elements, mult
compile_opt strictarr
n = n_elements(elements)
result = replicate(elements[0], n * mult)
for i = 0L, mult - 1L do result[i * n] = elements
return, result
end
function mgcoarraylist::_overloadAsterisk, left, right
compile_opt strictarr
on_error, 2
case 1 of
size(left, /type) ne 11: begin
mult = left
lst = right
end
size(right, /type) ne 11: begin
mult = right
lst = left
end
else: message, 'need a non-object multiplier'
endcase
if (mult le 0) then message, 'multiplier must be positive'
lst->getProperty, block_size=blockSize, count=count, type=type, example=example
elements = lst->get(/all)
result = obj_new('MGcoArrayList', $
type=type, example=example, $
block_size=blockSize > (mult * count))
case type of
0:
1: rep = self->_repeatNumeric(elements, mult)
2: rep = self->_repeatNumeric(elements, mult)
3: rep = self->_repeatNumeric(elements, mult)
4: rep = self->_repeatNumeric(elements, mult)
5: rep = self->_repeatNumeric(elements, mult)
6: rep = self->_repeatNonNumeric(elements, mult)
7: rep = self->_repeatNonNumeric(elements, mult)
8: rep = self->_repeatStructure(elements, mult)
9: rep = self->_repeatNonNumeric(elements, mult)
10: rep = self->_repeatNonNumeric(elements, mult)
11: rep = self->_repeatNonNumeric(elements, mult)
12: rep = self->_repeatNumeric(elements, mult)
13: rep = self->_repeatNumeric(elements, mult)
14: rep = self->_repeatNumeric(elements, mult)
15: rep = self->_repeatNumeric(elements, mult)
endcase
result->add, rep
return, result
end
function mgcoarraylist::_overloadForeach, value, key
compile_opt strictarr
key = n_elements(key) eq 0L ? 0L : (key + 1L)
if (key lt self.nUsed) then begin
value = (*self.pData)[key]
return, 1
endif else return, 0
end
function mgcoarraylist::_overloadPrint
compile_opt strictarr
return, self.nUsed eq 0L ? '[]' : (*self.pData)[0:self.nUsed-1L]
end
function mgcoarraylist::_overloadHelp, varname
compile_opt strictarr
all_types = ['UNDEFINED', 'BYTE', 'INT', 'LONG', 'FLOAT', 'DOUBLE', $
'COMPLEX', 'STRING', 'STRUCTURE', 'DCOMPLEX', 'POINTER', $
'OBJREF', 'UINT', 'ULONG', 'LONG64', 'ULONG64']
type = all_types[self.type]
specs = string(self.nUsed, '(%"MGcoArrayList[%d]")')
return, string(varname, type, specs, format='(%"%-15s %-9s = %s")')
end
function mgcoarraylist::_overloadSize
compile_opt strictarr
return, self.nUsed
end
pro mgcoarraylist::getProperty, type=type, block_size=blockSize, $
example=example, count=count, _ref_extra=e
compile_opt strictarr, logical_predicate
if (arg_present(type)) then type = self.type
if (arg_present(blockSize)) then blockSize = self.blockSize
if (arg_present(example) && ptr_valid(self.pExample)) then begin
example = *self.pExample
endif
if (arg_present(count)) then count = self.nUsed
if (n_elements(e) gt 0) then begin
self->mgcoabstractlist::getProperty, _strict_extra=e
endif
end
pro mgcoarraylist::setProperty, type=type, block_size=blockSize
compile_opt strictarr
on_error, 2
if (n_elements(type) gt 0 && ((type eq 8) ne (self.type eq 8))) then begin
message, 'Cannot convert between structures and other types'
endif
if (n_elements(blockSize) gt 0 && (blockSize lt self.nUsed)) then begin
message, 'Cannot set the blockSize to less than number of elements in list'
endif
if (n_elements(type) eq 0 && n_elements(blockSize) eq 0) then return
self.version++
self.type = n_elements(type) eq 0 ? self.type : type
self.blockSize = n_elements(blockSize) eq 0 ? self.blockSize : blockSize
if (self.type eq 8) then begin
newData = replicate(*self.pExample, self.blockSize)
endif else begin
newData = make_array(self.blockSize, type=self.type, /nozero)
endelse
newData[0] = (*self.pData)[0:self.nUsed-1L]
*self.pData = newData
end
pro mgcoarraylist::remove, elements, position=position, all=all
compile_opt strictarr
self.version++
if (self.nUsed eq 0L) then return
if (keyword_set(all)) then begin
self.nUsed = 0L
return
endif
if (n_elements(position) gt 0L) then begin
if (n_elements(position) lt self.nUsed) then begin
keep = bytarr(self.nUsed) + 1B
keep[position] = 0B
keep_ind = where(keep)
(*self.pData)[0L:self.nUsed - n_elements(position) - 1L] = (*self.pData)[keep_ind]
endif
self.nUsed -= n_elements(position)
endif
if (n_elements(position) eq 0L && n_elements(elements) eq 0L) then begin
if (self.nUsed ne 1) then begin
(*self.pData)[0L] = (*self.pData)[1L:self.nUsed-1L]
endif
self.nUsed--
return
endif
for i = 0L, n_elements(elements) - 1L do begin
keepIndices = where((*self.pData)[0L:self.nUsed-1L] ne elements[i], $
nKeep)
if (nKeep gt 0L) then begin
self.nUsed = nKeep
(*self.pData)[0L] = (*self.pData)[keepIndices]
endif else begin
self.nUsed = 0L
break
endelse
endfor
end
pro mgcoarraylist::move, source, destination
compile_opt strictarr, logical_predicate
self.version++
if (source lt 0 || source ge self.nUsed) then begin
message, 'Source index out of bounds'
endif
if (destination lt 0 || destination ge self.nUsed) then begin
message, 'Destination index out of bounds'
endif
sourceElement = (*self.pData)[source]
if (source lt destination) then begin
(*self.pData)[source] = (*self.pData)[source+1L:destination]
endif else begin
(*self.pData)[destination+1L] = (*self.pData)[destination:source-1L]
endelse
(*self.pData)[destination] = sourceElement
end
function mgcoarraylist::isContained, elements, position=position
compile_opt strictarr, logical_predicate
n = n_elements(elements)
position = lonarr(n)
isContained = n gt 0 ? bytarr(n) : 0B
for i = 0L, n - 1L do begin
ind = where(*self.pData eq elements[i], nFound)
isContained[i] = nFound gt 0L
position[i] = ind[0]
endfor
return, isContained
end
pro mgcoarraylist::add, elements, position=position
compile_opt strictarr
self.version++
nNew = mg_n_elements(elements, /no_operatoroverload)
if (self.nUsed + nNew gt self.blockSize) then begin
self.blockSize *= 2L
while (self.nUsed + nNew gt self.blockSize) do self.blockSize *= 2L
if (self.type eq 8) then begin
newData = replicate(*self.pExample, self.blockSize)
endif else begin
newData = make_array(self.blockSize, type=self.type)
endelse
newData[0] = *self.pData
*self.pData = temporary(newData)
endif
case n_elements(position) of
0 : begin
(*self.pData)[self.nUsed] = elements
self.nUsed += nNew
end
1 : begin
if (position lt self.nUsed) then begin
(*self.pData)[position+nNew] = (*self.pData)[position:self.nUsed-1L]
endif
(*self.pData)[position] = elements
self.nUsed += nNew
end
else : begin
for el = 0L, nNew - 1L do begin
self->add, elements[el], position=position[el]
endfor
end
endcase
end
function mgcoarraylist::isaGet, position=position, isa=isa, all=all, $
count=count
compile_opt strictarr
if (keyword_set(all)) then begin
good = bytarr(self.blocksize)
for i = 0L, n_elements(isa) - 1L do begin
good or= obj_isa(*self.pData, isa[i])
endfor
return, where(good, count)
endif
nPos = n_elements(position)
good = bytarr(nPos)
for i = 0L, n_elements(isa) - 1L do begin
good or= obj_isa((*self.pData)[position], isa[i])
endfor
return, where(good, count)
end
function mgcoarraylist::get, all=all, position=position, count=count, isa=isa
compile_opt strictarr
on_error, 2
if (self.nUsed eq 0) then begin
count = 0L
return, -1L
endif
if (keyword_set(all)) then begin
count = self.nUsed
if (self.type eq 11 && n_elements(isa) gt 0) then begin
ind = self->isaGet(all=all, isa=isa, count=count)
if (count eq 0) then return, -1L
return, (*self.pData)[ind]
endif
return, (*self.pData)[0:self.nUsed-1L]
endif
if (n_elements(position) eq 0) then begin
count = 1L
if (self.type eq 11 && n_elements(isa) gt 0) then begin
ind = self->isaGet(position=0, isa=isa, count=count)
if (count eq 0) then return, -1L
return, (*self.pData)[ind]
endif
return, (*self.pData)[0]
endif
badInd = where(position lt 0 or position gt (self.nUsed - 1L), nOutOfBounds)
if (nOutOfBounds gt 0) then begin
message, 'Position value out of range'
endif
count = n_elements(position)
if (self.type eq 11 && n_elements(isa) gt 0) then begin
ind = self->isaGet(position=position, isa=isa, count=count)
if (count eq 0) then return, -1L
return, (*self.pData)[position[ind]]
endif
return, (*self.pData)[position]
end
function mgcoarraylist::count
compile_opt strictarr
return, self.nUsed
end
function mgcoarraylist::iterator
compile_opt strictarr
return, obj_new('MGcoArrayListIterator', self)
end
pro mgcoarraylist::cleanup
compile_opt strictarr
if (self.type eq 11) then obj_destroy, *self.pData
ptr_free, self.pExample, self.pData
self->MGcoAbstractList::cleanup
end
function mgcoarraylist::init, elements, $
type=type, example=example, $
block_size=blockSize
compile_opt strictarr
on_error, 2
self.nUsed = 0L
self.type = n_elements(type) eq 0 $
? (n_elements(elements) eq 0 $
? size(example, /type) $
: size(elements, /type)) $
: type
if (self.type eq 0) then message, 'List type is undefined'
self.blockSize = n_elements(blockSize) eq 0 ? 1000 : blockSize
if (self.blockSize le 0) then message, 'List size must be positive'
self.blockSize >= n_elements(value)
if (self.type eq 8) then begin
if (n_elements(example) eq 0) then begin
message, 'Structure lists must specify type with EXAMPLE keyword'
endif
data = replicate(example, self.blockSize)
self.pExample = ptr_new(example)
endif else begin
data = make_array(self.blockSize, type=self.type)
endelse
self.pData = ptr_new(data, /no_copy)
if (n_elements(elements) gt 0) then self->add, elements
return, 1B
end
pro mgcoarraylist__define
compile_opt strictarr
define = { MGcoArrayList, inherits MGcoAbstractList, $
pData: ptr_new(), $
nUsed: 0L, $
type: 0L, $
blockSize: 0L, $
pExample: ptr_new() $
}
end