1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
/*
* ratSequence.c --
*
* This file contains code to build seqences of message numbers
*
* TkRat software and its included text is Copyright 1996-2005 by
* Martin Forssn
*
* The full text of the legal notice is contained in the file called
* COPYRIGHT, included with this distribution.
*/
#include "rat.h"
#define CHUNKSIZE 256
typedef struct {
int used;
int allocated;
unsigned long *elems;
Tcl_DString string;
} rat_int_sequence_t;
rat_sequence_t
RatSequenceInit(void)
{
rat_int_sequence_t *rs = (rat_int_sequence_t*)ckalloc(sizeof(*rs));
rs->used = 0;
rs->allocated = 0;
rs->elems = NULL;
Tcl_DStringInit(&rs->string);
return (rat_sequence_t)rs;
}
void
RatSequenceAdd(rat_sequence_t seq, unsigned long elem)
{
rat_int_sequence_t *rs = (rat_int_sequence_t*)seq;
int i;
if (rs->used == rs->allocated) {
rs->allocated += CHUNKSIZE;
rs->elems = (unsigned long*)ckrealloc(
rs->elems, rs->allocated * sizeof(unsigned long));
}
i=0;
while (rs->elems[i] < elem && i < rs->used) {
i++;
}
if (i == rs->used) {
rs->elems[rs->used] = elem;
} else {
if (rs->elems[i] == elem) {
return;
}
memmove(&rs->elems[i+1], &rs->elems[i],
sizeof(unsigned long)*(rs->used-i));
rs->elems[i] = elem;
}
rs->used++;
}
int
RatSequenceNotempty(rat_sequence_t seq)
{
rat_int_sequence_t *rs = (rat_int_sequence_t*)seq;
return rs->used;
}
char*
RatSequenceGet(rat_sequence_t seq)
{
rat_int_sequence_t *rs = (rat_int_sequence_t*)seq;
char buf[32];
int i, j;
if (Tcl_DStringLength(&rs->string)) {
Tcl_DStringSetLength(&rs->string, 0);
}
for (i=0; i<rs->used; i++) {
if (Tcl_DStringLength(&rs->string)) {
Tcl_DStringAppend(&rs->string, ",", 1);
}
snprintf(buf, sizeof(buf), "%lu", rs->elems[i]);
Tcl_DStringAppend(&rs->string, buf, -1);
j = i;
while(j < rs->used && rs->elems[j]+1 == rs->elems[j+1]) {
j++;
}
if (j > i+1) {
snprintf(buf, sizeof(buf), ":%lu", rs->elems[j]);
Tcl_DStringAppend(&rs->string, buf, -1);
i = j;
}
}
return Tcl_DStringValue(&rs->string);
}
void
RatSequenceFree(rat_sequence_t seq)
{
rat_int_sequence_t *rs = (rat_int_sequence_t*)seq;
Tcl_DStringFree(&rs->string);
ckfree(rs->elems);
ckfree(rs);
}
/*
* These functions are used for unit-testing
*/
static Tcl_ObjCmdProc RatSequenceCmd;
static Tcl_CmdDeleteProc RatSequenceDelProc;
int
RatCreateSequenceCmd(ClientData dummy, Tcl_Interp *interp, int objc,
Tcl_Obj *const objv[])
{
static int unique = 0;
char name[32];
snprintf(name, sizeof(name), "seq%d", unique++);
Tcl_CreateObjCommand(interp, name, RatSequenceCmd, RatSequenceInit(),
RatSequenceDelProc);
Tcl_SetResult(interp, name, TCL_VOLATILE);
return TCL_OK;
}
static int
RatSequenceCmd(ClientData clientData, Tcl_Interp *interp, int objc,
Tcl_Obj *const objv[])
{
rat_int_sequence_t *rs = (rat_int_sequence_t*)clientData;
long no;
if (objc == 3
&& !strcmp("add", Tcl_GetString(objv[1]))
&& TCL_OK == Tcl_GetLongFromObj(interp, objv[2], &no)) {
RatSequenceAdd(rs, no);
} else if (objc == 2 && !strcmp("get", Tcl_GetString(objv[1]))) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(RatSequenceGet(rs), -1));
} else if (objc == 2 && !strcmp("notempty", Tcl_GetString(objv[1]))) {
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(RatSequenceNotempty(rs)));
} else {
return TCL_ERROR;
}
return TCL_OK;
}
static void
RatSequenceDelProc(ClientData clientData)
{
rat_int_sequence_t *rs = (rat_int_sequence_t*)clientData;
RatSequenceFree(rs);
}
|