File: ratSequence.c

package info (click to toggle)
tkrat 1%3A2.2cvs20100105-true-dfsg-6
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 10,328 kB
  • ctags: 9,259
  • sloc: ansic: 96,057; tcl: 25,667; makefile: 1,638; sh: 282
file content (160 lines) | stat: -rw-r--r-- 3,938 bytes parent folder | download | duplicates (4)
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);
}