Esempio n. 1
0
File: xreq.c Progetto: gridmq/gridmq
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;
}
Esempio n. 2
0
File: xreq.c Progetto: gridmq/gridmq
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;
}
Esempio n. 3
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;
}
Esempio n. 4
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;
}
Esempio n. 5
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;
}
Esempio n. 6
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;
}
Esempio n. 7
0
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;
}
Esempio n. 8
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;
}
Esempio n. 9
0
/* =============================================================================
 * 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);
}