Upgrade ofono to 1.2
[profile/ivi/ofono.git] / gatchat / gatresult.c
1 /*
2  *
3  *  AT chat library with GLib integration
4  *
5  *  Copyright (C) 2008-2011  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 #include <stdio.h>
28
29 #include <glib.h>
30
31 #include "gatresult.h"
32
33 void g_at_result_iter_init(GAtResultIter *iter, GAtResult *result)
34 {
35         iter->result = result;
36         iter->pre.next = result->lines;
37         iter->pre.data = NULL;
38         iter->l = &iter->pre;
39         iter->line_pos = 0;
40 }
41
42 gboolean g_at_result_iter_next(GAtResultIter *iter, const char *prefix)
43 {
44         char *line;
45         int prefix_len = prefix ? strlen(prefix) : 0;
46         int linelen;
47
48         while ((iter->l = iter->l->next)) {
49                 line = iter->l->data;
50                 linelen = strlen(line);
51
52                 if (linelen > G_AT_RESULT_LINE_LENGTH_MAX)
53                         continue;
54
55                 if (prefix_len == 0) {
56                         iter->line_pos = 0;
57                         goto out;
58                 }
59
60                 if (g_str_has_prefix(line, prefix) == FALSE)
61                         continue;
62
63                 iter->line_pos = prefix_len;
64
65                 while (iter->line_pos < strlen(line) &&
66                         line[iter->line_pos] == ' ')
67                         iter->line_pos += 1;
68
69                 goto out;
70         }
71
72         return FALSE;
73
74 out:
75         /* Already checked the length to be no more than buflen */
76         strcpy(iter->buf, line);
77         return TRUE;
78 }
79
80 const char *g_at_result_iter_raw_line(GAtResultIter *iter)
81 {
82         const char *line;
83
84         if (iter == NULL)
85                 return NULL;
86
87         if (iter->l == NULL)
88                 return NULL;
89
90         line = iter->l->data;
91
92         line += iter->line_pos;
93
94         return line;
95 }
96
97 static inline int skip_to_next_field(const char *line, int pos, int len)
98 {
99         if (pos < len && line[pos] == ',')
100                 pos += 1;
101
102         while (pos < len && line[pos] == ' ')
103                 pos += 1;
104
105         return pos;
106 }
107
108 gboolean g_at_result_iter_next_unquoted_string(GAtResultIter *iter,
109                                                 const char **str)
110 {
111         unsigned int pos;
112         unsigned int end;
113         unsigned int len;
114         char *line;
115
116         if (iter == NULL)
117                 return FALSE;
118
119         if (iter->l == NULL)
120                 return FALSE;
121
122         line = iter->l->data;
123         len = strlen(line);
124
125         pos = iter->line_pos;
126
127         /* Omitted string */
128         if (line[pos] == ',') {
129                 end = pos;
130                 iter->buf[pos] = '\0';
131                 goto out;
132         }
133
134         if (line[pos] == '"' || line[pos] == ')')
135                 return FALSE;
136
137         end = pos;
138
139         while (end < len && line[end] != ',' && line[end] != ')')
140                 end += 1;
141
142         iter->buf[end] = '\0';
143
144 out:
145         iter->line_pos = skip_to_next_field(line, end, len);
146
147         if (str)
148                 *str = iter->buf + pos;
149
150         return TRUE;
151 }
152
153 gboolean g_at_result_iter_next_string(GAtResultIter *iter, const char **str)
154 {
155         unsigned int pos;
156         unsigned int end;
157         unsigned int len;
158         char *line;
159
160         if (iter == NULL)
161                 return FALSE;
162
163         if (iter->l == NULL)
164                 return FALSE;
165
166         line = iter->l->data;
167         len = strlen(line);
168
169         pos = iter->line_pos;
170
171         /* Omitted string */
172         if (line[pos] == ',') {
173                 end = pos;
174                 iter->buf[pos] = '\0';
175                 goto out;
176         }
177
178         if (line[pos++] != '"')
179                 return FALSE;
180
181         end = pos;
182
183         while (end < len && line[end] != '"')
184                 end += 1;
185
186         if (line[end] != '"')
187                 return FALSE;
188
189         iter->buf[end] = '\0';
190
191         /* Skip " */
192         end += 1;
193
194 out:
195         iter->line_pos = skip_to_next_field(line, end, len);
196
197         if (str)
198                 *str = iter->buf + pos;
199
200         return TRUE;
201 }
202
203 gboolean g_at_result_iter_next_hexstring(GAtResultIter *iter,
204                 const guint8 **str, gint *length)
205 {
206         unsigned int pos;
207         unsigned int end;
208         unsigned int len;
209         char *line;
210         char *bufpos;
211
212         if (iter == NULL)
213                 return FALSE;
214
215         if (iter->l == NULL)
216                 return FALSE;
217
218         line = iter->l->data;
219         len = strlen(line);
220
221         pos = iter->line_pos;
222         bufpos = iter->buf + pos;
223
224         /* Omitted string */
225         if (line[pos] == ',') {
226                 end = pos;
227                 iter->buf[pos] = '\0';
228                 goto out;
229         }
230
231         if (line[pos] == '"')
232                 pos += 1;
233
234         end = pos;
235
236         while (end < len && g_ascii_isxdigit(line[end]))
237                 end += 1;
238
239         if ((end - pos) & 1)
240                 return FALSE;
241
242         *length = (end - pos) / 2;
243
244         for (; pos < end; pos += 2)
245                 sscanf(line + pos, "%02hhx", bufpos++);
246
247         if (line[end] == '"')
248                 end += 1;
249
250 out:
251         iter->line_pos = skip_to_next_field(line, end, len);
252
253         if (str)
254                 *str = (guint8 *) bufpos - *length;
255
256         return TRUE;
257 }
258
259 gboolean g_at_result_iter_next_number(GAtResultIter *iter, gint *number)
260 {
261         int pos;
262         int end;
263         int len;
264         int value = 0;
265         char *line;
266
267         if (iter == NULL)
268                 return FALSE;
269
270         if (iter->l == NULL)
271                 return FALSE;
272
273         line = iter->l->data;
274         len = strlen(line);
275
276         pos = iter->line_pos;
277         end = pos;
278
279         while (line[end] >= '0' && line[end] <= '9') {
280                 value = value * 10 + (int)(line[end] - '0');
281                 end += 1;
282         }
283
284         if (pos == end)
285                 return FALSE;
286
287         iter->line_pos = skip_to_next_field(line, end, len);
288
289         if (number)
290                 *number = value;
291
292         return TRUE;
293 }
294
295 gboolean g_at_result_iter_next_number_default(GAtResultIter *iter, gint dflt,
296                                                 gint *number)
297 {
298         unsigned int pos;
299         int len;
300         char *line;
301
302         if (iter == NULL)
303                 return FALSE;
304
305         if (iter->l == NULL)
306                 return FALSE;
307
308         line = iter->l->data;
309         len = strlen(line);
310
311         pos = skip_to_next_field(line, iter->line_pos, len);
312
313         if (pos != iter->line_pos) {
314                 iter->line_pos = pos;
315
316                 if (number)
317                         *number = dflt;
318
319                 return TRUE;
320         }
321
322         return g_at_result_iter_next_number(iter, number);
323 }
324
325 gboolean g_at_result_iter_next_range(GAtResultIter *iter, gint *min, gint *max)
326 {
327         int pos;
328         int end;
329         int len;
330         int low = 0;
331         int high = 0;
332         char *line;
333
334         if (iter == NULL)
335                 return FALSE;
336
337         if (iter->l == NULL)
338                 return FALSE;
339
340         line = iter->l->data;
341         len = strlen(line);
342
343         pos = iter->line_pos;
344
345         while (pos < len && line[pos] == ' ')
346                 pos += 1;
347
348         end = pos;
349
350         while (line[end] >= '0' && line[end] <= '9') {
351                 low = low * 10 + (int)(line[end] - '0');
352                 end += 1;
353         }
354
355         if (pos == end)
356                 return FALSE;
357
358         if (line[end] != '-') {
359                 high = low;
360                 goto out;
361         }
362
363         pos = end = end + 1;
364
365         while (line[end] >= '0' && line[end] <= '9') {
366                 high = high * 10 + (int)(line[end] - '0');
367                 end += 1;
368         }
369
370         if (pos == end)
371                 return FALSE;
372
373 out:
374         iter->line_pos = skip_to_next_field(line, end, len);
375
376         if (min)
377                 *min = low;
378
379         if (max)
380                 *max = high;
381
382         return TRUE;
383 }
384
385 static gint skip_until(const char *line, int start, const char delim)
386 {
387         int len = strlen(line);
388         int i = start;
389
390         while (i < len) {
391                 if (line[i] == delim)
392                         return i;
393
394                 if (line[i] == '\"') {
395                         i += 1;
396                         while (i < len && line[i] != '\"')
397                                 i += 1;
398
399                         if (i < len)
400                                 i += 1;
401
402                         continue;
403                 }
404
405                 if (line[i] != '(') {
406                         i += 1;
407                         continue;
408                 }
409
410                 i = skip_until(line, i+1, ')');
411
412                 if (i < len)
413                         i += 1;
414         }
415
416         return i;
417 }
418
419 gboolean g_at_result_iter_skip_next(GAtResultIter *iter)
420 {
421         unsigned int skipped_to;
422         char *line;
423
424         if (iter == NULL)
425                 return FALSE;
426
427         if (iter->l == NULL)
428                 return FALSE;
429
430         line = iter->l->data;
431
432         skipped_to = skip_until(line, iter->line_pos, ',');
433
434         if (skipped_to == iter->line_pos && line[skipped_to] != ',')
435                 return FALSE;
436
437         iter->line_pos = skip_to_next_field(line, skipped_to, strlen(line));
438
439         return TRUE;
440 }
441
442 gboolean g_at_result_iter_open_list(GAtResultIter *iter)
443 {
444         char *line;
445         unsigned int len;
446
447         if (iter == NULL)
448                 return FALSE;
449
450         if (iter->l == NULL)
451                 return FALSE;
452
453         line = iter->l->data;
454         len = strlen(line);
455
456         if (iter->line_pos >= len)
457                 return FALSE;
458
459         if (line[iter->line_pos] != '(')
460                 return FALSE;
461
462         iter->line_pos += 1;
463
464         while (iter->line_pos < strlen(line) &&
465                 line[iter->line_pos] == ' ')
466                 iter->line_pos += 1;
467
468         return TRUE;
469 }
470
471 gboolean g_at_result_iter_close_list(GAtResultIter *iter)
472 {
473         char *line;
474         unsigned int len;
475
476         if (iter == NULL)
477                 return FALSE;
478
479         if (iter->l == NULL)
480                 return FALSE;
481
482         line = iter->l->data;
483         len = strlen(line);
484
485         if (iter->line_pos >= len)
486                 return FALSE;
487
488         if (line[iter->line_pos] != ')')
489                 return FALSE;
490
491         iter->line_pos += 1;
492
493         iter->line_pos = skip_to_next_field(line, iter->line_pos, len);
494
495         return TRUE;
496 }
497
498 const char *g_at_result_final_response(GAtResult *result)
499 {
500         if (result == NULL)
501                 return NULL;
502
503         return result->final_or_pdu;
504 }
505
506 const char *g_at_result_pdu(GAtResult *result)
507 {
508         if (result == NULL)
509                 return NULL;
510
511         return result->final_or_pdu;
512 }
513
514 gint g_at_result_num_response_lines(GAtResult *result)
515 {
516         if (result == NULL)
517                 return 0;
518
519         if (result->lines == NULL)
520                 return 0;
521
522         return g_slist_length(result->lines);
523 }