Example #1
0
int main(void) {
    int in[NSTR];
    int i, j, k;
    unsigned seed = 0;

    for (i = 0; i < NSTR; i++) in[i] = 0;
    array = NULL;
    arraylen = arraysize = 0;
    tree = newtree234(mycmp);
    cmp = mycmp;

    verify();
    for (i = 0; i < 10000; i++) {
        j = randomnumber(&seed);
        j %= NSTR;
        printf("trial: %d\n", i);
        if (in[j]) {
            printf("deleting %s (%d)\n", strings[j], j);
            deltest(strings[j]);
            in[j] = 0;
        } else {
            printf("adding %s (%d)\n", strings[j], j);
            addtest(strings[j]);
            in[j] = 1;
        }
	findtest();
    }

    while (arraylen > 0) {
        j = randomnumber(&seed);
        j %= arraylen;
        deltest(array[j]);
    }

    freetree234(tree);

    tree = newtree234(NULL);
    cmp = NULL;
    verify();
    for (i = 0; i < 1000; i++) {
	printf("trial: %d\n", i);
	j = randomnumber(&seed);
	j %= NSTR;
	k = randomnumber(&seed);
	k %= count234(tree)+1;
	printf("adding string %s at index %d\n", strings[j], k);
	addpostest(strings[j], k);
    }
    while (count234(tree) > 0) {
	printf("cleanup: tree size %d\n", count234(tree));
	j = randomnumber(&seed);
	j %= count234(tree);
	printf("deleting string %s from index %d\n", array[j], j);
	delpostest(j);
    }

    return 0;
}
Example #2
0
static struct sftp_request *sftp_alloc_request(void)
{
    unsigned low, high, mid;
    int tsize;
    struct sftp_request *r;

    if (sftp_requests == NULL)
	sftp_requests = newtree234(sftp_reqcmp);

    /*
     * First-fit allocation of request IDs: always pick the lowest
     * unused one. To do this, binary-search using the counted
     * B-tree to find the largest ID which is in a contiguous
     * sequence from the beginning. (Precisely everything in that
     * sequence must have ID equal to its tree index plus
     * REQUEST_ID_OFFSET.)
     */
    tsize = count234(sftp_requests);

    low = -1;
    high = tsize;
    while (high - low > 1) {
	mid = (high + low) / 2;
	r = index234(sftp_requests, mid);
	if (r->id == mid + REQUEST_ID_OFFSET)
	    low = mid;		       /* this one is fine */
	else
	    high = mid;		       /* this one is past it */
    }
    /*
     * Now low points to either -1, or the tree index of the
     * largest ID in the initial sequence.
     */
    {
	unsigned i = low + 1 + REQUEST_ID_OFFSET;
	assert(NULL == find234(sftp_requests, &i, sftp_reqfind));
    }

