2N/A/*
2N/A * This file is the collected implementation of libdyn.a, the C
2N/A * Dynamic Object library. It contains everything.
2N/A *
2N/A * There are no restrictions on this code; however, if you make any
2N/A * changes, I request that you document them so that I do not get
2N/A * credit or blame for your modifications.
2N/A *
2N/A * Written by Barr3y Jaspan, Student Information Processing Board (SIPB)
2N/A * and MIT-Project Athena, 1989.
2N/A *
2N/A * 2002-07-17 Collected full implementation into one source file for
2N/A * easy inclusion into the one library still dependent on
2N/A * libdyn. Assume memmove. Old ChangeLog appended.
2N/A */
2N/A
2N/A#include <stdio.h>
2N/A#include <stdlib.h>
2N/A#include <string.h>
2N/A
2N/A#include "dynP.h"
2N/A
2N/A
2N/A/* old dyn_append.c */
2N/A/*
2N/A * This file is part of libdyn.a, the C Dynamic Object library. It
2N/A * contains the source code for the function DynAppend().
2N/A */
2N/A
2N/A/*
2N/A * Made obsolete by DynInsert, now just a convenience function.
2N/A */
2N/Aint DynAppend(obj, els, num)
2N/A DynObjectP obj;
2N/A DynPtr els;
2N/A int num;
2N/A{
2N/A return DynInsert(obj, DynSize(obj), els, num);
2N/A}
2N/A
2N/A
2N/A/* old dyn_create.c */
2N/A/*
2N/A * This file is part of libdyn.a, the C Dynamic Object library. It
2N/A * contains the source code for the functions DynCreate() and
2N/A * DynDestroy().
2N/A */
2N/A
2N/A#ifndef DEFAULT_INC
2N/A#define DEFAULT_INC 100
2N/A#endif
2N/A
2N/Astatic int default_increment = DEFAULT_INC;
2N/A
2N/ADynObjectP DynCreate(el_size, inc)
2N/A int el_size, inc;
2N/A{
2N/A DynObjectP obj;
2N/A
2N/A obj = (DynObjectP) malloc(sizeof(DynObjectRecP));
2N/A if (obj == NULL)
2N/A return NULL;
2N/A
2N/A obj->array = (DynPtr) malloc(1);
2N/A if (obj->array == NULL) {
2N/A free(obj);
2N/A return NULL;
2N/A }
2N/A obj->array[0] = '\0';
2N/A
2N/A obj->el_size = el_size;
2N/A obj->num_el = obj->size = 0;
2N/A obj->debug = obj->paranoid = 0;
2N/A obj->inc = (inc) ? inc : default_increment;
2N/A obj->initzero = 0;
2N/A
2N/A return obj;
2N/A}
2N/A
2N/ADynObjectP DynCopy(obj)
2N/A DynObjectP obj;
2N/A{
2N/A DynObjectP obj1;
2N/A
2N/A obj1 = (DynObjectP) malloc(sizeof(DynObjectRecP));
2N/A if (obj1 == NULL)
2N/A return NULL;
2N/A
2N/A obj1->el_size = obj->el_size;
2N/A obj1->num_el = obj->num_el;
2N/A obj1->size = obj->size;
2N/A obj1->inc = obj->inc;
2N/A obj1->debug = obj->debug;
2N/A obj1->paranoid = obj->paranoid;
2N/A obj1->initzero = obj->initzero;
2N/A obj1->array = (char *) malloc((size_t) (obj1->el_size * obj1->size));
2N/A if (obj1->array == NULL) {
2N/A free(obj1);
2N/A return NULL;
2N/A }
2N/A memcpy(obj1->array, obj->array,
2N/A (size_t) (obj1->el_size * obj1->size));
2N/A
2N/A return obj1;
2N/A}
2N/A
2N/Aint DynDestroy(obj)
2N/A /*@only@*/DynObjectP obj;
2N/A{
2N/A if (obj->paranoid) {
2N/A if (obj->debug)
2N/A fprintf(stderr, "dyn: destroy: zeroing %d bytes from %p.\n",
2N/A obj->el_size * obj->size, obj->array);
2N/A memset(obj->array, 0, (size_t) (obj->el_size * obj->size));
2N/A }
2N/A free(obj->array);
2N/A free(obj);
2N/A return DYN_OK;
2N/A}
2N/A
2N/Aint DynRelease(obj)
2N/A DynObjectP obj;
2N/A{
2N/A if (obj->debug)
2N/A fprintf(stderr, "dyn: release: freeing object structure.\n");
2N/A free(obj);
2N/A return DYN_OK;
2N/A}
2N/A
2N/A
2N/A/* old dyn_debug.c */
2N/A/*
2N/A * This file is part of libdyn.a, the C Dynamic Object library. It
2N/A * contains the source code for the function DynDebug().
2N/A */
2N/A
2N/Aint DynDebug(obj, state)
2N/A DynObjectP obj;
2N/A int state;
2N/A{
2N/A obj->debug = state;
2N/A
2N/A fprintf(stderr, "dyn: debug: Debug state set to %d.\n", state);
2N/A return DYN_OK;
2N/A}
2N/A
2N/A
2N/A/* old dyn_delete.c */
2N/A/*
2N/A * This file is part of libdyn.a, the C Dynamic Object library. It
2N/A * contains the source code for the function DynDelete().
2N/A */
2N/A
2N/A/*
2N/A * Checkers! Get away from that "hard disk erase" button!
2N/A * (Stupid dog. He almost did it to me again ...)
2N/A */
2N/Aint DynDelete(obj, idx)
2N/A DynObjectP obj;
2N/A int idx;
2N/A{
2N/A if (idx < 0) {
2N/A if (obj->debug)
2N/A fprintf(stderr, "dyn: delete: bad index %d\n", idx);
2N/A return DYN_BADINDEX;
2N/A }
2N/A
2N/A if (idx >= obj->num_el) {
2N/A if (obj->debug)
2N/A fprintf(stderr, "dyn: delete: Highest index is %d.\n",
2N/A obj->num_el);
2N/A return DYN_BADINDEX;
2N/A }
2N/A
2N/A if (idx == obj->num_el-1) {
2N/A if (obj->paranoid) {
2N/A if (obj->debug)
2N/A fprintf(stderr, "dyn: delete: last element, zeroing.\n");
2N/A memset(obj->array + idx*obj->el_size, 0, (size_t) obj->el_size);
2N/A }
2N/A else {
2N/A if (obj->debug)
2N/A fprintf(stderr, "dyn: delete: last element, punting.\n");
2N/A }
2N/A }
2N/A else {
2N/A if (obj->debug)
2N/A fprintf(stderr,
2N/A "dyn: delete: copying %d bytes from %p + %d to + %d.\n",
2N/A obj->el_size*(obj->num_el - idx), obj->array,
2N/A (idx+1)*obj->el_size, idx*obj->el_size);
2N/A
2N/A memmove(obj->array + idx*obj->el_size,
2N/A obj->array + (idx+1)*obj->el_size,
2N/A (size_t) obj->el_size*(obj->num_el - idx));
2N/A if (obj->paranoid) {
2N/A if (obj->debug)
2N/A fprintf(stderr,
2N/A "dyn: delete: zeroing %d bytes from %p + %d\n",
2N/A obj->el_size, obj->array,
2N/A obj->el_size*(obj->num_el - 1));
2N/A memset(obj->array + obj->el_size*(obj->num_el - 1), 0,
2N/A (size_t) obj->el_size);
2N/A }
2N/A }
2N/A
2N/A --obj->num_el;
2N/A
2N/A if (obj->debug)
2N/A fprintf(stderr, "dyn: delete: done.\n");
2N/A
2N/A return DYN_OK;
2N/A}
2N/A
2N/A
2N/A/* old dyn_initzero.c */
2N/A/*
2N/A * This file is part of libdyn.a, the C Dynamic Object library. It
2N/A * contains the source code for the function DynInitZero().
2N/A */
2N/A
2N/Aint DynInitzero(obj, state)
2N/A DynObjectP obj;
2N/A int state;
2N/A{
2N/A obj->initzero = state;
2N/A
2N/A if (obj->debug)
2N/A fprintf(stderr, "dyn: initzero: initzero set to %d.\n", state);
2N/A return DYN_OK;
2N/A}
2N/A
2N/A
2N/A/* old dyn_insert.c */
2N/A/*
2N/A * This file is part of libdyn.a, the C Dynamic Object library. It
2N/A * contains the source code for the function DynInsert().
2N/A */
2N/A
2N/Aint DynInsert(obj, idx, els_in, num)
2N/A DynObjectP obj;
2N/A void *els_in;
2N/A int idx, num;
2N/A{
2N/A DynPtr els = (DynPtr) els_in;
2N/A int ret;
2N/A
2N/A if (idx < 0 || idx > obj->num_el) {
2N/A if (obj->debug)
2N/A fprintf(stderr, "dyn: insert: index %d is not in [0,%d]\n",
2N/A idx, obj->num_el);
2N/A return DYN_BADINDEX;
2N/A }
2N/A
2N/A if (num < 1) {
2N/A if (obj->debug)
2N/A fprintf(stderr, "dyn: insert: cannot insert %d elements\n",
2N/A num);
2N/A return DYN_BADVALUE;
2N/A }
2N/A
2N/A if (obj->debug)
2N/A fprintf(stderr,"dyn: insert: Moving %d bytes from %p + %d to + %d\n",
2N/A (obj->num_el-idx)*obj->el_size, obj->array,
2N/A obj->el_size*idx, obj->el_size*(idx+num));
2N/A
2N/A if ((ret = _DynResize(obj, obj->num_el + num)) != DYN_OK)
2N/A return ret;
2N/A memmove(obj->array + obj->el_size*(idx + num),
2N/A obj->array + obj->el_size*idx,
2N/A (size_t) ((obj->num_el-idx)*obj->el_size));
2N/A
2N/A if (obj->debug)
2N/A fprintf(stderr, "dyn: insert: Copying %d bytes from %p to %p + %d\n",
2N/A obj->el_size*num, els, obj->array, obj->el_size*idx);
2N/A
2N/A memmove(obj->array + obj->el_size*idx, els, (size_t) (obj->el_size*num));
2N/A obj->num_el += num;
2N/A
2N/A if (obj->debug)
2N/A fprintf(stderr, "dyn: insert: done.\n");
2N/A
2N/A return DYN_OK;
2N/A}
2N/A
2N/A
2N/A/* old dyn_paranoid.c */
2N/A/*
2N/A * This file is part of libdyn.a, the C Dynamic Object library. It
2N/A * contains the source code for the function DynDebug().
2N/A */
2N/A
2N/Aint DynParanoid(obj, state)
2N/A DynObjectP obj;
2N/A int state;
2N/A{
2N/A obj->paranoid = state;
2N/A
2N/A if (obj->debug)
2N/A fprintf(stderr, "dyn: paranoid: Paranoia set to %d.\n", state);
2N/A return DYN_OK;
2N/A}
2N/A
2N/A
2N/A/* old dyn_put.c */
2N/A/*
2N/A * This file is part of libdyn.a, the C Dynamic Object library. It
2N/A * contains the source code for the functions DynGet() and DynAdd().
2N/A */
2N/A
2N/ADynPtr DynArray(obj)
2N/A DynObjectP obj;
2N/A{
2N/A if (obj->debug)
2N/A fprintf(stderr, "dyn: array: returning array pointer %p.\n",
2N/A obj->array);
2N/A
2N/A return obj->array;
2N/A}
2N/A
2N/ADynPtr DynGet(obj, num)
2N/A DynObjectP obj;
2N/A int num;
2N/A{
2N/A if (num < 0) {
2N/A if (obj->debug)
2N/A fprintf(stderr, "dyn: get: bad index %d\n", num);
2N/A return NULL;
2N/A }
2N/A
2N/A if (num >= obj->num_el) {
2N/A if (obj->debug)
2N/A fprintf(stderr, "dyn: get: highest element is %d.\n",
2N/A obj->num_el);
2N/A return NULL;
2N/A }
2N/A
2N/A if (obj->debug)
2N/A fprintf(stderr, "dyn: get: Returning address %p + %d.\n",
2N/A obj->array, obj->el_size*num);
2N/A
2N/A return (DynPtr) obj->array + obj->el_size*num;
2N/A}
2N/A
2N/Aint DynAdd(obj, el)
2N/A DynObjectP obj;
2N/A void *el;
2N/A{
2N/A int ret;
2N/A
2N/A ret = DynPut(obj, el, obj->num_el);
2N/A if (ret != DYN_OK)
2N/A return ret;
2N/A
2N/A ++obj->num_el;
2N/A return ret;
2N/A}
2N/A
2N/A/*
2N/A * WARNING! There is a reason this function is not documented in the
2N/A * man page. If DynPut used to mutate already existing elements,
2N/A * everything will go fine. If it is used to add new elements
2N/A * directly, however, the state within the object (such as
2N/A * obj->num_el) will not be updated properly and many other functions
2N/A * in the library will lose. Have a nice day.
2N/A */
2N/Aint DynPut(obj, el_in, idx)
2N/A DynObjectP obj;
2N/A void *el_in;
2N/A int idx;
2N/A{
2N/A DynPtr el = (DynPtr) el_in;
2N/A int ret;
2N/A
2N/A if (obj->debug)
2N/A fprintf(stderr, "dyn: put: Writing %d bytes from %p to %p + %d\n",
2N/A obj->el_size, el, obj->array, idx*obj->el_size);
2N/A
2N/A if ((ret = _DynResize(obj, idx)) != DYN_OK)
2N/A return ret;
2N/A
2N/A memmove(obj->array + idx*obj->el_size, el, (size_t) obj->el_size);
2N/A
2N/A if (obj->debug)
2N/A fprintf(stderr, "dyn: put: done.\n");
2N/A
2N/A return DYN_OK;
2N/A}
2N/A
2N/A
2N/A/* old dyn_realloc.c */
2N/A/*
2N/A * This file is part of libdyn.a, the C Dynamic Object library. It
2N/A * contains the source code for the internal function _DynRealloc().
2N/A */
2N/A
2N/A/*
2N/A * Resize the array so that element req exists.
2N/A */
2N/Aint _DynResize(obj, req)
2N/A DynObjectP obj;
2N/A int req;
2N/A{
2N/A int size;
2N/A
2N/A if (obj->size > req)
2N/A return DYN_OK;
2N/A else if (obj->inc > 0)
2N/A return _DynRealloc(obj, (req - obj->size) / obj->inc + 1);
2N/A else {
2N/A if (obj->size == 0)
2N/A size = -obj->inc;
2N/A else
2N/A size = obj->size;
2N/A
2N/A /*@-shiftsigned@*/
2N/A while (size <= req)
2N/A size <<= 1;
2N/A /*@=shiftsigned@*/
2N/A
2N/A return _DynRealloc(obj, size);
2N/A }
2N/A}
2N/A
2N/A/*
2N/A * Resize the array by num_incs units. If obj->inc is positive, this
2N/A * means make it obj->inc*num_incs elements larger. If obj->inc is
2N/A * negative, this means make the array num_incs elements long.
2N/A *
2N/A * Ideally, this function should not be called from outside the
2N/A * library. However, nothing will break if it is.
2N/A */
2N/Aint _DynRealloc(obj, num_incs)
2N/A DynObjectP obj;
2N/A int num_incs;
2N/A{
2N/A DynPtr temp;
2N/A int new_size_in_bytes;
2N/A
2N/A if (obj->inc > 0)
2N/A new_size_in_bytes = obj->el_size*(obj->size + obj->inc*num_incs);
2N/A else
2N/A new_size_in_bytes = obj->el_size*num_incs;
2N/A
2N/A if (obj->debug)
2N/A fprintf(stderr,
2N/A "dyn: alloc: Increasing object by %d bytes (%d incs).\n",
2N/A new_size_in_bytes - obj->el_size*obj->size,
2N/A num_incs);
2N/A
2N/A temp = (DynPtr) realloc(obj->array, (size_t) new_size_in_bytes);
2N/A if (temp == NULL) {
2N/A if (obj->debug)
2N/A fprintf(stderr, "dyn: alloc: Out of memory.\n");
2N/A return DYN_NOMEM;
2N/A }
2N/A else {
2N/A obj->array = temp;
2N/A if (obj->inc > 0)
2N/A obj->size += obj->inc*num_incs;
2N/A else
2N/A obj->size = num_incs;
2N/A }
2N/A
2N/A if (obj->debug)
2N/A fprintf(stderr, "dyn: alloc: done.\n");
2N/A
2N/A return DYN_OK;
2N/A}
2N/A
2N/A
2N/A/* old dyn_size.c */
2N/A/*
2N/A * This file is part of libdyn.a, the C Dynamic Object library. It
2N/A * contains the source code for the function DynSize().
2N/A */
2N/A
2N/Aint DynSize(obj)
2N/A DynObjectP obj;
2N/A{
2N/A if (obj->debug)
2N/A fprintf(stderr, "dyn: size: returning size %d.\n", obj->num_el);
2N/A
2N/A return obj->num_el;
2N/A}
2N/A
2N/Aint DynCapacity(obj)
2N/A DynObjectP obj;
2N/A{
2N/A if (obj->debug)
2N/A fprintf(stderr, "dyn: capacity: returning cap of %d.\n", obj->size);
2N/A
2N/A return obj->size;
2N/A}
2N/A
2N/A/* Old change log, as it relates to source code; build system stuff
2N/A discarded.
2N/A
2N/A2001-10-09 Ken Raeburn <raeburn@mit.edu>
2N/A
2N/A * dyn.h, dynP.h: Make prototypes unconditional. Don't define
2N/A P().
2N/A
2N/A2001-04-25 Ezra Peisach <epeisach@mit.edu>
2N/A
2N/A * dyn.h: Lclint annotate functions.
2N/A
2N/A * dyn_create.c (DynCreate): Do not assume that malloc(0) is valid
2N/A and returns a valid pointer. Fix memory leak if malloc fails.
2N/A
2N/A * dyn_realloc.c (_DynResize): Turn off warning of shifting a
2N/A signed variable.
2N/A
2N/AThu Nov 9 15:31:31 2000 Ezra Peisach <epeisach@mit.edu>
2N/A
2N/A * dyn_create.c (DynCopy): Arguments to memcpy were reversed. Found
2N/A while playing with lclint.
2N/A
2N/A2000-11-09 Ezra Peisach <epeisach@mit.edu>
2N/A
2N/A * dyn_create.c, dyn_delete.c, dyn_insert.c, dyn_put.c,
2N/A dyn_realloc.c: Cast arguments to malloc(), realloc(), memmove() to
2N/A size_t.
2N/A
2N/A * dynP.h: Provide full prototypes for _DynRealloc() and _DynResize().
2N/A
2N/A * dyn.h: Add prototype for DynAppend.
2N/A
2N/A2000-06-29 Ezra Peisach <epeisach@mit.edu>
2N/A
2N/A * dyn_insert.c, dyn_put.c: Include string.h for memmove prototype.
2N/A
2N/A2000-06-28 Ezra Peisach <epeisach@mit.edu>
2N/A
2N/A * dyn_create.c, dyn_delete.c, dyn_insert.c, dyn_put.c: Use %p
2N/A format for displaying pointers.
2N/A
2N/A2000-06-26 Ezra Peisach <epeisach@mit.edu>
2N/A
2N/A * dyn_realloc.c: Remove unused variable.
2N/A
2N/ASat Dec 6 22:50:03 1997 Ezra Peisach <epeisach@mit.edu>
2N/A
2N/A * dyn_delete.c: Include <string.h>
2N/A
2N/AMon Jul 22 21:37:52 1996 Ezra Peisach <epeisach@mit.edu>
2N/A
2N/A * dyn.h: If __STDC__ is not defined, generate prototypes implying
2N/A functions and not variables.
2N/A
2N/AMon Jul 22 04:20:48 1996 Marc Horowitz <marc@mit.edu>
2N/A
2N/A * dyn_insert.c (DynInsert): what used to be #ifdef POSIX, should
2N/A be #ifdef HAVE_MEMMOVE
2N/A*/