Add support building Modem Manager plugin into the daemon
[connman] / gatchat / gatresult.c
1 /*
2  *
3  *  AT chat library with GLib integration
4  *
5  *  Copyright (C) 2008-2009  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <string.h>
27
28 #include <glib.h>
29
30 #include "gatresult.h"
31
32 void g_at_result_iter_init(GAtResultIter *iter, GAtResult *result)
33 {
34         iter->result = result;
35         iter->pre.next = result->lines;
36         iter->pre.data = NULL;
37         iter->l = &iter->pre;
38         iter->line_pos = 0;
39 }
40
41 gboolean g_at_result_iter_next(GAtResultIter *iter, const char *prefix)
42 {
43         char *line;
44         int prefix_len = prefix ? strlen(prefix) : 0;
45
46         while ((iter->l = iter->l->next)) {
47                 line = iter->l->data;
48
49                 if (prefix_len == 0) {
50                         iter->line_pos = 0;
51                         return TRUE;
52                 }
53
54                 if (g_str_has_prefix(line, prefix) == FALSE)
55                         continue;
56
57                 iter->line_pos = prefix_len;
58
59                 while (iter->line_pos < strlen(line) &&
60                         line[iter->line_pos] == ' ')
61                         iter->line_pos += 1;
62
63                 return TRUE;
64         }
65
66         return FALSE;
67 }
68
69 const char *g_at_result_iter_raw_line(GAtResultIter *iter)
70 {
71         const char *line;
72
73         if (!iter)
74                 return NULL;
75
76         if (!iter->l)
77                 return NULL;
78
79         line = iter->l->data;
80
81         line += iter->line_pos;
82
83         return line;
84 }
85
86 static inline int skip_to_next_field(const char *line, int pos, int len)
87 {
88         if (pos < len && line[pos] == ',')
89                 pos += 1;
90
91         while (pos < len && line[pos] == ' ')
92                 pos += 1;
93
94         return pos;
95 }
96
97 gboolean g_at_result_iter_next_string(GAtResultIter *iter, const char **str)
98 {
99         unsigned int pos;
100         unsigned int end;
101         unsigned int len;
102         char *line;
103
104         if (!iter)
105                 return FALSE;
106
107         if (!iter->l)
108                 return FALSE;
109
110         line = iter->l->data;
111         len = strlen(line);
112
113         pos = iter->line_pos;
114
115         /* Omitted string */
116         if (line[pos] == ',') {
117                 end = pos;
118                 memset(iter->buf, 0, sizeof(iter->buf));
119                 goto out;
120         }
121
122         if (line[pos++] != '"')
123                 return FALSE;
124
125         end = pos;
126
127         while (end < len && line[end] != '"')
128                 end += 1;
129
130         if (line[end] != '"')
131                 return FALSE;
132
133         if (end - pos >= sizeof(iter->buf))
134                 return FALSE;
135
136         strncpy(iter->buf, line+pos, end-pos);
137         memset(iter->buf + end - pos, 0, sizeof(iter->buf) - end + pos);
138
139         /* Skip " */
140         end += 1;
141
142 out:
143         iter->line_pos = skip_to_next_field(line, end, len);
144
145         if (str)
146                 *str = iter->buf;
147
148         return TRUE;
149 }
150
151 gboolean g_at_result_iter_next_number(GAtResultIter *iter, gint *number)
152 {
153         int pos;
154         int end;
155         int len;
156         int value = 0;
157         char *line;
158
159         if (!iter)
160                 return FALSE;
161
162         if (!iter->l)
163                 return FALSE;
164
165         line = iter->l->data;
166         len = strlen(line);
167
168         pos = iter->line_pos;
169         end = pos;
170
171         while (line[end] >= '0' && line[end] <= '9') {
172                 value = value * 10 + (int)(line[end] - '0');
173                 end += 1;
174         }
175
176         if (pos == end)
177                 return FALSE;
178
179         iter->line_pos = skip_to_next_field(line, end, len);
180
181         if (number)
182                 *number = value;
183
184         return TRUE;
185 }
186
187 gboolean g_at_result_iter_next_range(GAtResultIter *iter, gint *min, gint *max)
188 {
189         int pos;
190         int end;
191         int len;
192         int low = 0;
193         int high = 0;
194         char *line;
195
196         if (!iter)
197                 return FALSE;
198
199         if (!iter->l)
200                 return FALSE;
201
202         line = iter->l->data;
203         len = strlen(line);
204
205         pos = iter->line_pos;
206
207         while (pos < len && line[pos] == ' ')
208                 pos += 1;
209
210         end = pos;
211
212         while (line[end] >= '0' && line[end] <= '9') {
213                 low = low * 10 + (int)(line[end] - '0');
214                 end += 1;
215         }
216
217         if (pos == end)
218                 return FALSE;
219
220         if (line[end] == ',') {
221                 high = low;
222                 goto out;
223         }
224
225         if (line[end] == '-')
226                 pos = end = end + 1;
227         else
228                 return FALSE;
229
230         while (line[end] >= '0' && line[end] <= '9') {
231                 high = high * 10 + (int)(line[end] - '0');
232                 end += 1;
233         }
234
235         if (pos == end)
236                 return FALSE;
237
238 out:
239         iter->line_pos = skip_to_next_field(line, end, len);
240
241         if (min)
242                 *min = low;
243
244         if (max)
245                 *max = high;
246
247         return TRUE;
248 }
249
250 static gint skip_until(const char *line, int start, const char delim)
251 {
252         int len = strlen(line);
253         int i = start;
254
255         while (i < len) {
256                 if (line[i] == delim)
257                         return i;
258
259                 if (line[i] != '(') {
260                         i += 1;
261                         continue;
262                 }
263
264                 i = skip_until(line, i+1, ')');
265
266                 if (i < len)
267                         i += 1;
268         }
269
270         return i;
271 }
272
273 gboolean g_at_result_iter_skip_next(GAtResultIter *iter)
274 {
275         unsigned int skipped_to;
276         char *line;
277
278         if (!iter)
279                 return FALSE;
280
281         if (!iter->l)
282                 return FALSE;
283
284         line = iter->l->data;
285
286         skipped_to = skip_until(line, iter->line_pos, ',');
287
288         if (skipped_to == iter->line_pos && line[skipped_to] != ',')
289                 return FALSE;
290
291         iter->line_pos = skip_to_next_field(line, skipped_to, strlen(line));
292
293         return TRUE;
294 }
295
296 gboolean g_at_result_iter_open_list(GAtResultIter *iter)
297 {
298         char *line;
299         unsigned int len;
300
301         if (!iter)
302                 return FALSE;
303
304         if (!iter->l)
305                 return FALSE;
306
307         line = iter->l->data;
308         len = strlen(line);
309
310         if (iter->line_pos >= len)
311                 return FALSE;
312
313         if (line[iter->line_pos] != '(')
314                 return FALSE;
315
316         iter->line_pos += 1;
317
318         while (iter->line_pos < strlen(line) &&
319                 line[iter->line_pos] == ' ')
320                 iter->line_pos += 1;
321
322         return TRUE;
323 }
324
325 gboolean g_at_result_iter_close_list(GAtResultIter *iter)
326 {
327         char *line;
328         unsigned int len;
329
330         if (!iter)
331                 return FALSE;
332
333         if (!iter->l)
334                 return FALSE;
335
336         line = iter->l->data;
337         len = strlen(line);
338
339         if (iter->line_pos >= len)
340                 return FALSE;
341
342         if (line[iter->line_pos] != ')')
343                 return FALSE;
344
345         iter->line_pos += 1;
346
347         iter->line_pos = skip_to_next_field(line, iter->line_pos, len);
348
349         return TRUE;
350 }
351
352 const char *g_at_result_final_response(GAtResult *result)
353 {
354         if (!result)
355                 return NULL;
356
357         return result->final_or_pdu;
358 }
359
360 const char *g_at_result_pdu(GAtResult *result)
361 {
362         if (!result)
363                 return NULL;
364
365         return result->final_or_pdu;
366 }
367
368 gint g_at_result_num_response_lines(GAtResult *result)
369 {
370         if (!result)
371                 return 0;
372
373         if (!result->lines)
374                 return 0;
375
376         return g_slist_length(result->lines);
377 }