    /*
     * So the request ID we need to create is
     * low + 1 + REQUEST_ID_OFFSET.
     */
    r = snew(struct sftp_request);
    r->id = low + 1 + REQUEST_ID_OFFSET;
    r->registered = false;
    r->userdata = NULL;
    add234(sftp_requests, r);
    return r;
}
Example #3
0
void verify(void)
{
    chkctx ctx;
    int i;
    void *p;

    ctx.treedepth = -1;		       /* depth unknown yet */
    ctx.elemcount = 0;		       /* no elements seen yet */
    /*
     * Verify validity of tree properties.
     */
    if (tree->root) {
	if (tree->root->parent != NULL)
	    error("root->parent is %p should be null", tree->root->parent);
	chknode(&ctx, 0, tree->root, NULL, NULL);
    }
    printf("tree depth: %d\n", ctx.treedepth);
    /*
     * Enumerate the tree and ensure it matches up to the array.
     */
    for (i = 0; NULL != (p = index234(tree, i)); i++) {
	if (i >= arraylen)
	    error("tree contains more than %d elements", arraylen);
	if (array[i] != p)
	    error("enum at position %d: array says %s, tree says %s",
		  i, array[i], p);
    }
    if (ctx.elemcount != i) {
	error("tree really contains %d elements, enum gave %d",
	      ctx.elemcount, i);
    }
    if (i < arraylen) {
	error("enum gave only %d elements, array has %d", i, arraylen);
    }
    i = count234(tree);
    if (ctx.elemcount != i) {
	error("tree really contains %d elements, count234 gave %d",
	      ctx.elemcount, i);
    }
}
Example #4
0
int main(void) {
    int in[NSTR];
    int i, j, k;
    unsigned seed = 0;

    for (i = 0; i < NSTR; i++) in[i] = 0;
    array = NULL;
    arraylen = arraysize = 0;
    tree = newtree234(mycmp);
    cmp = mycmp;

    verify();
    for (i = 0; i < 10000; i++) {
        j = randomnumber(&seed);
        j %= NSTR;
        printf("trial: %d\n", i);
        if (in[j]) {
            printf("deleting %s (%d)\n", strings[j], j);
            deltest(strings[j]);
            in[j] = 0;
        } else {
            printf("adding %s (%d)\n", strings[j], j);
            addtest(strings[j]);
            in[j] = 1;
        }
	findtest();
    }

    while (arraylen > 0) {
        j = randomnumber(&seed);
        j %= arraylen;
        deltest(array[j]);
    }

    freetree234(tree);

    /*
     * Now try an unsorted tree. We don't really need to test
     * delpos234 because we know del234 is based on it, so it's
     * already been tested in the above sorted-tree code; but for
     * completeness we'll use it to tear down our unsorted tree
     * once we've built it.
     */
    tree = newtree234(NULL);
    cmp = NULL;
    verify();
    for (i = 0; i < 1000; i++) {
	printf("trial: %d\n", i);
	j = randomnumber(&seed);
	j %= NSTR;
	k = randomnumber(&seed);
	k %= count234(tree)+1;
	printf("adding string %s at index %d\n", strings[j], k);
	addpostest(strings[j], k);
    }
    while (count234(tree) > 0) {
	printf("cleanup: tree size %d\n", count234(tree));
	j = randomnumber(&seed);
	j %= count234(tree);
	printf("deleting string %s from index %d\n", array[j], j);
	delpostest(j);
    }

    return 0;
}
Example #5
0
/**
 * SER2Jab connection management - function to use with iHttp module
 * - be aware of who is able to use the ihttp because he can close any 
 *   open connection between SER and Jabber server
 */ 
