pro mgcoarraylist::getProperty, type=type, blockSize=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, blockSize=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)
endelse
newData[0] = (*self.pData)[0:self.nUsed-1L]
*self.pData = newData
end
pro mgcoarraylist::remove, elements, position=position, all=all
compile_opt strictarr
on_error, 2
self.version++
if (self.nUsed eq 0L) then return
if (keyword_set(all)) then begin
self.nUsed = 0L
return
endif
case n_elements(position) of
0 :
1 : begin
pos = position[0]
if (pos ge self.nUsed or pos lt 0) then begin
message, 'Position value out of range'
endif
if (pos ne self.nUsed - 1L) then begin
(*self.pData)[pos] = (*self.pData)[pos+1L:self.nUsed-1L]
endif
self.nUsed--
return
end
else : message, 'Position must be a scalar or 1-element array'
endcase
if (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 = n_elements(elements)
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
(*self.pData)[position+nNew] = (*self.pData)[position:self.nUsed-1L]
(*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
end
function mgcoarraylist::init, type=type, example=example, block_size=blockSize
compile_opt strictarr
on_error, 2
self.nUsed = 0L
self.type = n_elements(type) eq 0 ? size(example, /type) : type
if (self.type eq 0) then message, 'List type is undefined'
self.blockSize = n_elements(blockSize) eq 0 ? 1000L : blockSize
if (self.blockSize le 0) then message, 'List size must be positive'
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, /nozero)
endelse
self.pData = ptr_new(data, /no_copy)
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