/*1* This file is the collected implementation of libdyn.a, the C2* Dynamic Object library. It contains everything.3*4* There are no restrictions on this code; however, if you make any5* changes, I request that you document them so that I do not get6* credit or blame for your modifications.7*8* Written by Barr3y Jaspan, Student Information Processing Board (SIPB)9* and MIT-Project Athena, 1989.10*11* 2002-07-17 Collected full implementation into one source file for12* easy inclusion into the one library still dependent on13* libdyn. Assume memmove. Old ChangeLog appended.14*/1516#include <stdio.h>17#include <stdlib.h>18#include <string.h>1920#include "dynP.h"212223/* old dyn_append.c */24/*25* This file is part of libdyn.a, the C Dynamic Object library. It26* contains the source code for the function DynAppend().27*/2829/*30* Made obsolete by DynInsert, now just a convenience function.31*/32int33DynAppend(DynObjectP obj, DynPtr els, int num)34{35return DynInsert(obj, DynSize(obj), els, num);36}373839/* old dyn_create.c */40/*41* This file is part of libdyn.a, the C Dynamic Object library. It42* contains the source code for the functions DynCreate() and43* DynDestroy().44*/4546#ifndef DEFAULT_INC47#define DEFAULT_INC 10048#endif4950static int default_increment = DEFAULT_INC;5152DynObjectP53DynCreate(int el_size, int inc)54{55DynObjectP obj;5657obj = (DynObjectP) malloc(sizeof(DynObjectRecP));58if (obj == NULL)59return NULL;6061obj->array = (DynPtr) malloc(1);62if (obj->array == NULL) {63free(obj);64return NULL;65}66obj->array[0] = '\0';6768obj->el_size = el_size;69obj->num_el = obj->size = 0;70obj->debug = obj->paranoid = 0;71obj->inc = (inc) ? inc : default_increment;72obj->initzero = 0;7374return obj;75}7677DynObjectP78DynCopy(DynObjectP obj)79{80DynObjectP obj1;8182obj1 = (DynObjectP) malloc(sizeof(DynObjectRecP));83if (obj1 == NULL)84return NULL;8586obj1->el_size = obj->el_size;87obj1->num_el = obj->num_el;88obj1->size = obj->size;89obj1->inc = obj->inc;90obj1->debug = obj->debug;91obj1->paranoid = obj->paranoid;92obj1->initzero = obj->initzero;93obj1->array = (char *) malloc((size_t) (obj1->el_size * obj1->size));94if (obj1->array == NULL) {95free(obj1);96return NULL;97}98memcpy(obj1->array, obj->array,99(size_t) (obj1->el_size * obj1->size));100101return obj1;102}103104int105DynDestroy(/*@only@*/DynObjectP obj)106{107if (obj->paranoid) {108if (obj->debug)109fprintf(stderr, "dyn: destroy: zeroing %d bytes from %p.\n",110obj->el_size * obj->size, obj->array);111memset(obj->array, 0, (size_t) (obj->el_size * obj->size));112}113free(obj->array);114free(obj);115return DYN_OK;116}117118int119DynRelease(DynObjectP obj)120{121if (obj->debug)122fprintf(stderr, "dyn: release: freeing object structure.\n");123free(obj);124return DYN_OK;125}126127128/* old dyn_debug.c */129/*130* This file is part of libdyn.a, the C Dynamic Object library. It131* contains the source code for the function DynDebug().132*/133134int135DynDebug(DynObjectP obj, int state)136{137obj->debug = state;138139fprintf(stderr, "dyn: debug: Debug state set to %d.\n", state);140return DYN_OK;141}142143144/* old dyn_delete.c */145/*146* This file is part of libdyn.a, the C Dynamic Object library. It147* contains the source code for the function DynDelete().148*/149150/*151* Checkers! Get away from that "hard disk erase" button!152* (Stupid dog. He almost did it to me again ...)153*/154int155DynDelete(DynObjectP obj, int idx)156{157if (idx < 0) {158if (obj->debug)159fprintf(stderr, "dyn: delete: bad index %d\n", idx);160return DYN_BADINDEX;161}162163if (idx >= obj->num_el) {164if (obj->debug)165fprintf(stderr, "dyn: delete: Highest index is %d.\n",166obj->num_el);167return DYN_BADINDEX;168}169170if (idx == obj->num_el-1) {171if (obj->paranoid) {172if (obj->debug)173fprintf(stderr, "dyn: delete: last element, zeroing.\n");174memset(obj->array + idx*obj->el_size, 0, (size_t) obj->el_size);175}176else {177if (obj->debug)178fprintf(stderr, "dyn: delete: last element, punting.\n");179}180}181else {182if (obj->debug)183fprintf(stderr,184"dyn: delete: copying %d bytes from %p + %d to + %d.\n",185obj->el_size*(obj->num_el - idx), obj->array,186(idx+1)*obj->el_size, idx*obj->el_size);187188memmove(obj->array + idx*obj->el_size,189obj->array + (idx+1)*obj->el_size,190(size_t) obj->el_size*(obj->num_el - idx));191if (obj->paranoid) {192if (obj->debug)193fprintf(stderr,194"dyn: delete: zeroing %d bytes from %p + %d\n",195obj->el_size, obj->array,196obj->el_size*(obj->num_el - 1));197memset(obj->array + obj->el_size*(obj->num_el - 1), 0,198(size_t) obj->el_size);199}200}201202--obj->num_el;203204if (obj->debug)205fprintf(stderr, "dyn: delete: done.\n");206207return DYN_OK;208}209210211/* old dyn_initzero.c */212/*213* This file is part of libdyn.a, the C Dynamic Object library. It214* contains the source code for the function DynInitZero().215*/216217int218DynInitzero(DynObjectP obj, int state)219{220obj->initzero = state;221222if (obj->debug)223fprintf(stderr, "dyn: initzero: initzero set to %d.\n", state);224return DYN_OK;225}226227228/* old dyn_insert.c */229/*230* This file is part of libdyn.a, the C Dynamic Object library. It231* contains the source code for the function DynInsert().232*/233234int235DynInsert(DynObjectP obj, int idx, void *els_in, int num)236{237DynPtr els = (DynPtr) els_in;238int ret;239240if (idx < 0 || idx > obj->num_el) {241if (obj->debug)242fprintf(stderr, "dyn: insert: index %d is not in [0,%d]\n",243idx, obj->num_el);244return DYN_BADINDEX;245}246247if (num < 1) {248if (obj->debug)249fprintf(stderr, "dyn: insert: cannot insert %d elements\n",250num);251return DYN_BADVALUE;252}253254if (obj->debug)255fprintf(stderr,"dyn: insert: Moving %d bytes from %p + %d to + %d\n",256(obj->num_el-idx)*obj->el_size, obj->array,257obj->el_size*idx, obj->el_size*(idx+num));258259if ((ret = _DynResize(obj, obj->num_el + num)) != DYN_OK)260return ret;261memmove(obj->array + obj->el_size*(idx + num),262obj->array + obj->el_size*idx,263(size_t) ((obj->num_el-idx)*obj->el_size));264265if (obj->debug)266fprintf(stderr, "dyn: insert: Copying %d bytes from %p to %p + %d\n",267obj->el_size*num, els, obj->array, obj->el_size*idx);268269memmove(obj->array + obj->el_size*idx, els, (size_t) (obj->el_size*num));270obj->num_el += num;271272if (obj->debug)273fprintf(stderr, "dyn: insert: done.\n");274275return DYN_OK;276}277278279/* old dyn_paranoid.c */280/*281* This file is part of libdyn.a, the C Dynamic Object library. It282* contains the source code for the function DynDebug().283*/284285int286DynParanoid(DynObjectP obj, int state)287{288obj->paranoid = state;289290if (obj->debug)291fprintf(stderr, "dyn: paranoid: Paranoia set to %d.\n", state);292return DYN_OK;293}294295296/* old dyn_put.c */297/*298* This file is part of libdyn.a, the C Dynamic Object library. It299* contains the source code for the functions DynGet() and DynAdd().300*/301302DynPtr303DynArray(DynObjectP obj)304{305if (obj->debug)306fprintf(stderr, "dyn: array: returning array pointer %p.\n",307obj->array);308309return obj->array;310}311312DynPtr313DynGet(DynObjectP obj, int num)314{315if (num < 0) {316if (obj->debug)317fprintf(stderr, "dyn: get: bad index %d\n", num);318return NULL;319}320321if (num >= obj->num_el) {322if (obj->debug)323fprintf(stderr, "dyn: get: highest element is %d.\n",324obj->num_el);325return NULL;326}327328if (obj->debug)329fprintf(stderr, "dyn: get: Returning address %p + %d.\n",330obj->array, obj->el_size*num);331332return (DynPtr) obj->array + obj->el_size*num;333}334335int DynAdd(DynObjectP obj, void *el)336{337int ret;338339ret = DynPut(obj, el, obj->num_el);340if (ret != DYN_OK)341return ret;342343++obj->num_el;344return ret;345}346347/*348* WARNING! There is a reason this function is not documented in the349* man page. If DynPut used to mutate already existing elements,350* everything will go fine. If it is used to add new elements351* directly, however, the state within the object (such as352* obj->num_el) will not be updated properly and many other functions353* in the library will lose. Have a nice day.354*/355int356DynPut(DynObjectP obj, void *el_in, int idx)357{358DynPtr el = (DynPtr) el_in;359int ret;360361if (obj->debug)362fprintf(stderr, "dyn: put: Writing %d bytes from %p to %p + %d\n",363obj->el_size, el, obj->array, idx*obj->el_size);364365if ((ret = _DynResize(obj, idx)) != DYN_OK)366return ret;367368memmove(obj->array + idx*obj->el_size, el, (size_t) obj->el_size);369370if (obj->debug)371fprintf(stderr, "dyn: put: done.\n");372373return DYN_OK;374}375376377/* old dyn_realloc.c */378/*379* This file is part of libdyn.a, the C Dynamic Object library. It380* contains the source code for the internal function _DynRealloc().381*/382383/*384* Resize the array so that element req exists.385*/386int387_DynResize(DynObjectP obj, int req)388{389int size;390391if (obj->size > req)392return DYN_OK;393else if (obj->inc > 0)394return _DynRealloc(obj, (req - obj->size) / obj->inc + 1);395else {396if (obj->size == 0)397size = -obj->inc;398else399size = obj->size;400401/*@-shiftsigned@*/402while (size <= req)403size <<= 1;404/*@=shiftsigned@*/405406return _DynRealloc(obj, size);407}408}409410/*411* Resize the array by num_incs units. If obj->inc is positive, this412* means make it obj->inc*num_incs elements larger. If obj->inc is413* negative, this means make the array num_incs elements long.414*415* Ideally, this function should not be called from outside the416* library. However, nothing will break if it is.417*/418int419_DynRealloc(DynObjectP obj, int num_incs)420{421DynPtr temp;422int new_size_in_bytes;423424if (obj->inc > 0)425new_size_in_bytes = obj->el_size*(obj->size + obj->inc*num_incs);426else427new_size_in_bytes = obj->el_size*num_incs;428429if (obj->debug)430fprintf(stderr,431"dyn: alloc: Increasing object by %d bytes (%d incs).\n",432new_size_in_bytes - obj->el_size*obj->size,433num_incs);434435temp = (DynPtr) realloc(obj->array, (size_t) new_size_in_bytes);436if (temp == NULL) {437if (obj->debug)438fprintf(stderr, "dyn: alloc: Out of memory.\n");439return DYN_NOMEM;440}441else {442obj->array = temp;443if (obj->inc > 0)444obj->size += obj->inc*num_incs;445else446obj->size = num_incs;447}448449if (obj->debug)450fprintf(stderr, "dyn: alloc: done.\n");451452return DYN_OK;453}454455456/* old dyn_size.c */457/*458* This file is part of libdyn.a, the C Dynamic Object library. It459* contains the source code for the function DynSize().460*/461462int463DynSize(DynObjectP obj)464{465if (obj->debug)466fprintf(stderr, "dyn: size: returning size %d.\n", obj->num_el);467468return obj->num_el;469}470471int472DynCapacity(DynObjectP obj)473{474if (obj->debug)475fprintf(stderr, "dyn: capacity: returning cap of %d.\n", obj->size);476477return obj->size;478}479480/* Old change log, as it relates to source code; build system stuff481discarded.4824832001-10-09 Ken Raeburn <[email protected]>484485* dyn.h, dynP.h: Make prototypes unconditional. Don't define486P().4874882001-04-25 Ezra Peisach <[email protected]>489490* dyn.h: Lclint annotate functions.491492* dyn_create.c (DynCreate): Do not assume that malloc(0) is valid493and returns a valid pointer. Fix memory leak if malloc fails.494495* dyn_realloc.c (_DynResize): Turn off warning of shifting a496signed variable.497498Thu Nov 9 15:31:31 2000 Ezra Peisach <[email protected]>499500* dyn_create.c (DynCopy): Arguments to memcpy were reversed. Found501while playing with lclint.5025032000-11-09 Ezra Peisach <[email protected]>504505* dyn_create.c, dyn_delete.c, dyn_insert.c, dyn_put.c,506dyn_realloc.c: Cast arguments to malloc(), realloc(), memmove() to507size_t.508509* dynP.h: Provide full prototypes for _DynRealloc() and _DynResize().510511* dyn.h: Add prototype for DynAppend.5125132000-06-29 Ezra Peisach <[email protected]>514515* dyn_insert.c, dyn_put.c: Include string.h for memmove prototype.5165172000-06-28 Ezra Peisach <[email protected]>518519* dyn_create.c, dyn_delete.c, dyn_insert.c, dyn_put.c: Use %p520format for displaying pointers.5215222000-06-26 Ezra Peisach <[email protected]>523524* dyn_realloc.c: Remove unused variable.525526Sat Dec 6 22:50:03 1997 Ezra Peisach <[email protected]>527528* dyn_delete.c: Include <string.h>529530Mon Jul 22 21:37:52 1996 Ezra Peisach <[email protected]>531532* dyn.h: If __STDC__ is not defined, generate prototypes implying533functions and not variables.534535Mon Jul 22 04:20:48 1996 Marc Horowitz <[email protected]>536537* dyn_insert.c (DynInsert): what used to be #ifdef POSIX, should538be #ifdef HAVE_MEMMOVE539*/540541542