int xjab_connections(ih_req_p _irp, void *_p, char *_bb, int *_bl, 
		char *_hb, int *_hl)
{
	t_xj_jkey jkey, *p;
	str _u;
	ih_param_p _ipp = NULL;
	int idx, i, maxcount;
	char *cp;

	if(!_irp || !_bb || !_bl || *_bl <= 0 || !_hb || !_hl || *_hl <= 0)
		return -1;
	
	*_hl = 0;
	*_hb = 0;
	idx = -1;
	strcpy(_bb, "<h4>Active XMPP connections</h4>");
	
	if(_irp->params)
	{
		strcat(_bb, "<br><b>Close action is alpha release!</b><br>");
		_ipp = _irp->params;
		i = 0;
		while(_ipp)
		{
			switch(_ipp->name[0])
			{
				case 'w':
					idx = 0;
					cp = _ipp->value;
					while(*cp && *cp>='0' && *cp<='9')
					{
						idx = idx*10 + *cp-'0';
						cp++;
					}
					i++;
				break;
				case 'u':
					_u.s = _ipp->value;
					_u.len = strlen(_ipp->value);
					jkey.id = &_u;
					i++;
				break;
				case 'i':
					jkey.hash = 0;
					cp = _ipp->value;
					while(*cp && *cp>='0' && *cp<='9')
					{
						jkey.hash = jkey.hash*10 + *cp-'0';
						cp++;
					}
					i++;
				break;
				
			}
			_ipp = _ipp->next;
		}
		if(i!=3 || idx < 0 || idx >= jwl->len)
		{
			strcat(_bb, "<br><b><i>Bad parameters!</i></b>\n");
		}
		else
		{
			strcat(_bb, "<br><b><i>The connection of [");
			strcat(_bb, _u.s);

			if(xj_wlist_set_flag(jwl, &jkey, XJ_FLAG_CLOSE) < 0)
				strcat(_bb, "] does not exist!</i></b>\n");
			else
				strcat(_bb, "] was scheduled for closing!</i></b>\n");
		}
		*_bl = strlen(_bb);

		return 0;
	}
	
	if(jwl!=NULL && jwl->len > 0 && jwl->workers!=NULL)
	{
		for(idx=0; idx<jwl->len; idx++)
		{
			strcat(_bb, "<br><b><i>Worker[");
			strcat(_bb, int2str(idx, NULL));
			strcat(_bb, "]</i></b> &nbsp;&nbsp;pid=");
			strcat(_bb, int2str(jwl->workers[idx].pid, NULL));
			strcat(_bb, " &nbsp;&nbsp;nr of jobs=");
			strcat(_bb, int2str(jwl->workers[idx].nr, NULL));
			if(!jwl->workers[idx].sip_ids)
				continue;
			lock_set_get(jwl->sems, idx);
			maxcount = count234(jwl->workers[idx].sip_ids);
			for (i = 0; i < maxcount; i++) 
			{
				p = (xj_jkey)index234(jwl->workers[idx].sip_ids, i);
				if(p == NULL)
					continue;
				strcat(_bb, "<br>&nbsp;&nbsp;&nbsp;");
				strcat(_bb, int2str(i, NULL));
				strcat(_bb, ".&nbsp;&nbsp;&nbsp;");
				strcat(_bb, "<a href=\"xjabc?w=");
				strcat(_bb, int2str(idx, NULL));
				strcat(_bb, "&i=");
				strcat(_bb, int2str(p->hash, NULL));
				strcat(_bb, "&u=");
				strncat(_bb, p->id->s, p->id->len);
				strcat(_bb, "\">close</a>");
				strcat(_bb, "&nbsp;&nbsp;&nbsp;");
				strcat(_bb, int2str(p->hash, NULL));
				strcat(_bb, "&nbsp;&nbsp;&nbsp;");
				strncat(_bb, p->id->s, p->id->len);
			}
			lock_set_release(jwl->sems, idx);
		}
	}
	
	*_bl = strlen(_bb);

	return 0;
}
Example #6
0
/*
 * Generate a new complete random closed loop for the given grid.
 *
 * The method is to generate a WHITE/BLACK colouring of all the faces,
 * such that the WHITE faces will define the inside of the path, and the
 * BLACK faces define the outside.
 * To do this, we initially colour all faces GREY.  The infinite space outside
 * the grid is coloured BLACK, and we choose a random face to colour WHITE.
 * Then we gradually grow the BLACK and the WHITE regions, eliminating GREY
 * faces, until the grid is filled with BLACK/WHITE.  As we grow the regions,
 * we avoid creating loops of a single colour, to preserve the topological
 * shape of the WHITE and BLACK regions.
 * We also try to make the boundary as loopy and twisty as possible, to avoid
 * generating paths that are uninteresting.
 * The algorithm works by choosing a BLACK/WHITE colour, then choosing a GREY
 * face that can be coloured with that colour (without violating the
 * topological shape of that region).  It's not obvious, but I think this
 * algorithm is guaranteed to terminate without leaving any GREY faces behind.
 * Indeed, if there are any GREY faces at all, both the WHITE and BLACK
 * regions can be grown.
 * This is checked using assert()ions, and I haven't seen any failures yet.
 *
 * Hand-wavy proof: imagine what can go wrong...
 *
 * Could the white faces get completely cut off by the black faces, and still
 * leave some grey faces remaining?
 * No, because then the black faces would form a loop around both the white
 * faces and the grey faces, which is disallowed because we continually
 * maintain the correct topological shape of the black region.
 * Similarly, the black faces can never get cut off by the white faces.  That
 * means both the WHITE and BLACK regions always have some room to grow into
 * the GREY regions.
 * Could it be that we can't colour some GREY face, because there are too many
 * WHITE/BLACK transitions as we walk round the face? (see the
 * can_colour_face() function for details)
 * No.  Imagine otherwise, and we see WHITE/BLACK/WHITE/BLACK as we walk
 * around the face.  The two WHITE faces would be connected by a WHITE path,
 * and the BLACK faces would be connected by a BLACK path.  These paths would
 * have to cross, which is impossible.
 * Another thing that could go wrong: perhaps we can't find any GREY face to
 * colour WHITE, because it would create a loop-violation or a corner-violation
 * with the other WHITE faces?
 * This is a little bit tricky to prove impossible.  Imagine you have such a
 * GREY face (that is, if you coloured it WHITE, you would create a WHITE loop
 * or corner violation).
 * That would cut all the non-white area into two blobs.  One of those blobs
 * must be free of BLACK faces (because the BLACK stuff is a connected blob).
 * So we have a connected GREY area, completely surrounded by WHITE
 * (including the GREY face we've tentatively coloured WHITE).
 * A well-known result in graph theory says that you can always find a GREY
 * face whose removal leaves the remaining GREY area connected.  And it says
 * there are at least two such faces, so we can always choose the one that
 * isn't the "tentative" GREY face.  Colouring that face WHITE leaves
 * everything nice and connected, including that "tentative" GREY face which
 * acts as a gateway to the rest of the non-WHITE grid.
 */
