core, lib, modules: restructured source code tree
[sip-router] / src / lib / cds / serialize.c
1 /* 
2  * Copyright (C) 2005 iptelorg GmbH
3  *
4  * This file is part of ser, a free SIP server.
5  *
6  * ser is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version
10  *
11  * For a license to use the ser software under conditions
12  * other than those described here, or to purchase support for this
13  * software, please contact iptel.org by e-mail at the following addresses:
14  *    info@iptel.org
15  *
16  * ser is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
24  */
25
26 #include <cds/serialize.h>
27 #include <cds/logger.h>
28 #include <stdio.h>
29
30 int init_input_sstream(sstream_t *ss, char *data_in, int data_len)
31 {
32         if (!ss) return -1;
33         
34         ss->type = sstream_in;
35         ss->in.len = data_len;
36         ss->in.s = data_in;
37         ss->in_pos = 0;
38         return 0;
39 }
40
41 int init_output_sstream(sstream_t *ss, int out_buff_resize)
42 {
43         if (!ss) return -1;
44         
45         ss->type = sstream_out;
46         str_clear(&ss->in);
47         ss->in_pos = 0;
48         dstr_init(&ss->out, out_buff_resize);
49         return 0;
50 }
51
52 int get_serialized_sstream(sstream_t *ss, str_t *dst)
53 {
54         if (ss->type == sstream_out) return dstr_get_str(&ss->out, dst);
55         else return -1; /* no output for input stream */
56 }
57
58 int get_serialized_sstream_data(sstream_t *ss, char *dst)
59 {
60         if (ss->type == sstream_out) return dstr_get_data(&ss->out, dst);
61         else return -1; /* no output for input stream */
62 }
63
64 int get_serialized_sstream_len(sstream_t *ss)
65 {
66         if (ss->type == sstream_out) return dstr_get_data_length(&ss->out);
67         else return 0; /* no output for input stream */
68 }
69
70 int sstream_get(sstream_t *ss, char *c)
71 {
72         /* if (!is_input_sstream(ss)) return -1;  */ /* optimalization */
73         /* if (!c) return -1; */ /* dangerous optimalization */
74         if (ss->in_pos < ss->in.len) {
75                 *c = ss->in.s[ss->in_pos++];
76                 return 0;
77         }
78         else return 1;
79 }
80
81 int sstream_put_str(sstream_t *ss, str_t *s)
82 {
83         /* if (is_input_sstream(ss)) return -1;  */ /* dangerous optimalization */
84         return dstr_append_str(&ss->out, s);
85 }
86
87 /* returns a part of string of given length - it is NOT a copy !!! */
88 int sstream_get_str_ex(sstream_t *ss, int len, str_t *dst)
89 {
90         int l;
91         int res = 0;
92         
93         if (!is_input_sstream(ss)) return -1;
94         if (!dst) return -1;
95
96         if (len == 0) {
97                 str_clear(dst);
98                 return 0;
99         }
100         
101         l = ss->in.len - ss->in_pos;
102         dst->s = ss->in.s + ss->in_pos;
103
104         if (len > l) {
105                 dst->len = l;
106                 res = 1; /* not whole requested string is returned ! */
107         }
108         else dst->len = len;
109         ss->in_pos += dst->len;
110         
111         return 0;
112 }
113
114 /* returns a copy of string from input buffer */
115 int sstream_get_str(sstream_t *ss, int len, str_t *dst)
116 {
117         str_t tmp;
118         int res = sstream_get_str_ex(ss, len, &tmp);
119         if (res >= 0) {
120                 res = str_dup(dst, &tmp);
121                 if (res != 0) str_clear(dst);
122         }
123         return res;
124 }
125
126 int sstream_put_zt(sstream_t *ss, const char *s)
127 {
128         /* if (!is_input_sstream(ss)) return -1;  */ /* dangerous optimalization */
129         return dstr_append_zt(&ss->out, s);
130 }
131
132 int sstream_put(sstream_t *ss, const char *s, int len)
133 {
134         /* if (!is_input_sstream(ss)) return -1;  */ /* dangerous optimalization */
135         return dstr_append(&ss->out, s, len);
136 }
137
138 void destroy_sstream(sstream_t *ss)
139 {
140         if (ss->type == sstream_out) dstr_destroy(&ss->out);
141 }
142
143 /*****************************************************************/
144
145 int serialize_int(sstream_t *ss, int *num)
146 {
147         char sep = ':';
148         
149         if (!num) return -1;
150         
151         if (is_input_sstream(ss)) {
152                 char c;
153                 int first = 1;
154                 int sign = 1; /* positive */
155                 
156                 *num = 0;
157                 while (sstream_get(ss, &c) == 0) {
158                         if (c == sep) break;
159                         if ((c >= '0') && (c <= '9')) *num = 10 * (*num) + (c - '0');
160                         else {
161                                 switch (c) {
162                                         case '-': 
163                                                 if (first) sign = -1;
164                                                 else return -1;
165                                         case '+': 
166                                                 if (!first) return -1;
167                                         default: 
168                                                 return -1; /* unknown character */
169                                 }
170                         }
171                         first = 0;
172                 }
173                 *num = sign * (*num);
174         }
175         else {
176                 char tmp[32];
177
178                 sprintf(tmp, "%d%c", *num, sep);
179                 sstream_put_zt(ss, tmp);
180         }
181         return 0;
182 }
183
184 int serialize_uint(sstream_t *ss, unsigned int *num)
185 {
186         char sep = ':';
187         
188         if (!num) return -1;
189         
190         if (is_input_sstream(ss)) {
191                 char c;
192                 
193                 *num = 0;
194                 while (sstream_get(ss, &c) == 0) {
195                         if (c == sep) break;
196                         if ((c >= '0') && (c <= '9')) *num = 10 * (*num) + (c - '0');
197                         else return -1; /* unknown character */
198                 }
199         }
200         else {
201                 char tmp[32];
202
203                 sprintf(tmp, "%u%c", *num, sep);
204                 sstream_put_zt(ss, tmp);
205         }
206         return 0;
207 }
208
209 int serialize_str(sstream_t *ss, str_t *s)
210 {
211         int res = 0;
212         
213         if (!s) return -1; 
214         
215         if (serialize_int(ss, &s->len) != 0) return -1;
216         if (is_input_sstream(ss)) {
217                 if (s->len == 0) s->s = NULL;
218                 else res = sstream_get_str(ss, s->len, s); /* duplicates read string */
219         }
220         else res = sstream_put(ss, s->s, s->len);
221
222         return res;
223 }
224
225 int serialize_str_ex(sstream_t *ss, str_t *s)
226 {
227         int res = 0;
228         
229         if (!s) return -1; 
230         
231         if (serialize_int(ss, &s->len) != 0) return -1;
232         if (is_input_sstream(ss)) {
233                 if (s->len == 0) s->s = NULL;
234                 else res = sstream_get_str_ex(ss, s->len, s); /* doesn't duplicate read string */
235         }
236         else res = sstream_put(ss, s->s, s->len);
237
238         return res;
239 }
240
241 int serialize_char(sstream_t *ss, char *c)
242 {
243         if (!c) return -1;
244         if (is_input_sstream(ss)) return sstream_get(ss, c);
245         else return sstream_put(ss, c, 1);
246 }
247
248 int serialize_uchar(sstream_t *ss, unsigned char *c)
249 {
250         if (!c) return -1;
251         if (is_input_sstream(ss)) return sstream_get(ss, (char *)c);
252         else return sstream_put(ss, (char *)c, 1);
253 }