pieterh / xump

Extensible Universal Message Processor

This URL has Read+Write access

xump / xump_headers.icl
100644 123 lines (105 sloc) 3.652 kb
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
<?xml?>
<!--
    Copyright (c) 1996-2009 iMatix Corporation
 
    This file is licensed under the GPL as follows:
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or (at
    your option) any later version.
 
    This program is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    General Public License for more details.
 
    For information on alternative licensing for OEMs, please contact
    iMatix Corporation.
 -->
<class
    name = "xump_headers"
    comment = "Xump headers class"
    script = "icl_gen"
    license = "gpl"
    opaque = "1"
    >
<doc>
The xump_headers class implements a environ-style headers block.
</doc>
 
<inherit class = "icl_object">
    <option name = "alloc" value = "cache" />
    <option name = "links" value = "1" />
</inherit>
 
<import class = "xump" />
 
<context>
    icl_longstr_t
        *longstr; // Data for headers table
</context>
 
<method name = "new">
    // Constructor is deliberately empty
</method>
 
<method name = "destroy">
    icl_longstr_destroy (&self->longstr);
</method>
 
<method name = "set" template = "function">
    <doc>
    Sets a header value.
    </doc>
    <argument name = "name" type = "char *" />
    <argument name = "value" type = "char *" />
    //
    // Name may not contain '=', that's a fail
    assert (strchr (name, '=') == NULL);
    if (self->longstr) {
        // Look for existing value, squash if any
        icl_shortstr_t
            name_key;
        char
            *found;
 
        icl_shortstr_fmt (name_key, "%s=", name);
        found = (char *) icl_longstr_find (
            self->longstr, 0, (byte *) name_key, strlen (name_key));
        if (found) {
            byte
                *next = (byte *) strchr (found, 0) + 1;
            self->longstr->cur_size -= (next - self->longstr->data);
            memcpy (found, next, self->longstr->cur_size);
        }
        // String ends in double null, we'll quash the last one
        if (self->longstr->cur_size)
            self->longstr->cur_size--;
    }
    else
        self->longstr = icl_longstr_new (NULL, 1024);
 
    icl_longstr_cat (self->longstr, "%s=%s%c%c", name, value, 0, 0);
</method>
 
<method name = "get" return = "value">
    <doc>
    Returns value of specified header; if not found returns an empty string.
    </doc>
    <argument name = "self" type = "$(selftype) *" />
    <argument name = "name" type = "char *" />
    <declare name = "value" type = "char *" />
    value = ""; // Default is empty string
    if (self->longstr) {
        icl_shortstr_t
            name_key;
        char
            *found;
 
        icl_shortstr_fmt (name_key, "%s=", name);
        found = (char *) icl_longstr_find (
            self->longstr, 0, (byte *) name_key, strlen (name_key));
        if (found)
            value = found + strlen (name_key);
    }
</method>
 
<method name = "selftest">
    xump_headers_t
        *headers;
 
    headers = xump_headers_new ();
    xump_headers_set (headers, "a", "one");
    xump_headers_set (headers, "b", "two");
    xump_headers_set (headers, "c", "three");
    xump_headers_set (headers, "a", "value");
    assert (streq (xump_headers_get (headers, "a"), "value"));
    assert (streq (xump_headers_get (headers, "z"), ""));
    xump_headers_destroy (&headers);
</method>
 
</class>