#include "Col.ph" #ifdef __GNUG__ #pragma implementation #endif #include "ObjArray.h" #include "ContainerTypes.h" #include "Class.h" #include "Error.h" #include "Math.h" #include "ET_stdlib.h" const char *cOutOfBoundsError = "index %d out of bounds (size: %d, this: 0x%08x)", *cMethodName = "operator[]"; //---- ObjArray ---------------------------------------------------------------- NewMetaImpl(ObjArray,SeqCollection, (T(lb), TVP(cont,size))); ObjArray::ObjArray(int s, int lowerBound) { if (s <= 0) s= 10; cont= new Object*[size= s]; lb= lowerBound; } ObjArray::~ObjArray() { SafeDelete(cont); } void ObjArray::InitNew() { cont= new Object*[cContainerInitCap]; lb= 0; } void ObjArray::FreeAll() { register int i; for (i= 0; i < size; i++) { if (cont[i]) { cont[i]->FreeAll(); SafeDelete(cont[i]); } } size= 0; } Object *ObjArray::RemoveAt(int i) { if (!BoundsOk("RemoveAt", i)) return 0; Object *t= cont[i-lb]; cont[i-lb]= 0; Changed(); return t; } Object *ObjArray::Remove(Object *a) { register int i; register Object *op; for (i= 0; i < size; i++) { op= cont[i]; if (op && op->IsEqual(a)) { cont[i]= 0; Changed(); return op; } } return 0; } Object *ObjArray::RemovePtr(Object *a) { register int i; register Object *op; for (i= 0; i < size; i++) { op= cont[i]; if (op && op == a) { cont[i]= 0; Changed(); return op; } } return 0; } void ObjArray::Expand(int newSize) { if (newSize < 0) { Error ("Expand", "newSize < 0"); return; } if (newSize == size) return; if (newSize <= size) { // if the array is shrinked check whether there are nonempty entries for (int j= newSize; j < size; j++) if (cont[j]) { Error ("Expand", "expand would cut off nonempty entries at %d", j); return; } } cont= (Object**) Storage::ReAlloc(cont, newSize * sizeof(Object*)); if (newSize > size) // clear slots for (int i= size; i < newSize; i++) cont[i]= 0; size= newSize; } Iterator *ObjArray::MakeIterator(bool dir, void *placement) { if (dir == cIterForward) return new(placement) ObjArrayIter(this); Error("MakeIterator", "no reversed iterator"); // ?? why that return 0; } Object *ObjArray::AtPut(int i, Object *ob) { if (!BoundsOk("AtPut", i)) return 0; Object *t= cont[i-lb]; cont[i-lb]= ob; Changed(); return t; } void ObjArray::AtPutAndExpand(int i,Object *op) { if (i < lb) { Error ("AtPutAndExpand", "out of bounds at %d in %x", i, this); return; } if (i-lb >= size) Expand (Math::Max(i, GrowBy(size))); cont[i-lb]= op; Changed(); } Object *ObjArray::Add(Object *op) { register int i; if (cont == 0) cont= new Object*[size= 10]; for (i= 0; i < size; i++) if (cont[i] == 0) break; if (i >= size) Expand(GrowBy(size)); cont[i]= op; Changed(); return 0; } int ObjArray::Index(Object *op) { register int i, fi= -1; if (cont == 0) cont= new Object*[size= 10]; for (i= 0; i < size; i++) { if (cont[i] == op) return i+lb; if (cont[i] == 0 && fi == -1) fi= i; } if (fi == -1) { Expand(GrowBy(size)); fi= i; } cont[fi]= op; return fi+lb; } int ObjArray::IndexOf(Object *ob) { register int i; for (i= 0; i < size; i++) if (ob && ob->IsEqual(cont[i])) return i+lb; return -1; } int ObjArray::IndexOfPtr(Object *ob) { register int i; for (i= 0; i < size; i++) if (ob == cont[i]) return i+lb; return -1; } Object *ObjArray::At(int i) { if (!BoundsOk("At", i)) return 0; return cont[i-lb]; } int ObjArray::Compare(Object*) { MayNotUse ("Compare"); return -2; } bool ObjArray::IsEqual(Object *ob) { if (!ob->IsKindOf(ObjArray)) return FALSE; ObjArray *t= (ObjArray*) ob; if (t->size != size || t->lb != lb) return FALSE; for (int i= 0; i < Size(); i++) { if (cont[i] == 0 && t->cont[i] == 0) continue; if (cont[i] == 0 || t->cont[i] == 0) break; if (!cont[i]->IsEqual(t->cont[i])) break; } return i == size; } OStream& ObjArray::PrintOn(OStream &s) { Object::PrintOn(s); // supress Collection::PrintOn s << Size() SP; for (int i= 0; i < Size(); i++) s << cont[i] SP; return s NL; } IStream& ObjArray::ReadFrom(IStream &s) { Object::ReadFrom(s); delete cont; s >> size; cont= new Object*[size]; for (int i= 0; i < size; i++) s >> cont[i]; return s; } unsigned long ObjArray::Hash () { register u_long hash= 0; for (int i= 0; i < size; i++) if (cont[i]) hash ^= cont[i]->Hash(); return hash; } void ObjArray::Sort(int upto) { ::qsort(cont, Math::Min(size, upto-lb), sizeof(Object*), &::ppCompare); } int ObjArray::BinarySearch(Object *op, int upto) { register int base, position, last, result; register Object *op2; if (op == 0) return -1; base= 0; last= Math::Min(size, upto-lb) - 1; while (last >= base) { position= (base+last) / 2; op2= cont[position]; if ((op2 == 0) || (result= op->Compare(op2)) == 0) return position + lb; if (result < 0) last= position-1; else base= position+1; } return -1; } //---- ObjArrayIter ------------------------------------------------------------ ObjArrayIter::ObjArrayIter(ObjArray *oa) { cs= oa; ce= 0; } ObjArrayIter::~ObjArrayIter() { } void ObjArrayIter::Reset() { ce= 0; } Object *ObjArrayIter::operator()() { for (;ce < cs->Size() && cs->cont[ce] == 0; ce++) ; if (ce < cs->Size()) return cs->cont[ce++]; return 0; } bool ObjArrayIter::Filter(Object*) { return TRUE; }