/*------------------------------------------------------------------------ Procedure: Add ID:1 Purpose: Adds a string to the string collection. Input: The collection and the string to be added to it Output: Number of items in the collection or <= 0 if error Errors: ------------------------------------------------------------------------*/ static int Add(ElementType *SC,const CHAR_TYPE *newval) { if (SC == NULL) { return NullPtrError("Add"); } if (SC->Flags & CONTAINER_READONLY) return ReadOnlyError(SC,"Add"); if ((SC->count+1) >= SC->capacity) { int r = Resize(SC); if (r <= 0) return r; } if (newval) { SC->contents[SC->count] = DuplicateString(SC,newval,"Add"); if (SC->contents[SC->count] == NULL) { return 0; } } else SC->contents[SC->count] = NULL; SC->timestamp++; ++SC->count; return 1; }
static int SetCapacity(ElementType *SC,size_t newCapacity) { CHAR_TYPE **newContents; if (SC == NULL) { return NullPtrError("SetCapacity"); } if (SC->Flags & CONTAINER_READONLY) { return ReadOnlyError(SC,"SetCapacity"); } newContents = SC->Allocator->malloc(newCapacity*sizeof(void *)); if (newContents == NULL) { return NoMemoryError(SC,"SetCapacity"); } memset(SC->contents,0,sizeof(void *)*newCapacity); SC->capacity = newCapacity; if (newCapacity > SC->count) newCapacity = SC->count; else if (newCapacity < SC->count) SC->count = newCapacity; if (newCapacity > 0) { memcpy(newContents,SC->contents,newCapacity*sizeof(void *)); } SC->Allocator->free(SC->contents); SC->contents = newContents; SC->timestamp++; return 1; }
static int EraseInternal(ElementType *SC,const CHAR_TYPE *str,int all) { size_t i; int result = CONTAINER_ERROR_NOTFOUND; if (SC == NULL) { return NullPtrError("Erase"); } if (str == NULL) { return BadArgError(SC,"Erase"); } if (SC->Flags & CONTAINER_READONLY) return ReadOnlyError(SC,"Erase"); for (i=0; i<SC->count;i++) { if (!SC->strcompare((const void **)&SC->contents[i], (const void **)&str,SC->StringCompareContext)) { if (SC->DestructorFn) SC->DestructorFn(SC->contents[i]); SC->Allocator->free(SC->contents[i]); if (i < (SC->count-1)) memmove(SC->contents+i,SC->contents+i+1,(SC->count-i)*sizeof(char *)); --SC->count; SC->contents[SC->count]=NULL; SC->timestamp++; result = 1; if (all == 0) break; i--; } } return result; }
static int Reverse(ElementType *SC) { CHAR_TYPE **p, **q, *t; if (SC == NULL) { return NullPtrError("Reverse"); } if (SC->Flags & CONTAINER_READONLY) { return ReadOnlyError(SC,"Reverse"); } if (SC->count < 2) return 1; p = SC->contents; q = &p[SC->count-1]; while ( p < q ) { t = *p; *p = *q; *q = t; p++; q--; } SC->timestamp++; return 1; }
static int Append(ElementType *SC1, ElementType *SC2) { if (SC1 == NULL || SC2 == NULL) { return NullPtrError("Append"); } if (SC1->Flags & CONTAINER_READONLY) { return ReadOnlyError(SC1,"Append"); } return AddRange(SC1,SC2->count,(const CHAR_TYPE **)SC2->contents); }
static int InsertIn(ElementType *source, size_t idx, ElementType *newData) { size_t newCount,i,j,siz; CHAR_TYPE **p,**oldcontents; if (source == NULL || newData == NULL) { return NullPtrError("InsertIn"); } if (source->Flags & CONTAINER_READONLY) return ReadOnlyError(source,"InsertIn"); if (idx > source->count) { return IndexError(source,idx,"InsertIn"); } newCount = source->count + newData->count; if (newData->count == 0) return 1; if (newCount == 0) return 1; if (newCount >= (source->capacity-1)) { int r = ResizeTo(source,1+newCount+newCount/4); if (r <= 0) return r; } p = source->contents; siz = source->capacity*sizeof(CHAR_TYPE *); oldcontents = source->Allocator->malloc(siz); if (oldcontents == NULL) { return NoMemoryError(source,"InsertIn"); } memset(oldcontents,0,siz); memcpy(oldcontents,p,sizeof(char *)*source->count); if (idx < source->count) { memmove(p+(idx+newData->count), p+idx, (source->count-idx)*sizeof(char *)); } for (i=idx,j=0; i<idx+newData->count;i++,j++) { source->contents[i] = DuplicateString(newData,newData->contents[j],"InsertIn"); if (source->contents[i] == NULL) { source->Allocator->free(source->contents); source->contents = oldcontents; return NoMemoryError(source,"InsertIn"); } } source->Allocator->free(oldcontents); source->timestamp++; source->count = newCount; return 1; }
void Variable::verifyWritable(Value const &attemptedNewValue) { if(d->mode & ReadOnly) { if(d->value && typeid(*d->value) == typeid(attemptedNewValue) && !d->value->compare(attemptedNewValue)) { // This is ok: the value doesn't change. return; } /// @throw ReadOnlyError The variable is in read-only mode. throw ReadOnlyError("Variable::verifyWritable", "Variable '" + d->name + "' is in read-only mode"); } }
static CHAR_TYPE *GetElement(const ElementType *SC,size_t idx) { if (SC == NULL) { NullPtrError("GetElement"); return NULL; } if (SC->Flags & CONTAINER_READONLY) { ReadOnlyError(SC,"GetElement"); return NULL; } if (idx >=SC->count) { IndexError(SC,idx,"GetElement"); return NULL; } return SC->contents[idx]; }
static int Sort(ElementType *SC) { CompareInfo ci; ci.ExtraArgs = NULL; ci.ContainerLeft = SC; ci.ContainerRight = NULL; if (SC == NULL) { return NullPtrError("Sort"); } if (SC->Flags & CONTAINER_READONLY) { return ReadOnlyError(SC,"Sort"); } qsortEx(SC->contents,SC->count,sizeof(char *),(CompareFunction)SC->strcompare,&ci); SC->timestamp++; return 1; }
static int Clear(ElementType *SC) { size_t i; if (SC == NULL) { return NullPtrError("Clear"); } if (SC->Flags & CONTAINER_READONLY) return ReadOnlyError(SC,"Clear"); for (i=0; i<SC->count;i++) { if (SC->DestructorFn) SC->DestructorFn(SC->contents[i]); SC->Allocator->free(SC->contents[i]); SC->contents[i] = NULL; } SC->count = 0; SC->timestamp=0; SC->Flags=0; return 1; }
static int InsertAt(ElementType *SC,size_t idx,const CHAR_TYPE *newval) { CHAR_TYPE *p; if (SC == NULL) { return NullPtrError("InsertAt"); } if (newval == NULL) { return BadArgError(SC,"InsertAt"); } if (SC->Flags & CONTAINER_READONLY) { return ReadOnlyError(SC,"InsertAt"); } if (idx >= SC->count) { return IndexError(SC,idx,"InsertAt"); } if ((SC->count+1) >= SC->capacity) { int r = Resize(SC); if (r <= 0) return r; } p = DuplicateString(SC,newval,"InsertAt"); if (p == NULL) { return NoMemoryError(SC,"InsertAt"); } if (idx == 0) { if (SC->count > 0) memmove(SC->contents+1,SC->contents,SC->count*sizeof(CHAR_TYPE *)); SC->contents[0] = p; } else if (idx == SC->count) { SC->contents[idx] = p; } else if (idx < SC->count) { memmove(SC->contents+idx+1,SC->contents+idx,(SC->count-idx+1)*sizeof(CHAR_TYPE *)); SC->contents[idx] = p; } SC->timestamp++; ++SC->count; return 1; }
static int PushBack(ElementType *SC,const CHAR_TYPE *str) { CHAR_TYPE *r; if (SC == NULL) return NullPtrError("PushBack"); if (SC->Flags&CONTAINER_READONLY) { return ReadOnlyError(SC,"PushBack"); } if (SC->count >= SC->capacity-1) { int res = Resize(SC); if (res <= 0) return res; } r = DuplicateString(SC,str,"Push"); if (r == NULL) return 0; SC->contents[SC->count++] = r; SC->timestamp++; return 1; }
/* [email protected] (gerome) proposed calling DuplicateString. Good suggestion */ static int ReplaceAt(ElementType *SC,size_t idx,CHAR_TYPE *newval) { CHAR_TYPE *r; if (SC == NULL) { return NullPtrError("ReplaceAt"); } if (SC->Flags & CONTAINER_READONLY) { return ReadOnlyError(SC,"ReplaceAt"); } if (idx >= SC->count) { return IndexError(SC,idx,"ReplaceAt"); } SC->Allocator->free(SC->contents[idx]); r = DuplicateString(SC,newval,(char *)"ReplaceAt"); if (r == NULL) { return NoMemoryError(SC,"ReplaceAt"); } SC->contents[idx] = r; SC->timestamp++; return 1; }
static int Finalize(ElementType *SC) { size_t i; if (SC == NULL) { return CONTAINER_ERROR_BADARG; } if (SC->Flags & CONTAINER_READONLY) { return ReadOnlyError(SC,"Finalize"); } for (i=0; i<SC->count;i++) { if (SC->DestructorFn) SC->DestructorFn(SC->contents[i]); SC->Allocator->free(SC->contents[i]); } SC->Allocator->free(SC->contents); if (SC->VTable != &INTERFACE_OBJECT) SC->Allocator->free(SC->VTable); SC->Allocator->free(SC); return 1; }
static int RemoveAt(ElementType *SC,size_t idx) { if (SC == NULL) { return NullPtrError("RemoveAt"); } if (idx >= SC->count ) return IndexError(SC,idx,"RemoveAt"); if (SC->Flags & CONTAINER_READONLY) return ReadOnlyError(SC,"RemoveAt"); /* Test for remove of an empty collection */ if (SC->count == 0) return 0; if (SC->DestructorFn) SC->DestructorFn(SC->contents[idx]); SC->Allocator->free(SC->contents[idx]); if (idx < (SC->count-1)) { memmove(SC->contents+idx,SC->contents+idx+1,(SC->count-idx)*sizeof(char *)); } SC->contents[SC->count-1]=NULL; SC->timestamp++; --SC->count; return 1; }
static int AddRange(ElementType *SC,size_t n, const CHAR_TYPE **data) { size_t newcapacity; CHAR_TYPE **p; if (n == 0) return 1; if (SC == NULL) { return NullPtrError("AddRange"); } if (data == NULL) { return BadArgError(SC,"AddRange"); } if (SC->Flags & CONTAINER_READONLY) { return ReadOnlyError(SC,"AddRange"); } newcapacity = SC->count+n; if (newcapacity >= SC->capacity-1) { CHAR_TYPE **newcontents; newcapacity += SC->count/4; newcontents = SC->Allocator->realloc(SC->contents,newcapacity*sizeof(void *)); if (newcontents == NULL) { return NoMemoryError(SC,"AddRange"); } SC->capacity = newcapacity; SC->contents = newcontents; } p = SC->contents; p += SC->count; memcpy(p,data,n*sizeof(void *)); SC->count += n; SC->timestamp++; return 1; }