/* Dynamic 2D Array Library; version 1.0 */
/* (c) copyright Ian Hickson 2000, distributed under the GNU GPL */

#include <malloc.h> /* malloc and co */
#include <string.h> /* memcpy */
#include <assert.h> /* debugging */

/* BASIC 2D ARRAY FUNCTIONALITY */               

typedef char byte;  /* SizeOf(byte) MUST equal 1! */

typedef struct ARRAY2D {
  int elementSize;
  int width, height;
  byte* array;
} array2d;

array2d* allocArray2D(int width, int height, int elementSize) {
  array2d* array;
  /* here we should do bounds checking... */
  assert(width>0);
  assert(height>0);
  assert(elementSize>0);
  array = malloc(sizeof(array2d));
  /* here we should do error checking... */
  assert(array!=0);
  array->elementSize = elementSize;
  array->width = width;
  array->height = height;
  array->array = malloc(elementSize*width*height);
  /* here we should do error checking... */
  assert(array->array!=0);
  return array;
}

array2d* cloneArray2D(array2d* source) {
  array2d* array;
  /* here we should do error checking... */
  assert(source!=NULL);
  array = allocArray2D(source->width, source->height, source->elementSize);
  memcpy(array->array, source->array, source->elementSize*source->width*source->height);
  return array;
}

void* getPointerArray2D(array2d* array, int x, int y) {
  /* internal routine, no need to do error checking */
  assert(array!=NULL);
  assert(x<array->width);
  assert(y<array->height);
  return (array->array) + (((array->width)*(array->elementSize)*(y)) + ((array->elementSize)*(x)));
}

void freeArray2D(array2d* array) {
  /* here we should do error checking... */
  free(array->array);
  free(array);
}

void setArray2D(array2d* array, int x, int y, void* value) {
  /* here we should do error checking... */
  assert(array!=NULL);
  assert(x<array->width);
  assert(y<array->height);
  assert(x>=0);
  assert(y>=0);
  memcpy(getPointerArray2D(array, x, y), value, array->elementSize);
}

void* getArray2D(array2d* array, int x, int y) {
  /* here we should do error checking... */
  assert(array!=NULL);
  assert(x<array->width);
  assert(y<array->height);
  return getPointerArray2D(array, x, y);
}

void permuteRowsArray2D(array2d* array, int y1, int y2) {
  byte* rowBuffer;
  int rowSize;
  if (y1 != y2) {
    /* here we should do some bounds checking... */
    assert(array!=NULL);
    assert(y1<array->height);
    assert(y2<array->height);
    rowSize = (array->elementSize)*(array->width);
    rowBuffer = malloc(rowSize);
    memcpy(rowBuffer, getPointerArray2D(array, 0, y1), rowSize);
    memcpy(getPointerArray2D(array, 0, y1), getPointerArray2D(array, 0, y2), rowSize);
    memcpy(getPointerArray2D(array, 0, y2), rowBuffer, rowSize);
    free(rowBuffer);
  }
}

/* end */