void generate_loop(grid *g, char *board, random_state *rs,
                   loopgen_bias_fn_t bias, void *biasctx)
{
    int i, j;
    int num_faces = g->num_faces;
    struct face_score *face_scores; /* Array of face_score objects */
    struct face_score *fs; /* Points somewhere in the above list */
    struct grid_face *cur_face;
    tree234 *lightable_faces_sorted;
    tree234 *darkable_faces_sorted;
    int *face_list;
    int do_random_pass;

    /* Make a board */
    memset(board, FACE_GREY, num_faces);
    
    /* Create and initialise the list of face_scores */
    face_scores = snewn(num_faces, struct face_score);
    for (i = 0; i < num_faces; i++) {
        face_scores[i].random = random_bits(rs, 31);
        face_scores[i].black_score = face_scores[i].white_score = 0;
    }
    
    /* Colour a random, finite face white.  The infinite face is implicitly
     * coloured black.  Together, they will seed the random growth process
     * for the black and white areas. */
    i = random_upto(rs, num_faces);
    board[i] = FACE_WHITE;

    /* We need a way of favouring faces that will increase our loopiness.
     * We do this by maintaining a list of all candidate faces sorted by
     * their score and choose randomly from that with appropriate skew.
     * In order to avoid consistently biasing towards particular faces, we
     * need the sort order _within_ each group of scores to be completely
     * random.  But it would be abusing the hospitality of the tree234 data
     * structure if our comparison function were nondeterministic :-).  So with
     * each face we associate a random number that does not change during a
     * particular run of the generator, and use that as a secondary sort key.
     * Yes, this means we will be biased towards particular random faces in
     * any one run but that doesn't actually matter. */

    lightable_faces_sorted = newtree234(white_sort_cmpfn);
    darkable_faces_sorted = newtree234(black_sort_cmpfn);

    /* Initialise the lists of lightable and darkable faces.  This is
     * slightly different from the code inside the while-loop, because we need
     * to check every face of the board (the grid structure does not keep a
     * list of the infinite face's neighbours). */
    for (i = 0; i < num_faces; i++) {
        grid_face *f = g->faces + i;
        struct face_score *fs = face_scores + i;
        if (board[i] != FACE_GREY) continue;
        /* We need the full colourability check here, it's not enough simply
         * to check neighbourhood.  On some grids, a neighbour of the infinite
         * face is not necessarily darkable. */
        if (can_colour_face(g, board, i, FACE_BLACK)) {
            fs->black_score = face_score(g, board, f, FACE_BLACK);
            add234(darkable_faces_sorted, fs);
        }
        if (can_colour_face(g, board, i, FACE_WHITE)) {
            fs->white_score = face_score(g, board, f, FACE_WHITE);
            add234(lightable_faces_sorted, fs);
        }
    }

    /* Colour faces one at a time until no more faces are colourable. */
    while (TRUE)
    {
        enum face_colour colour;
        tree234 *faces_to_pick;
        int c_lightable = count234(lightable_faces_sorted);
        int c_darkable = count234(darkable_faces_sorted);
        if (c_lightable == 0 && c_darkable == 0) {
            /* No more faces we can use at all. */
            break;
        }
	assert(c_lightable != 0 && c_darkable != 0);

        /* Choose a colour, and colour the best available face
         * with that colour. */
        colour = random_upto(rs, 2) ? FACE_WHITE : FACE_BLACK;

        if (colour == FACE_WHITE)
            faces_to_pick = lightable_faces_sorted;
        else
            faces_to_pick = darkable_faces_sorted;
        if (bias) {
            /*
             * Go through all the candidate faces and pick the one the
             * bias function likes best, breaking ties using the
             * ordering in our tree234 (which is why we replace only
             * if score > bestscore, not >=).
             */
            int j, k;
            struct face_score *best = NULL;
            int score, bestscore = 0;

            for (j = 0;
                 (fs = (struct face_score *)index234(faces_to_pick, j))!=NULL;
                 j++) {

                assert(fs);
                k = fs - face_scores;
                assert(board[k] == FACE_GREY);
                board[k] = colour;
                score = bias(biasctx, board, k);
                board[k] = FACE_GREY;
                bias(biasctx, board, k); /* let bias know we put it back */

                if (!best || score > bestscore) {
                    bestscore = score;
                    best = fs;
                }
            }
            fs = best;
        } else {
            fs = (struct face_score *)index234(faces_to_pick, 0);
        }
        assert(fs);
        i = fs - face_scores;
        assert(board[i] == FACE_GREY);
        board[i] = colour;
        if (bias)
            bias(biasctx, board, i); /* notify bias function of the change */

        /* Remove this newly-coloured face from the lists.  These lists should
         * only contain grey faces. */
        del234(lightable_faces_sorted, fs);
        del234(darkable_faces_sorted, fs);

        /* Remember which face we've just coloured */
        cur_face = g->faces + i;

        /* The face we've just coloured potentially affects the colourability
         * and the scores of any neighbouring faces (touching at a corner or
         * edge).  So the search needs to be conducted around all faces
         * touching the one we've just lit.  Iterate over its corners, then
         * over each corner's faces.  For each such face, we remove it from
         * the lists, recalculate any scores, then add it back to the lists
         * (depending on whether it is lightable, darkable or both). */
        for (i = 0; i < cur_face->order; i++) {
            grid_dot *d = cur_face->dots[i];
            for (j = 0; j < d->order; j++) {
                grid_face *f = d->faces[j];
                int fi; /* face index of f */

                if (f == NULL)
                    continue;
                if (f == cur_face)
                    continue;
                
                /* If the face is already coloured, it won't be on our
                 * lightable/darkable lists anyway, so we can skip it without 
                 * bothering with the removal step. */
                if (FACE_COLOUR(f) != FACE_GREY) continue; 

                /* Find the face index and face_score* corresponding to f */
                fi = f - g->faces;                
                fs = face_scores + fi;

                /* Remove from lightable list if it's in there.  We do this,
                 * even if it is still lightable, because the score might
                 * be different, and we need to remove-then-add to maintain
                 * correct sort order. */
                del234(lightable_faces_sorted, fs);
                if (can_colour_face(g, board, fi, FACE_WHITE)) {
                    fs->white_score = face_score(g, board, f, FACE_WHITE);
                    add234(lightable_faces_sorted, fs);
                }
                /* Do the same for darkable list. */
                del234(darkable_faces_sorted, fs);
                if (can_colour_face(g, board, fi, FACE_BLACK)) {
                    fs->black_score = face_score(g, board, f, FACE_BLACK);
                    add234(darkable_faces_sorted, fs);
                }
            }
        }
    }

    /* Clean up */
    freetree234(lightable_faces_sorted);
    freetree234(darkable_faces_sorted);
    sfree(face_scores);

    /* The next step requires a shuffled list of all faces */
    face_list = snewn(num_faces, int);
    for (i = 0; i < num_faces; ++i) {
        face_list[i] = i;
    }
    shuffle(face_list, num_faces, sizeof(int), rs);

    /* The above loop-generation algorithm can often leave large clumps
     * of faces of one colour.  In extreme cases, the resulting path can be 
     * degenerate and not very satisfying to solve.
     * This next step alleviates this problem:
     * Go through the shuffled list, and flip the colour of any face we can
     * legally flip, and which is adjacent to only one face of the opposite
     * colour - this tends to grow 'tendrils' into any clumps.
     * Repeat until we can find no more faces to flip.  This will
     * eventually terminate, because each flip increases the loop's
     * perimeter, which cannot increase for ever.
     * The resulting path will have maximal loopiness (in the sense that it
     * cannot be improved "locally".  Unfortunately, this allows a player to
     * make some illicit deductions.  To combat this (and make the path more
     * interesting), we do one final pass making random flips. */

    /* Set to TRUE for final pass */
    do_random_pass = FALSE;

    while (TRUE) {
        /* Remember whether a flip occurred during this pass */
        int flipped = FALSE;

        for (i = 0; i < num_faces; ++i) {
            int j = face_list[i];
            enum face_colour opp =
                (board[j] == FACE_WHITE) ? FACE_BLACK : FACE_WHITE;
            if (can_colour_face(g, board, j, opp)) {
                grid_face *face = g->faces +j;
                if (do_random_pass) {
                    /* final random pass */
                    if (!random_upto(rs, 10))
                        board[j] = opp;
                } else {
                    /* normal pass - flip when neighbour count is 1 */
                    if (face_num_neighbours(g, board, face, opp) == 1) {
                        board[j] = opp;
                        flipped = TRUE;
                    }
                }
            }
        }

        if (do_random_pass) break;
        if (!flipped) do_random_pass = TRUE;
    }

    sfree(face_list);
}
Example #7
0
void GuiFindToolBar::on_findDown()
{
    termline *line;
    tree234 *whichtree;
    unsigned long tchar;
    GuiTerminalWindow *gterm = mainWnd->getCurrentTerminal();
    Terminal *term;
    QScrollBar *scrollbar;
    QString str = "";
    int tempStartPosition = 0;
    int tempCol, tempRow;

    if (!gterm)
        return;

    term = gterm->term;
    scrollbar = gterm->verticalScrollBar();

    findTextFlag = true;
    if(getSearchedText() == "")
    {
        findTextFlag = false;
        gterm->viewport()->repaint();
        return;
    }
    tempCol = currentCol;
    tempRow = currentRow;
    currentCol = currentCol + currentSearchedText.length();

    if(getSearchedText().compare(currentSearchedText, Qt::CaseInsensitive))
    {
        pageStartPosition = scrollbar->value();
        currentSearchedText = getSearchedText();
        if(currentCol < 0)
            currentCol = 0;
        whichtree = NULL;
    }

    if(currentRow < 0)
        currentRow = scrollbar->value();

    while(1)
    {
        str = "";

        if(currentRow >= scrollbar->maximum()+term->rows)
        {
            currentRow = 0;
        }
        if(count234(term->scrollback) > currentRow)
        {
            whichtree = term->scrollback;
            unsigned char *cline = (unsigned char*)index234(whichtree, currentRow);
            line = (termline*) decompressline(cline, NULL);
        }
        else
        {
            whichtree = term->screen;
            line = (termline*)index234(whichtree, abs(currentRow - count234(term->scrollback)));
        }
        for(int i = 0; line && i < line->size; i++)
        {
            //qDebug() << line->chars[i].chr;
            tchar = line->chars[i].chr;
            switch (tchar & CSET_MASK)
            {
              case CSET_ASCII:
            tchar = term->ucsdata->unitab_line[tchar & 0xFF];
            break;
              case CSET_LINEDRW:
            tchar = term->ucsdata->unitab_xterm[tchar & 0xFF];
            break;
              case CSET_SCOACS:
            tchar = term->ucsdata->unitab_scoacs[tchar&0xFF];
            break;
            }
            str.append((char)tchar);
        }
        if(currentCol < term->cols && (currentCol = str.indexOf(currentSearchedText, currentCol, Qt::CaseInsensitive)) >= 0)
        {
            if(pageStartPosition != scrollbar->value())
                gterm->setScrollBar(scrollbar->maximum()+term->rows, pageStartPosition, term->rows);
            else
            {
                if(currentRow < scrollbar->value() || currentRow >= (scrollbar->value() + term->rows))
                {
                    gterm->setScrollBar(scrollbar->maximum()+term->rows, currentRow, term->rows);
                    pageStartPosition = scrollbar->value();
                }
            }
            currentSearchedText = str.mid(currentCol, currentSearchedText.length());
            tempStartPosition = pageStartPosition;
            break;
        }
        tempStartPosition++;
        if(tempStartPosition > (scrollbar->maximum()+term->rows))
        {
            findTextFlag = false;
            currentCol = tempCol;
            currentRow = tempRow;
            gterm->viewport()->repaint();
            return;
        }
        currentRow++;
        currentCol = 0;
    }
    gterm->viewport()->repaint();
}