int grid_xreq_add (struct grid_sockbase *self, struct grid_pipe *pipe) { struct grid_xreq *xreq; struct grid_xreq_data *data; int sndprio; int rcvprio; size_t sz; xreq = grid_cont (self, struct grid_xreq, sockbase); sz = sizeof (sndprio); grid_pipe_getopt (pipe, GRID_SOL_SOCKET, GRID_SNDPRIO, &sndprio, &sz); grid_assert (sz == sizeof (sndprio)); grid_assert (sndprio >= 1 && sndprio <= 16); sz = sizeof (rcvprio); grid_pipe_getopt (pipe, GRID_SOL_SOCKET, GRID_RCVPRIO, &rcvprio, &sz); grid_assert (sz == sizeof (rcvprio)); grid_assert (rcvprio >= 1 && rcvprio <= 16); data = grid_alloc (sizeof (struct grid_xreq_data), "pipe data (req)"); alloc_assert (data); grid_pipe_setdata (pipe, data); grid_lb_add (&xreq->lb, &data->lb, pipe, sndprio); grid_fq_add (&xreq->fq, &data->fq, pipe, rcvprio); return 0; }
static int grid_xreq_create (void *hint, struct grid_sockbase **sockbase) { struct grid_xreq *self; self = grid_alloc (sizeof (struct grid_xreq), "socket (xreq)"); alloc_assert (self); grid_xreq_init (self, &grid_xreq_sockbase_vfptr, hint); *sockbase = &self->sockbase; return 0; }
static int grid_node_unsubscribe (struct grid_trie_node **self, const uint8_t *data, size_t size) { int i; int j; int index; int new_min; struct grid_trie_node **ch; struct grid_trie_node *new_node; struct grid_trie_node *ch2; if (!size) goto found; /* If prefix does not match the data, return. */ if (grid_node_check_prefix (*self, data, size) != (*self)->prefix_len) return 0; /* Skip the prefix. */ data += (*self)->prefix_len; size -= (*self)->prefix_len; if (!size) goto found; /* Move to the next node. */ ch = grid_node_next (*self, *data); if (!ch) return 0; /* TODO: This should be an error. */ /* Recursive traversal of the trie happens here. If the subscription wasn't really removed, nothing have changed in the trie and no additional pruning is needed. */ if (grid_node_unsubscribe (ch, data + 1, size - 1) == 0) return 0; /* Subscription removal is already done. Now we are going to compact the trie. However, if the following node remains in place, there's nothing to compact here. */ if (*ch) return 1; /* Sparse array. */ if ((*self)->type < GRID_TRIE_DENSE_TYPE) { /* Get the indices of the removed child. */ for (index = 0; index != (*self)->type; ++index) if ((*self)->u.sparse.children [index] == *data) break; assert (index != (*self)->type); /* Remove the destroyed child from both lists of children. */ memmove ( (*self)->u.sparse.children + index, (*self)->u.sparse.children + index + 1, (*self)->type - index - 1); memmove ( grid_node_child (*self, index), grid_node_child (*self, index + 1), ((*self)->type - index - 1) * sizeof (struct grid_trie_node*)); --(*self)->type; *self = grid_realloc (*self, sizeof (struct grid_trie_node) + ((*self)->type * sizeof (struct grid_trie_node*))); assert (*self); /* If there are no more children and no refcount, we can delete the node altogether. */ if (!(*self)->type && !grid_node_has_subscribers (*self)) { grid_free (*self); *self = NULL; return 1; } /* Try to merge the node with the following node. */ *self = grid_node_compact (*self); return 1; } /* Dense array. */ /* In this case the array stays dense. We have to adjust the limits of the array, if appropriate. */ if ((*self)->u.dense.nbr > GRID_TRIE_SPARSE_MAX + 1) { /* If the removed item is the leftmost one, trim the array from the left side. */ if (*data == (*self)->u.dense.min) { for (i = 0; i != (*self)->u.dense.max - (*self)->u.dense.min + 1; ++i) if (*grid_node_child (*self, i)) break; new_min = i + (*self)->u.dense.min; memmove (grid_node_child (*self, 0), grid_node_child (*self, i), ((*self)->u.dense.max - new_min + 1) * sizeof (struct grid_trie_node*)); (*self)->u.dense.min = new_min; --(*self)->u.dense.nbr; *self = grid_realloc (*self, sizeof (struct grid_trie_node) + ((*self)->u.dense.max - new_min + 1) * sizeof (struct grid_trie_node*)); assert (*self); return 1; } /* If the removed item is the rightmost one, trim the array from the right side. */ if (*data == (*self)->u.dense.max) { for (i = (*self)->u.dense.max - (*self)->u.dense.min; i != 0; --i) if (*grid_node_child (*self, i)) break; (*self)->u.dense.max = i + (*self)->u.dense.min; --(*self)->u.dense.nbr; *self = grid_realloc (*self, sizeof (struct grid_trie_node) + ((*self)->u.dense.max - (*self)->u.dense.min + 1) * sizeof (struct grid_trie_node*)); assert (*self); return 1; } /* If the item is removed from the middle of the array, do nothing. */ --(*self)->u.dense.nbr; return 1; } /* Convert dense array into sparse array. */ { new_node = grid_alloc (sizeof (struct grid_trie_node) + GRID_TRIE_SPARSE_MAX * sizeof (struct grid_trie_node*), "trie node"); assert (new_node); new_node->refcount = 0; new_node->prefix_len = (*self)->prefix_len; memcpy (new_node->prefix, (*self)->prefix, new_node->prefix_len); new_node->type = GRID_TRIE_SPARSE_MAX; j = 0; for (i = 0; i != (*self)->u.dense.max - (*self)->u.dense.min + 1; ++i) { ch2 = *grid_node_child (*self, i); if (ch2) { new_node->u.sparse.children [j] = i + (*self)->u.dense.min; *grid_node_child (new_node, j) = ch2; ++j; } } assert (j == GRID_TRIE_SPARSE_MAX); grid_free (*self); *self = new_node; return 1; } found: /* We are at the end of the subscription here. */ /* Subscription doesn't exist. */ if (grid_slow (!*self || !grid_node_has_subscribers (*self))) return -EINVAL; /* Subscription exists. Unsubscribe. */ --(*self)->refcount; /* If reference count has dropped to zero we can try to compact the node. */ if (!(*self)->refcount) { /* If there are no children, we can delete the node altogether. */ if (!(*self)->type) { grid_free (*self); *self = NULL; return 1; } /* Try to merge the node with the following node. */ *self = grid_node_compact (*self); return 1; } return 0; }
int grid_trie_subscribe (struct grid_trie *self, const uint8_t *data, size_t size) { int i; struct grid_trie_node **node; struct grid_trie_node **n; struct grid_trie_node *ch; struct grid_trie_node *old_node; int pos; uint8_t c; uint8_t c2; uint8_t new_min; uint8_t new_max; int old_children; int new_children; int inserted; int more_nodes; /* Step 1 -- Traverse the trie. */ node = &self->root; pos = 0; while (1) { /* If there are no more nodes on the path, go to step 4. */ if (!*node) goto step4; /* Check whether prefix matches the new subscription. */ pos = grid_node_check_prefix (*node, data, size); data += pos; size -= pos; /* If only part of the prefix matches, go to step 2. */ if (pos < (*node)->prefix_len) goto step2; /* Even if whole prefix matches and there's no more data to match, go directly to step 5. */ if (!size) goto step5; /* Move to the next node. If it is not present, go to step 3. */ n = grid_node_next (*node, *data); if (!n || !*n) goto step3; node = n; ++data; --size; } /* Step 2 -- Split the prefix into two parts if required. */ step2: ch = *node; *node = grid_alloc (sizeof (struct grid_trie_node) + sizeof (struct grid_trie_node*), "trie node"); assert (*node); (*node)->refcount = 0; (*node)->prefix_len = pos; (*node)->type = 1; memcpy ((*node)->prefix, ch->prefix, pos); (*node)->u.sparse.children [0] = ch->prefix [pos]; ch->prefix_len -= (pos + 1); memmove (ch->prefix, ch->prefix + pos + 1, ch->prefix_len); ch = grid_node_compact (ch); *grid_node_child (*node, 0) = ch; pos = (*node)->prefix_len; /* Step 3 -- Adjust the child array to accommodate the new character. */ step3: /* If there are no more data in the subscription, there's nothing to adjust in the child array. Proceed directly to the step 5. */ if (!size) goto step5; /* If the new branch fits into sparse array... */ if ((*node)->type < GRID_TRIE_SPARSE_MAX) { *node = grid_realloc (*node, sizeof (struct grid_trie_node) + ((*node)->type + 1) * sizeof (struct grid_trie_node*)); assert (*node); (*node)->u.sparse.children [(*node)->type] = *data; ++(*node)->type; node = grid_node_child (*node, (*node)->type - 1); *node = NULL; ++data; --size; goto step4; } /* If the node is already a dense array, resize it to fit the next character. */ if ((*node)->type == GRID_TRIE_DENSE_TYPE) { c = *data; if (c < (*node)->u.dense.min || c > (*node)->u.dense.max) { new_min = (*node)->u.dense.min < c ? (*node)->u.dense.min : c; new_max = (*node)->u.dense.max > c ? (*node)->u.dense.max : c; *node = grid_realloc (*node, sizeof (struct grid_trie_node) + (new_max - new_min + 1) * sizeof (struct grid_trie_node*)); assert (*node); old_children = (*node)->u.dense.max - (*node)->u.dense.min + 1; new_children = new_max - new_min + 1; if ((*node)->u.dense.min != new_min) { inserted = (*node)->u.dense.min - new_min; memmove (grid_node_child (*node, inserted), grid_node_child (*node, 0), old_children * sizeof (struct grid_trie_node*)); memset (grid_node_child (*node, 0), 0, inserted * sizeof (struct grid_trie_node*)); } else { memset (grid_node_child (*node, old_children), 0, (new_children - old_children) * sizeof (struct grid_trie_node*)); } (*node)->u.dense.min = new_min; (*node)->u.dense.max = new_max; } ++(*node)->u.dense.nbr; node = grid_node_child (*node, c - (*node)->u.dense.min); ++data; --size; goto step4; } /* This is a sparse array, but no more children can be added to it. We have to convert it into a dense array. */ { /* First, determine the range of children. */ new_min = 255; new_max = 0; for (i = 0; i != (*node)->type; ++i) { c2 = (*node)->u.sparse.children [i]; new_min = new_min < c2 ? new_min : c2; new_max = new_max > c2 ? new_max : c2; } new_min = new_min < *data ? new_min : *data; new_max = new_max > *data ? new_max : *data; /* Create a new mode, while keeping the old one for a while. */ old_node = *node; *node = (struct grid_trie_node*) grid_alloc (sizeof (struct grid_trie_node) + (new_max - new_min + 1) * sizeof (struct grid_trie_node*), "trie node"); assert (*node); /* Fill in the new node. */ (*node)->refcount = 0; (*node)->prefix_len = old_node->prefix_len; (*node)->type = GRID_TRIE_DENSE_TYPE; memcpy ((*node)->prefix, old_node->prefix, old_node->prefix_len); (*node)->u.dense.min = new_min; (*node)->u.dense.max = new_max; (*node)->u.dense.nbr = old_node->type + 1; memset (*node + 1, 0, (new_max - new_min + 1) * sizeof (struct grid_trie_node*)); for (i = 0; i != old_node->type; ++i) *grid_node_child (*node, old_node->u.sparse.children [i] - new_min) = *grid_node_child (old_node, i); node = grid_node_next (*node, *data); ++data; --size; /* Get rid of the obsolete old node. */ grid_free (old_node); } /* Step 4 -- Create new nodes for remaining part of the subscription. */ step4: assert (!*node); while (1) { /* Create a new node to hold the next part of the subscription. */ more_nodes = size > GRID_TRIE_PREFIX_MAX; *node = grid_alloc (sizeof (struct grid_trie_node) + (more_nodes ? sizeof (struct grid_trie_node*) : 0), "trie node"); assert (*node); /* Fill in the new node. */ (*node)->refcount = 0; (*node)->type = more_nodes ? 1 : 0; (*node)->prefix_len = size < (uint8_t) GRID_TRIE_PREFIX_MAX ? (uint8_t) size : (uint8_t) GRID_TRIE_PREFIX_MAX; memcpy ((*node)->prefix, data, (*node)->prefix_len); data += (*node)->prefix_len; size -= (*node)->prefix_len; if (!more_nodes) break; (*node)->u.sparse.children [0] = *data; node = grid_node_child (*node, 0); ++data; --size; } /* Step 5 -- Create the subscription as such. */ step5: ++(*node)->refcount; /* Return 1 in case of a fresh subscription. */ return (*node)->refcount == 1 ? 1 : 0; }
int32_t main(int32_t argc, char *argv[]) { if( init_sdl2() ) { return 1; } SDL_Window* window; sdl2_window("test-grid", 100, 60, 1280, 720, &window); SDL_GLContext* context; sdl2_glcontext(3, 2, window, &context); if( init_vbo() ) { return 1; } printf("vbo\n"); struct Vbo vbo = {0}; vbo_create(&vbo); vbo_add_buffer(&vbo, SHADER_ATTRIBUTE_VERTEX, 3, GL_FLOAT, GL_STATIC_DRAW); vbo_add_buffer(&vbo, SHADER_ATTRIBUTE_VERTEX_NORMAL, 3, GL_FLOAT, GL_STATIC_DRAW); struct Ibo ibo = {0}; ibo_create(GL_TRIANGLES, GL_UNSIGNED_INT, GL_STATIC_DRAW, &ibo); struct Grid grid = {0}; grid_create(4,4,1,&grid); struct GridPages pages = {0}; grid_pages(&grid,2,2,1,&pages); grid_dump(grid,pages); struct GridIndex index = {0}; for( uint64_t z = 0; z < grid.size.z; z++ ) { for( uint64_t y = 0; y < grid.size.y; y++ ) { for( uint64_t x = 0; x < grid.size.x; x++ ) { grid_index_xyz(&grid, &pages, NULL, x, y, z, &index); printf("x:%lu y:%lu z:%lu page:%lu cell:%lu\n", x, y, z, index.page, index.cell); } } } printf("-----------\n"); struct GridBox box = {0}; box.position.x = 1; box.position.y = 1; box.position.z = 0; box.size.x = 2; box.size.y = 2; box.size.z = 1; box.level = 0; for( uint64_t z = 0; z < box.size.z; z++ ) { for( uint64_t y = 0; y < box.size.y; y++ ) { for( uint64_t x = 0; x < box.size.x; x++ ) { grid_index_xyz(&grid, &pages, &box, x, y, z, &index); printf("x:%lu y:%lu z:%lu page:%lu cell:%lu\n", x, y, z, index.page, index.cell); } } } struct GridSize size = {0}; uint64_t array_size = grid_levelsize(&grid, &pages, 0, &size)->array; for( int32_t i = 0; i < array_size; i++ ) { grid_index(&grid, &pages, NULL, i, &index); } uint64_t x = UINT64_MAX; printf("0x%lx\n", x); grid_alloc(&pages, 0, 0); grid_alloc(&pages, 1, 0); grid_alloc(&pages, 2, 0); grid_alloc(&pages, 3, 0); grid_set1(&grid, &pages, NULL, 23); grid_set1(&grid, &pages, &box, 42); printf("lala\n"); grid_pagebox(&grid, &pages, 3, 0, &box); printf("%lu %lu %lu %lu %lu %lu %d\n", box.position.x, box.position.y, box.position.z, box.size.x, box.size.y, box.size.z, box.level); /* grid_pageout(&grid, &pages, 0, NULL); */ /* printf("\n"); */ /* grid_pageout(&grid, &pages, 1, NULL); */ /* printf("\n"); */ /* grid_pageout(&grid, &pages, 2, NULL); */ /* printf("\n"); */ /* grid_pageout(&grid, &pages, 3, NULL); */ /* printf("\n"); */ return 0; }
int grid_poll (struct grid_pollfd *fds, int nfds, int timeout) { int rc; int i; int pos; int fd; int res; size_t sz; struct pollfd *pfd; /* Construct a pollset to be used with OS-level 'poll' function. */ pfd = grid_alloc (sizeof (struct pollfd) * nfds * 2, "pollset"); alloc_assert (pfd); pos = 0; for (i = 0; i != nfds; ++i) { if (fds [i].events & GRID_POLLIN) { sz = sizeof (fd); rc = grid_getsockopt (fds [i].fd, GRID_SOL_SOCKET, GRID_RCVFD, &fd, &sz); if (grid_slow (rc < 0)) { grid_free (pfd); errno = -rc; return -1; } grid_assert (sz == sizeof (fd)); pfd [pos].fd = fd; pfd [pos].events = POLLIN; ++pos; } if (fds [i].events & GRID_POLLOUT) { sz = sizeof (fd); rc = grid_getsockopt (fds [i].fd, GRID_SOL_SOCKET, GRID_SNDFD, &fd, &sz); if (grid_slow (rc < 0)) { grid_free (pfd); errno = -rc; return -1; } grid_assert (sz == sizeof (fd)); pfd [pos].fd = fd; pfd [pos].events = POLLIN; ++pos; } } /* Do the polling itself. */ rc = poll (pfd, pos, timeout); if (grid_slow (rc <= 0)) { res = errno; grid_free (pfd); errno = res; return rc; } /* Move the results from OS-level poll to grid_poll's pollset. */ res = 0; pos = 0; for (i = 0; i != nfds; ++i) { fds [i].revents = 0; if (fds [i].events & GRID_POLLIN) { if (pfd [pos].revents & POLLIN) fds [i].revents |= GRID_POLLIN; ++pos; } if (fds [i].events & GRID_POLLOUT) { if (pfd [pos].revents & POLLIN) fds [i].revents |= GRID_POLLOUT; ++pos; } if (fds [i].revents) ++res; } grid_free (pfd); return res; }
static int grid_usock_recv_raw (struct grid_usock *self, void *buf, size_t *len) { size_t sz; size_t length; ssize_t nbytes; struct iovec iov; struct msghdr hdr; unsigned char ctrl [256]; #if defined GRID_HAVE_MSG_CONTROL struct cmsghdr *cmsg; #endif /* If batch buffer doesn't exist, allocate it. The point of delayed deallocation to allow non-receiving sockets, such as TCP listening sockets, to do without the batch buffer. */ if (grid_slow (!self->in.batch)) { self->in.batch = grid_alloc (GRID_USOCK_BATCH_SIZE, "AIO batch buffer"); alloc_assert (self->in.batch); } /* Try to satisfy the recv request by data from the batch buffer. */ length = *len; sz = self->in.batch_len - self->in.batch_pos; if (sz) { if (sz > length) sz = length; memcpy (buf, self->in.batch + self->in.batch_pos, sz); self->in.batch_pos += sz; buf = ((char*) buf) + sz; length -= sz; if (!length) return 0; } /* If recv request is greater than the batch buffer, get the data directly into the place. Otherwise, read data to the batch buffer. */ if (length > GRID_USOCK_BATCH_SIZE) { iov.iov_base = buf; iov.iov_len = length; } else { iov.iov_base = self->in.batch; iov.iov_len = GRID_USOCK_BATCH_SIZE; } memset (&hdr, 0, sizeof (hdr)); hdr.msg_iov = &iov; hdr.msg_iovlen = 1; #if defined GRID_HAVE_MSG_CONTROL hdr.msg_control = ctrl; hdr.msg_controllen = sizeof (ctrl); #else *((int*) ctrl) = -1; hdr.msg_accrights = ctrl; hdr.msg_accrightslen = sizeof (int); #endif nbytes = recvmsg (self->s, &hdr, 0); /* Handle any possible errors. */ if (grid_slow (nbytes <= 0)) { if (grid_slow (nbytes == 0)) return -ECONNRESET; /* Zero bytes received. */ if (grid_fast (errno == EAGAIN || errno == EWOULDBLOCK)) nbytes = 0; else { /* If the peer closes the connection, return ECONNRESET. */ return -ECONNRESET; } } /* Extract the associated file descriptor, if any. */ if (nbytes > 0) { #if defined GRID_HAVE_MSG_CONTROL cmsg = CMSG_FIRSTHDR (&hdr); while (cmsg) { if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { if (self->in.pfd) { *self->in.pfd = *((int*) CMSG_DATA (cmsg)); self->in.pfd = NULL; } else { grid_closefd (*((int*) CMSG_DATA (cmsg))); } break; } cmsg = CMSG_NXTHDR (&hdr, cmsg); } #else if (hdr.msg_accrightslen > 0) { grid_assert (hdr.msg_accrightslen == sizeof (int)); if (self->in.pfd) { *self->in.pfd = *((int*) hdr.msg_accrights); self->in.pfd = NULL; } else { grid_closefd (*((int*) hdr.msg_accrights)); } } #endif } /* If the data were received directly into the place we can return straight away. */ if (length > GRID_USOCK_BATCH_SIZE) { length -= nbytes; *len -= length; return 0; } /* New data were read to the batch buffer. Copy the requested amount of it to the user-supplied buffer. */ self->in.batch_len = nbytes; self->in.batch_pos = 0; if (nbytes) { sz = nbytes > (ssize_t)length ? length : (size_t)nbytes; memcpy (buf, self->in.batch, sz); length -= sz; self->in.batch_pos += sz; } *len -= length; return 0; }
/* ============================================================================= * maze_checkPaths * ============================================================================= */ bool_t maze_checkPaths (maze_t* mazePtr, list_t* pathVectorListPtr, bool_t doPrintPaths) { grid_t* gridPtr = mazePtr->gridPtr; long width = gridPtr->width; long height = gridPtr->height; long depth = gridPtr->depth; long i; /* Mark walls */ grid_t* testGridPtr = grid_alloc(width, height, depth); grid_addPath(testGridPtr, mazePtr->wallVectorPtr); /* Mark sources */ vector_t* srcVectorPtr = mazePtr->srcVectorPtr; long numSrc = vector_getSize(srcVectorPtr); for (i = 0; i < numSrc; i++) { coordinate_t* srcPtr = (coordinate_t*)vector_at(srcVectorPtr, i); grid_setPoint(testGridPtr, srcPtr->x, srcPtr->y, srcPtr->z, 0); } /* Mark destinations */ vector_t* dstVectorPtr = mazePtr->dstVectorPtr; long numDst = vector_getSize(dstVectorPtr); for (i = 0; i < numDst; i++) { coordinate_t* dstPtr = (coordinate_t*)vector_at(dstVectorPtr, i); grid_setPoint(testGridPtr, dstPtr->x, dstPtr->y, dstPtr->z, 0); } /* Make sure path is contiguous and does not overlap */ long id = 0; list_iter_t it; list_iter_reset(&it, pathVectorListPtr); while (list_iter_hasNext(&it)) { vector_t* pathVectorPtr = (vector_t*)list_iter_next(&it); long numPath = vector_getSize(pathVectorPtr); long i; for (i = 0; i < numPath; i++) { id++; vector_t* pointVectorPtr = (vector_t*)vector_at(pathVectorPtr, i); /* Check start */ long* prevGridPointPtr = (long*)vector_at(pointVectorPtr, 0); long x; long y; long z; grid_getPointIndices(gridPtr, prevGridPointPtr, &x, &y, &z); if (grid_getPoint(testGridPtr, x, y, z) != 0) { grid_free(testGridPtr); return FALSE; } coordinate_t prevCoordinate; grid_getPointIndices(gridPtr, prevGridPointPtr, &prevCoordinate.x, &prevCoordinate.y, &prevCoordinate.z); long numPoint = vector_getSize(pointVectorPtr); long j; for (j = 1; j < (numPoint-1); j++) { /* no need to check endpoints */ long* currGridPointPtr = (long*)vector_at(pointVectorPtr, j); coordinate_t currCoordinate; grid_getPointIndices(gridPtr, currGridPointPtr, &currCoordinate.x, &currCoordinate.y, &currCoordinate.z); if (!coordinate_areAdjacent(&currCoordinate, &prevCoordinate)) { grid_free(testGridPtr); return FALSE; } prevCoordinate = currCoordinate; long x = currCoordinate.x; long y = currCoordinate.y; long z = currCoordinate.z; if (grid_getPoint(testGridPtr, x, y, z) != GRID_POINT_EMPTY) { grid_free(testGridPtr); return FALSE; } else { grid_setPoint(testGridPtr, x, y, z, id); } } /* Check end */ long* lastGridPointPtr = (long*)vector_at(pointVectorPtr, j); grid_getPointIndices(gridPtr, lastGridPointPtr, &x, &y, &z); if (grid_getPoint(testGridPtr, x, y, z) != 0) { grid_free(testGridPtr); return FALSE; } } /* iteratate over pathVector */ } /* iterate over pathVectorList */ if (doPrintPaths) { puts("\nRouted Maze:"); grid_print(testGridPtr); } grid_free(testGridPtr); return TRUE; }
/* ============================================================================= * maze_read * -- Return number of path to route * ============================================================================= */ long maze_read (maze_t* mazePtr, char* inputFileName) { FILE* inputFile = fopen(inputFileName, "rt"); if (!inputFile) { fprintf(stderr, "Error: Could not read %s\n", inputFileName); exit(1); } /* * Parse input file */ long lineNumber = 0; long height = -1; long width = -1; long depth = -1; char line[256]; list_t* workListPtr = list_alloc(&coordinate_comparePair); vector_t* wallVectorPtr = mazePtr->wallVectorPtr; vector_t* srcVectorPtr = mazePtr->srcVectorPtr; vector_t* dstVectorPtr = mazePtr->dstVectorPtr; while (fgets(line, sizeof(line), inputFile)) { char code; long x1, y1, z1; long x2, y2, z2; long numToken = sscanf(line, " %c %li %li %li %li %li %li", &code, &x1, &y1, &z1, &x2, &y2, &z2); lineNumber++; if (numToken < 1) { continue; } switch (code) { case '#': { /* comment */ /* ignore line */ break; } case 'd': { /* dimensions (format: d x y z) */ if (numToken != 4) { goto PARSE_ERROR; } width = x1; height = y1; depth = z1; if (width < 1 || height < 1 || depth < 1) { goto PARSE_ERROR; } break; } case 'p': { /* paths (format: p x1 y1 z1 x2 y2 z2) */ if (numToken != 7) { goto PARSE_ERROR; } coordinate_t* srcPtr = coordinate_alloc(x1, y1, z1); coordinate_t* dstPtr = coordinate_alloc(x2, y2, z2); assert(srcPtr); assert(dstPtr); if (coordinate_isEqual(srcPtr, dstPtr)) { goto PARSE_ERROR; } pair_t* coordinatePairPtr = pair_alloc(srcPtr, dstPtr); assert(coordinatePairPtr); bool_t status = list_insert(workListPtr, (void*)coordinatePairPtr); assert(status == TRUE); vector_pushBack(srcVectorPtr, (void*)srcPtr); vector_pushBack(dstVectorPtr, (void*)dstPtr); break; } case 'w': { /* walls (format: w x y z) */ if (numToken != 4) { goto PARSE_ERROR; } coordinate_t* wallPtr = coordinate_alloc(x1, y1, z1); vector_pushBack(wallVectorPtr, (void*)wallPtr); break; } PARSE_ERROR: default: { /* error */ fprintf(stderr, "Error: line %li of %s invalid\n", lineNumber, inputFileName); exit(1); } } } /* iterate over lines in input file */ fclose(inputFile); /* * Initialize grid contents */ if (width < 1 || height < 1 || depth < 1) { fprintf(stderr, "Error: Invalid dimensions (%li, %li, %li)\n", width, height, depth); exit(1); } grid_t* gridPtr = grid_alloc(width, height, depth); assert(gridPtr); mazePtr->gridPtr = gridPtr; addToGrid(gridPtr, wallVectorPtr, "wall"); addToGrid(gridPtr, srcVectorPtr, "source"); addToGrid(gridPtr, dstVectorPtr, "destination"); printf("Maze dimensions = %li x %li x %li\n", width, height, depth); printf("Paths to route = %li\n", list_getSize(workListPtr)); /* * Initialize work queue */ queue_t* workQueuePtr = mazePtr->workQueuePtr; list_iter_t it; list_iter_reset(&it, workListPtr); while (list_iter_hasNext(&it)) { pair_t* coordinatePairPtr = (pair_t*)list_iter_next(&it); queue_push(workQueuePtr, (void*)coordinatePairPtr); } list_free(workListPtr); return vector_getSize(srcVectorPtr); }