void stress_test_array(int amt) { array arr; /* matey! */ gendata x; int i; arr = array_create(); assert(array_size(arr) == 0); printf("Adding %d items to an array...\n", amt); for (i = 0; i < amt; ++i) { x.num = i; arr = array_add(arr, x); assert(x.num == array_get_data(arr, (unsigned int)i).num); assert(array_size(arr) == (unsigned int)(i + 1)); } printf("Shrinking an array of %d items...\n", amt); for (i = amt - 1; i >= 0; --i) { assert(array_get_data(arr, (unsigned int)i).num == i); arr = array_remove(arr); assert(array_size(arr) == (unsigned int)i); } printf("Filling a pre-grown array of %d items...\n", amt); array_grow(arr, amt); assert(array_size(arr) == (unsigned int)amt); for (i = 0; i < amt; ++i) { x.num = i; arr = array_set_data(arr, (unsigned int)i, x); assert(x.num == array_get_data(arr, (unsigned int)i).num); } printf("Shrinking an array of %d items...\n", amt); for (i = amt - 1; i >= 0; --i) { assert(array_get_data(arr, (unsigned int)i).num == i); arr = array_shrink(arr, 1); assert(array_size(arr) == (unsigned int)i); /* Compactise at funky points */ if ((i % COMPACTISE_MODULO) == 0) { arr = array_compact(arr); /* Compactising should not change size */ assert(array_size(arr) == (unsigned int)i); } } array_destroy(arr, NULL); }
string stack_pop_string(object store, string name) { // error checking if (!array_exists(store,name)) return ""; int size=array_get_int(store,name,0); if (size==0) return ""; else { string popped=array_get_string(store,name,size); array_shrink(store,name,size); array_set_int(store,name,0,size-1); return popped; } }
object stack_pop_object(object store, string name) { /* No error checking :( // error checking if (!array_exists(store,name)) return SDL_ERROR_DOES_NOT_EXIST; */ int size=array_get_int(store,name,0); /* no error checking :( if (size==0) return ""; */ object popped=array_get_object(store,name,size); array_shrink(store,name,size); array_set_int(store,name,0,size-1); return popped; }
static void shrink(Process *p, Eterm* ret) { unsigned int range = HASH_RANGE(p->dictionary); unsigned int steps = (range*3) / 10; Eterm hi, lo, tmp; unsigned int i; Eterm *hp; #ifdef DEBUG Eterm *hp_limit; #endif if (range - steps < INITIAL_SIZE) { steps = range - INITIAL_SIZE; } for (i = 0; i < steps; ++i) { ProcDict *pd = p->dictionary; if (pd->splitPosition == 0) { pd->homeSize /= 2; pd->splitPosition = pd->homeSize; } --(pd->splitPosition); hi = ARRAY_GET(pd, (pd->splitPosition + pd->homeSize)); lo = ARRAY_GET(pd, pd->splitPosition); if (hi != NIL) { if (lo == NIL) { array_put(&(p->dictionary), pd->splitPosition, hi); } else { int needed = 4; if (is_list(hi) && is_list(lo)) { needed = 2*erts_list_length(hi); } if (HeapWordsLeft(p) < needed) { BUMP_REDS(p, erts_garbage_collect(p, needed, ret, 1)); hi = pd->data[(pd->splitPosition + pd->homeSize)]; lo = pd->data[pd->splitPosition]; } #ifdef DEBUG hp_limit = p->htop + needed; #endif if (is_tuple(lo)) { if (is_tuple(hi)) { hp = HeapOnlyAlloc(p, 4); tmp = CONS(hp, hi, NIL); hp += 2; array_put(&(p->dictionary), pd->splitPosition, CONS(hp,lo,tmp)); hp += 2; ASSERT(hp <= hp_limit); } else { /* hi is a list */ hp = HeapOnlyAlloc(p, 2); array_put(&(p->dictionary), pd->splitPosition, CONS(hp, lo, hi)); hp += 2; ASSERT(hp <= hp_limit); } } else { /* lo is a list */ if (is_tuple(hi)) { hp = HeapOnlyAlloc(p, 2); array_put(&(p->dictionary), pd->splitPosition, CONS(hp, hi, lo)); hp += 2; ASSERT(hp <= hp_limit); } else { /* Two lists */ hp = HeapOnlyAlloc(p, needed); for (tmp = hi; tmp != NIL; tmp = TCDR(tmp)) { lo = CONS(hp, TCAR(tmp), lo); hp += 2; } ASSERT(hp <= hp_limit); array_put(&(p->dictionary), pd->splitPosition, lo); } } } } array_put(&(p->dictionary), (pd->splitPosition + pd->homeSize), NIL); } if (HASH_RANGE(p->dictionary) <= (p->dictionary->size / 4)) { array_shrink(&(p->dictionary), (HASH_RANGE(p->dictionary) * 3) / 2); } }
/** * @brief Loads the tech information. */ int tech_load (void) { int i, ret, s; uint32_t bufsize; char *buf, *data; xmlNodePtr node, parent; xmlDocPtr doc; tech_group_t *tech; /* Load the data. */ data = ndata_read( TECH_DATA, &bufsize ); if (data == NULL) return -1; /* Load the document. */ doc = xmlParseMemory( data, bufsize ); if (doc == NULL) { WARN("'%s' is not a valid XML file.", TECH_DATA); return -1; } /* Load root element. */ parent = doc->xmlChildrenNode; if (!xml_isNode(parent,XML_TECH_ID)) { WARN("Malformed "TECH_DATA" file: missing root element '"XML_TECH_ID"'"); return -1; } /* Get first node. */ node = parent->xmlChildrenNode; if (node == NULL) { WARN("Malformed "TECH_DATA" file: does not contain elements"); return -1; } /* Create the array. */ tech_groups = array_create( tech_group_t ); /* First pass create the groups - needed to reference them later. */ ret = 0; tech = NULL; do { xml_onlyNodes(node); /* Must match tag. */ if (!xml_isNode(node, XML_TECH_TAG)) { WARN("'"XML_TECH_ID"' has unknown node '%s'.", node->name); continue; } if (ret==0) /* Write over failures. */ tech = &array_grow( &tech_groups ); ret = tech_parseNode( tech, node ); } while (xml_nextNode(node)); array_shrink( &tech_groups ); /* Now we load the data. */ node = parent->xmlChildrenNode; s = array_size( tech_groups ); do { /* Must match tag. */ if (!xml_isNode(node, XML_TECH_TAG)) continue; /* Must avoid warning by checking explicit NULL. */ xmlr_attr( node, "name", buf ); if (buf == NULL) continue; /* Load next tech. */ for (i=0; i<s; i++) { tech = &tech_groups[i]; if (strcmp(tech->name, buf)==0) tech_parseNodeData( tech, node ); } /* Free memory. */ free(buf); } while (xml_nextNode(node)); /* Info. */ DEBUG("Loaded %d tech group%s", s, (s == 1) ? "" : "s" ); /* Free memory. */ free(data); xmlFreeDoc(doc); return 0; }
result_t motionmaskplayer_load(motionmaskplayer_t *player, const char *filename) { result_t err; FILE *f = NULL; stream_t *s = NULL; uint32_t signature; frame_t *frames = NULL; int start; int i; int totalheights; mmoffset_t *offsets = NULL; mmdata_t *data = NULL; int dataused; int dataallocated; if (player->flags & player_FLAGS_LOADED) { free(player->frames); free(player->offsets); free(player->data); player->flags &= ~player_FLAGS_LOADED; } f = fopen(filename, "rb"); if (f == NULL) { err = result_FILE_NOT_FOUND; goto failure; } err = stream_stdio_create(f, 1024, &s); if (err) goto failure; f = NULL; /* 'f' is now owned by the stream code */ /* read file header */ err = unpackfromstream(s, format_HEADER_SIZE, "<i2hii", &signature, &player->width, &player->height, &player->nframes); if (err) goto failure; if (signature != format_ID) { logf_fatal("header has bad signature"); err = result_MMPLAYER_BAD_SIGNATURE; goto failure; } logf_info("header: width x height = %d x %d, nframes = %d", player->width, player->height, player->nframes); if (player->width <= 0 || player->height <= 0 || player->nframes <= 0) { logf_fatal("header has invalid dimensions"); err = result_MMPLAYER_INVALID_DIMENSIONS; goto failure; } /* read frames */ frames = malloc(player->nframes * sizeof(*frames)); if (frames == NULL) goto oom; start = 0; for (i = 0; i < player->nframes; i++) { frame_t *frame = &frames[i]; err = unpackfromstream(s, format_FRAME_SIZE, "<4hiC", &frame->width, &frame->height, &frame->x, &frame->y, &frame->source); if (err) goto failure; logf_info("frame %d: width x height = %d x %d, x,y = %d,%d, source = %x", i, frame->width, frame->height, frame->x, frame->y, frame->source); if (frame->width <= 0 || frame->height <= 0) { err = result_MMPLAYER_INVALID_FRAME_DIMENSIONS; goto failure; } // FIXME: Expand checks for x,y and source fields. frame->start = start; start += player->height; } totalheights = start; /* unpack offsets. we'll need to work over them again later. */ offsets = malloc(totalheights * sizeof(*offsets)); if (offsets == NULL) goto oom; { int consumedoffsets; for (i = 0; i < totalheights; i += consumedoffsets) { stream_size_t availablebytes; stream_size_t availableoffsets; int32_t maxavailableoffsets; availablebytes = stream_remaining_need_and_fill(s, 2); if (availablebytes == stream_EOF || availablebytes < 2) { err = result_MMPLAYER_TRUNCATED_INPUT; goto failure; } availableoffsets = availablebytes / 2; /* read up to the limit of the size of data we're anticipating */ maxavailableoffsets = availableoffsets > INT32_MAX ? INT32_MAX : (int32_t) availableoffsets; consumedoffsets = MIN(totalheights - i, maxavailableoffsets); if (consumedoffsets < 1) { err = result_MMPLAYER_TRUNCATED_INPUT; goto failure; } s->buf += unpack(s->buf, "<*hP", consumedoffsets, offsets + i); } } /* read data chunk */ data = NULL; dataused = 0; dataallocated = 0; for (;;) { stream_size_t remaining; // stream returns a ptrdiff_t actually remaining = stream_remaining_and_fill(s); if (remaining == stream_EOF) break; /* EOF (we assume) */ if (array_grow((void **) &data, sizeof(*data), dataused, &dataallocated, (int) remaining, 1)) goto oom; memcpy(data + dataused, s->buf, remaining); dataused += remaining; s->buf += remaining; } if (data == NULL) { err = result_MMPLAYER_TRUNCATED_INPUT; goto failure; } if (array_shrink((void **) &data, sizeof(*data), dataused, &dataallocated)) goto oom; /* fix up offsets table now we know where 'data' lives */ for (i = 0; i < totalheights; i++) { mmoffset_t o; o = offsets[i]; /* verify the offsets (since a truncated data chunk cannot be detected * earlier on) */ if ((intptr_t) o >= dataused) { logf_fatal("offset %d out of range\n", i); err = result_MMPLAYER_BAD_OFFSET; goto failure; } offsets[i] = data + (ptrdiff_t) o; } stream_destroy(s); player->frames = frames; player->offsets = offsets; player->data = data; player->ndata = dataused; player->flags |= player_FLAGS_LOADED; return result_OK; oom: err = result_OOM; failure: if (f) fclose(f); stream_destroy(s); free(frames); free(offsets); free(data); return err; }
int main(int argc, const char* argv[]) { array_t(int) a = NULL; test(array_size(a) == 0); test(array_capacity(a) == 0); array_alloc(a, 0, destructed_element_count_destructor); test(array_size(a) == 0); test(array_capacity(a) == 0); array_append(a, 1); test(array_size(a) == 1); test(array_capacity(a) >= 1); test(a[0] == 1); array_append(a, 2); test(array_size(a) == 2); test(array_capacity(a) >= 2); test(a[0] == 1); test(a[1] == 2); array_append(a, 3); test(array_size(a) == 3); test(array_capacity(a) >= 3); test(a[0] == 1); test(a[1] == 2); test(a[2] == 3); array_insert(a, 0, 0); test(array_size(a) == 4); test(array_capacity(a) >= 4); test(a[0] == 0); test(a[1] == 1); test(a[2] == 2); test(a[3] == 3); array_reserve(a, 16); test(array_size(a) == 4); test(array_capacity(a) == 16); test(a[0] == 0); test(a[1] == 1); test(a[2] == 2); test(a[3] == 3); array_shrink(a); test(array_size(a) == 4); test(array_capacity(a) == 4); test(a[0] == 0); test(a[1] == 1); test(a[2] == 2); test(a[3] == 3); array_remove(a, 0); test(array_size(a) == 3); test(array_capacity(a) == 4); test(a[0] == 1); test(a[1] == 2); test(a[2] == 3); test(destructed_element_count == 1); destructed_element_count = 0; array_remove_unordered(a,0); test(array_size(a) == 2); test(array_capacity(a) == 4); test(a[0] == 3); test(a[1] == 2); test(destructed_element_count == 1); destructed_element_count = 0; array_clear(a); test(array_size(a) == 0); test(array_capacity(a) >= 0); test(destructed_element_count == 2); destructed_element_count = 0; array_append(a, 0); array_append(a, 1); array_append(a, 2); test(array_size(a) == 3); test(array_capacity(a) >= 3); test(destructed_element_count == 0); array_free(a); test(a == NULL); test(array_size(a) == 0); test(array_capacity(a) == 0); test(destructed_element_count == 3); destructed_element_count = 0; enum { TEST_LENGTH = 1024 }; array_alloc(a, 0, destructed_element_count_destructor); for (int i = 0; i < TEST_LENGTH; ++i) { array_append(a, i); test(a[i] == i); } test(array_size(a) == TEST_LENGTH); test(array_capacity(a) >= TEST_LENGTH); for (int i = 0; i < TEST_LENGTH; ++i) { test(a[i] == i); } { int i = 0; const int* const end = array_end(a); for (int* itr = array_begin(a); itr < end; ++itr) { test(*itr == i++); } } { int i = 0; while (array_size(a)) { test(a[0] == i++); array_remove(a,0); } test(array_size(a) == 0); test(array_capacity(a) >= TEST_LENGTH); test(destructed_element_count == TEST_LENGTH); destructed_element_count = 0; } array_free(a); test(a == NULL); test(array_size(a) == 0); test(array_capacity(a) == 0); array_alloc(a, 0, destructed_element_count_destructor); for (int i = 0; i < TEST_LENGTH; ++i) { array_insert(a, 0, i); } test(array_size(a) == TEST_LENGTH); test(array_capacity(a) >= TEST_LENGTH); for (int i = 0; i < TEST_LENGTH; ++i) { test(a[i] == (TEST_LENGTH - 1) - i); } array_free(a); test(a == NULL); test(array_size(a) == 0); test(array_capacity(a) == 0); puts("array tests passed"); }