#include "pointergrid.h" /** Allocates a new, uninitialized PointerGrid. */ PointerGrid * pointergrid_alloc(void) { return mem_alloc(sizeof(PointerGrid)); } /** Nulls out all the data in pointergrid. If memdestructor is not NULL, * it will be called with the old value in the cell before NULL is set. */ int pointergrid_nullall(PointerGrid * self, MemDestructor * destroy) { int w, h, x, y; if (!self) return -1; if (!self->data) return -1; w = pointergrid_w(self); h = pointergrid_h(self); for(y = 0; y < h ; y++) { for(x = 0; x < w ; x++) { void * cell = pointergrid_getraw(self, x, y); if (destroy && cell) { destroy(cell); } pointergrid_putraw(self, x, y, NULL); } } return 0; } /** Cleans up and deinitializes the PointerGrid self, using the destructor if needed */ PointerGrid * pointergrid_done(PointerGrid * self, MemDestructor * destroy) { int index; if(!self) return NULL; if(!self->data) return self; for (index = 0; index < self->h; index ++) { if(self->data[index]) { /* Clean up elements if needed. */ if(destroy) { pointergrid_nullall(self, destroy); } mem_free(self->data[index]); } self->data[index] = NULL; } self->w = -1; self->h = -1; mem_free(self->data); return self; } /** Calls PointerGrid_done, and then frees the PointerGrid self. Returns NULL. */ PointerGrid * pointergrid_free(PointerGrid * self) { pointergrid_done(self, NULL); mem_free(self); return NULL; } /** Returns the width of the PointerGrid. Returns -1 is self isn't propery * initialized. */ int pointergrid_w(PointerGrid * self) { if(!self) return -1; return self->w; } /** Returns the height of the PointerGrid. * Returns -1 is self isn't propery initialized. */ int pointergrid_h(PointerGrid * self) { if(!self) return -1; return self->h; } /** Initializes a PointerGrid to be of the given width and height. * Returns NULL on error, or if h or w are less than 1. * Returns self on sucess. */ PointerGrid * pointergrid_init(PointerGrid * self, int w, int h) { int index; if(!self) return NULL; self->w = w; self->h = h; self->data = NULL; if ((self->h <= 0) || (self->w <= 0)) { return NULL; } // Allocate y dimension self->data = (intptr_t **) mem_alloc(sizeof(intptr_t *) * self->h); if(!self->data) return NULL; // Now allocate the x dimensions. for (index = 0; index < self->h; index ++) { self->data[index] = (intptr_t *) mem_alloc(sizeof(intptr_t) * self->w); if(!self->data[index]) return pointergrid_free(self); } return self; } /** Allocates a new grid and initializes it. */ PointerGrid * pointergrid_new(int w, int h) { PointerGrid * self = pointergrid_alloc(); return pointergrid_init(self, w, h); } /** * Return true if the arguments x and or y are out of range, or * if self itself isn't properly initialized. Return false if OK. */ int pointergrid_outofrange(PointerGrid * self, int x, int y) { if(!self) return TRUE; if(!self->data) return TRUE; if ((x < 0) || (y < 0)) { return TRUE; } if ((y >= self->h) || (x >= self->w)) { return TRUE; } return FALSE; } /** Gets an element from the grid. Does no checking whatsoever. * Use only where the inputs are guaranteed to be valid, where speed is * of the essence. */ void * pointergrid_getraw(PointerGrid * self, int x, int y) { return (void *)self->data[y][x]; } /** Gets a row of elements from the grid. Does no checking whatsoever. * Use only where the inputs are guaranteed to be valid, where speed is * of the essence. */ void * * pointergrid_rowraw(PointerGrid * self, int y) { return (void **) self->data[y]; } /** Gets an element from the grid self. * If all goes well, this function returns 0, and sets the value to * (*result). * If w and h are out of range, or the grid isn't correctly initialized, * does nothing and returns -1 in stead. */ int pointergrid_get(PointerGrid * self, int x, int y, void * * result) { void * * aid; if(pointergrid_outofrange(self,x,y)) { return -1; } (*result) = pointergrid_getraw(self,x,y); return 0; } /** Puts an element in the grid self. Does no checking whatsoever. * Use only where the inputs are guaranteed to be valid, where speed is * of the essence. */ void pointergrid_putraw(PointerGrid * self, int x, int y, void * el) { self->data[y][x] = (intptr_t)el; } /** Puts and element into the grid self. * If all goes well, this function returns 0. * If w and h are out of range, or the grid isn't correctly initialized, * does nothing and returns -1 in stead. */ int pointergrid_put(PointerGrid * self, int x, int y, void * el) { if(pointergrid_outofrange(self,x,y)) { return -1; } pointergrid_putraw(self,x,y,el); return 0; } /** Sets and element into the grid self. * If all goes well, this function returns el. * If w and h are out of range, or the grid isn't correctly initialized, * does nothing and returns NULL in stead. */ void * pointergrid_store(PointerGrid * self, int x, int y, void * el) { if(pointergrid_outofrange(self,x,y)) { return NULL; } pointergrid_putraw(self,x,y,el); return el; } /** Fetched an element from the grid self. * If all goes well, this returns the result. * If w and h are out of range, or the grid isn't correctly initialized, * returns NULL. */ void * pointergrid_fetch(PointerGrid * self, int x, int y) { if (pointergrid_outofrange(self,x,y)) { return NULL; } return pointergrid_getraw(self,x,y); } /** Copies the data from one grid to the other. * If the grides are of unequal size, copies the smallest of both * heights and widths. * Returns 0 on succes, -1 on error. */ int pointergrid_copy(PointerGrid * self, PointerGrid * other) { int ws, hs, wo, ho, w, h, x, y; if ((!self) || (!other)) return -1; if ((!self->data) || (!other->data)) return -1; ws = pointergrid_w(self); hs = pointergrid_h(self); wo = pointergrid_w(other); ho = pointergrid_h(other); // Copy only smallest of width and height. w = (ws < wo ? ws : wo); h = (hs < ho ? hs : ho); for(y = 0; y < h ; y++) { for(x = 0; x < w ; x++) { self->data[y][x] = other->data[y][x]; } } return 0; } /** Gets an element from the grid. Does no checking whatsoever. * Use only where the inputs are guaranteed to be valid, where speed is * of the essence. */ intptr_t pointergrid_get_raw_int(PointerGrid * self, int x, int y) { return self->data[y][x]; } /** Gets a row of elements from the grid. Does no checking whatsoever. * Use only where the inputs are guaranteed to be valid, where speed is * of the essence. */ intptr_t * pointergrid_row_raw_int(PointerGrid * self, int y) { return self->data[y]; } /** Gets an integer value from the grid self. * If all goes well, this function returns 0, and sets the value to * (*result). * If w and h are out of range, or the grid isn't correctly initialized, * does nothing and returns -1 in stead. */ int pointergrid_get_int(PointerGrid * self, int x, int y, int * result) { if(pointergrid_outofrange(self,x,y)) { return -1; } (*result) = (int) pointergrid_get_raw_int(self, x, y); return 0; } /** Puts an integer in the grid self. Does no checking whatsoever. * Use only where the inputs are guaranteed to be valid, where speed is * of the essence. */ void pointergrid_put_raw_int(PointerGrid * self, int x, int y, int el) { self->data[y][x] = (intptr_t)el; } /** Puts an integer into the grid self. * If all goes well, this function returns 0. * If w and h are out of range, or the grid isn't correctly initialized, * does nothing and returns -1 in stead. */ int pointergrid_put_int(PointerGrid * self, int x, int y, int el) { if(pointergrid_outofrange(self,x,y)) { return -1; } pointergrid_put_raw_int(self,x,y,el); return 0; } /** Sets and element into the grid self. * If all goes well, this function returns el. * If w and h are out of range, or the grid isn't correctly initialized, * does nothing and returns 0 in stead. */ int pointergrid_store_int(PointerGrid * self, int x, int y, int el) { if(pointergrid_outofrange(self, x, y)) { return 0; } pointergrid_put_raw_int(self, x, y, el); return el; } /** Fetched an element from the grid self. * If all goes well, this returns the result. * If w and h are out of range, or the grid isn't correctly initialized, * returns 0. */ int pointergrid_fetch_int(PointerGrid * self, int x, int y) { if (pointergrid_outofrange(self,x,y)) { return 0; } return (int) pointergrid_get_raw_int(self,x,y); } /** Sets all the pointer grid to a 0 integer. Do NOT do this * if the pointergrid is intent to store pointer, only if it stores integers. */ int pointergrid_zero_all(PointerGrid * self) { int w, h, x, y; if (!self) return -1; if (!self->data) return -1; w = pointergrid_w(self); h = pointergrid_h(self); for(y = 0; y < h ; y++) { for(x = 0; x < w ; x++) { pointergrid_put_raw_int(self, x, y, 0); } } return 0; }