Integer type name change.
[silc.git] / lib / silccore / silcargument.c
1 /*
2
3   silcargument.c 
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2001 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19 /* Implementation of Argument Payload routines */ 
20 /* $Id$ */
21
22 #include "silcincludes.h"
23 #include "silcargument.h"
24
25 /******************************************************************************
26
27                              Argument Payload
28
29 ******************************************************************************/
30
31 struct SilcArgumentPayloadStruct {
32   SilcUInt32 argc;
33   unsigned char **argv;
34   SilcUInt32 *argv_lens;
35   SilcUInt32 *argv_types;
36   SilcUInt32 pos;
37 };
38
39 /* Parses arguments and returns them into Argument Payload structure. */
40
41 SilcArgumentPayload silc_argument_payload_parse(const unsigned char *payload,
42                                                 SilcUInt32 payload_len,
43                                                 SilcUInt32 argc)
44 {
45   SilcBufferStruct buffer;
46   SilcArgumentPayload new;
47   SilcUInt16 p_len = 0;
48   unsigned char arg_num = 0;
49   unsigned char arg_type = 0;
50   SilcUInt32 pull_len = 0;
51   int i = 0, ret;
52
53   SILC_LOG_DEBUG(("Parsing argument payload"));
54
55   silc_buffer_set(&buffer, (unsigned char *)payload, payload_len);
56   new = silc_calloc(1, sizeof(*new));
57   new->argv = silc_calloc(argc, sizeof(unsigned char *));
58   new->argv_lens = silc_calloc(argc, sizeof(SilcUInt32));
59   new->argv_types = silc_calloc(argc, sizeof(SilcUInt32));
60     
61   /* Get arguments */
62   arg_num = 1;
63   for (i = 0; i < argc; i++) {
64     ret = silc_buffer_unformat(&buffer,
65                                SILC_STR_UI_SHORT(&p_len),
66                                SILC_STR_UI_CHAR(&arg_type),
67                                SILC_STR_END);
68     if (ret == -1)
69       goto err;
70     
71     new->argv_lens[i] = p_len;
72     new->argv_types[i] = arg_type;
73
74     if (p_len > buffer.len - 3)
75       break;
76     
77     /* Get argument data */
78     silc_buffer_pull(&buffer, 3);
79     ret = silc_buffer_unformat(&buffer,
80                                SILC_STR_UI_XNSTRING_ALLOC(&new->argv[i], 
81                                                           p_len),
82                                SILC_STR_END);
83     if (ret == -1)
84       goto err;
85
86     silc_buffer_pull(&buffer, p_len);
87     pull_len += 3 + p_len;
88   }
89
90   if (buffer.len != 0)
91     goto err;
92
93   new->argc = argc;
94   new->pos = 0;
95
96   silc_buffer_push(&buffer, pull_len);
97
98   return new;
99
100  err:
101   if (i) {
102     int k;
103
104     for (k = 0; k < i; k++)
105       silc_free(new->argv[k]);
106   }
107
108   silc_free(new->argv);
109   silc_free(new->argv_lens);
110   silc_free(new->argv_types);
111
112   if (new)
113     silc_free(new);
114
115   return NULL;
116 }
117
118 /* Encodes arguments in to Argument Paylods returning them to SilcBuffer. */
119
120 SilcBuffer silc_argument_payload_encode(SilcUInt32 argc,
121                                         unsigned char **argv,
122                                         SilcUInt32 *argv_lens,
123                                         SilcUInt32 *argv_types)
124 {
125   SilcBuffer buffer;
126   SilcUInt32 len;
127   int i;
128
129   SILC_LOG_DEBUG(("Encoding Argument payload"));
130
131   len = 0;
132   for (i = 0; i < argc; i++)
133     len += 3 + argv_lens[i];
134
135   buffer = silc_buffer_alloc(len);
136   silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
137
138   /* Put arguments */
139   for (i = 0; i < argc; i++) {
140     silc_buffer_format(buffer,
141                        SILC_STR_UI_SHORT(argv_lens[i]),
142                        SILC_STR_UI_CHAR(argv_types[i]),
143                        SILC_STR_UI_XNSTRING(argv[i], argv_lens[i]),
144                        SILC_STR_END);
145     silc_buffer_pull(buffer, 3 + argv_lens[i]);
146   }
147
148   silc_buffer_push(buffer, len);
149
150   return buffer;
151 }
152
153 /* Same as above but encode the buffer from SilcArgumentPayload structure
154    instead of raw data. */
155
156 SilcBuffer silc_argument_payload_encode_payload(SilcArgumentPayload payload)
157 {
158   SilcBuffer buffer;
159   SilcUInt32 len;
160   int i;
161
162   SILC_LOG_DEBUG(("Encoding Argument payload"));
163
164   len = 0;
165   for (i = 0; i < payload->argc; i++)
166     len += 3 + payload->argv_lens[i];
167
168   buffer = silc_buffer_alloc(len);
169   silc_buffer_pull_tail(buffer, SILC_BUFFER_END(buffer));
170
171   /* Put arguments */
172   for (i = 0; i < payload->argc; i++) {
173     silc_buffer_format(buffer,
174                        SILC_STR_UI_SHORT(payload->argv_lens[i]),
175                        SILC_STR_UI_CHAR(payload->argv_types[i]),
176                        SILC_STR_UI_XNSTRING(payload->argv[i], 
177                                             payload->argv_lens[i]),
178                        SILC_STR_END);
179     silc_buffer_pull(buffer, 3 + payload->argv_lens[i]);
180   }
181
182   silc_buffer_push(buffer, len);
183
184   return buffer;
185 }
186
187 /* Frees Argument Payload */
188
189 void silc_argument_payload_free(SilcArgumentPayload payload)
190 {
191   int i;
192
193   if (payload) {
194     for (i = 0; i < payload->argc; i++)
195       silc_free(payload->argv[i]);
196
197     silc_free(payload->argv);
198     silc_free(payload->argv_lens);
199     silc_free(payload->argv_types);
200     silc_free(payload);
201   }
202 }
203
204 /* Returns number of arguments in payload */
205
206 SilcUInt32 silc_argument_get_arg_num(SilcArgumentPayload payload)
207 {
208   return payload ? payload->argc : 0;
209 }
210
211 /* Returns first argument from payload. */
212
213 unsigned char *silc_argument_get_first_arg(SilcArgumentPayload payload,
214                                            SilcUInt32 *ret_len)
215 {
216   if (!payload)
217     return NULL;
218
219   payload->pos = 0;
220
221   if (ret_len)
222     *ret_len = payload->argv_lens[payload->pos];
223
224   return payload->argv[payload->pos++];
225 }
226
227 /* Returns next argument from payload or NULL if no more arguments. */
228
229 unsigned char *silc_argument_get_next_arg(SilcArgumentPayload payload,
230                                           SilcUInt32 *ret_len)
231 {
232   if (!payload)
233     return NULL;
234
235   if (payload->pos >= payload->argc)
236     return NULL;
237
238   if (ret_len)
239     *ret_len = payload->argv_lens[payload->pos];
240
241   return payload->argv[payload->pos++];
242 }
243
244 /* Returns argument which type is `type'. */
245
246 unsigned char *silc_argument_get_arg_type(SilcArgumentPayload payload,
247                                           SilcUInt32 type,
248                                           SilcUInt32 *ret_len)
249 {
250   int i;
251
252   if (!payload)
253     return NULL;
254
255   for (i = 0; i < payload->argc; i++)
256     if (payload->argv_types[i] == type)
257       break;
258
259   if (i >= payload->argc)
260     return NULL;
261
262   if (ret_len)
263     *ret_len = payload->argv_lens[i];
264
265   return payload->argv[i];
266 }