/* * * AT chat library with GLib integration * * Copyright (C) 2008-2011 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include "gatresult.h" void g_at_result_iter_init(GAtResultIter *iter, GAtResult *result) { iter->result = result; iter->pre.next = result->lines; iter->pre.data = NULL; iter->l = &iter->pre; iter->line_pos = 0; } gboolean g_at_result_iter_next(GAtResultIter *iter, const char *prefix) { char *line; int prefix_len = prefix ? strlen(prefix) : 0; int linelen; while ((iter->l = iter->l->next)) { line = iter->l->data; linelen = strlen(line); if (linelen > G_AT_RESULT_LINE_LENGTH_MAX) continue; if (prefix_len == 0) { iter->line_pos = 0; goto out; } if (g_str_has_prefix(line, prefix) == FALSE) continue; iter->line_pos = prefix_len; while (iter->line_pos < strlen(line) && line[iter->line_pos] == ' ') iter->line_pos += 1; goto out; } return FALSE; out: /* Already checked the length to be no more than buflen */ strcpy(iter->buf, line); return TRUE; } const char *g_at_result_iter_raw_line(GAtResultIter *iter) { const char *line; if (iter == NULL) return NULL; if (iter->l == NULL) return NULL; line = iter->l->data; line += iter->line_pos; return line; } static inline int skip_to_next_field(const char *line, int pos, int len) { if (pos < len && line[pos] == ',') pos += 1; while (pos < len && line[pos] == ' ') pos += 1; return pos; } gboolean g_at_result_iter_next_unquoted_string(GAtResultIter *iter, const char **str) { unsigned int pos; unsigned int end; unsigned int len; unsigned int stripped; char *line; if (iter == NULL) return FALSE; if (iter->l == NULL) return FALSE; line = iter->l->data; len = strlen(line); pos = iter->line_pos; /* Omitted string */ if (line[pos] == ',') { end = pos; iter->buf[pos] = '\0'; goto out; } if (line[pos] == '"' || line[pos] == ')') return FALSE; end = pos; while (end < len && line[end] != ',' && line[end] != ')') end += 1; stripped = end; while (line[stripped - 1] == ' ') stripped -= 1; iter->buf[stripped] = '\0'; out: iter->line_pos = skip_to_next_field(line, end, len); if (str) *str = iter->buf + pos; return TRUE; } gboolean g_at_result_iter_next_string(GAtResultIter *iter, const char **str) { unsigned int pos; unsigned int end; unsigned int len; char *line; if (iter == NULL) return FALSE; if (iter->l == NULL) return FALSE; line = iter->l->data; len = strlen(line); pos = iter->line_pos; /* Omitted string */ if (line[pos] == ',') { end = pos; iter->buf[pos] = '\0'; goto out; } if (line[pos++] != '"') return FALSE; end = pos; while (end < len && line[end] != '"') end += 1; if (line[end] != '"') return FALSE; iter->buf[end] = '\0'; /* Skip " */ end += 1; out: iter->line_pos = skip_to_next_field(line, end, len); if (str) *str = iter->buf + pos; return TRUE; } gboolean g_at_result_iter_next_hexstring(GAtResultIter *iter, const guint8 **str, gint *length) { unsigned int pos; unsigned int end; unsigned int len; char *line; char *bufpos; if (iter == NULL) return FALSE; if (iter->l == NULL) return FALSE; line = iter->l->data; len = strlen(line); pos = iter->line_pos; bufpos = iter->buf + pos; /* Omitted string */ if (line[pos] == ',') { end = pos; iter->buf[pos] = '\0'; *length = 0; goto out; } if (line[pos] == '"') pos += 1; end = pos; while (end < len && g_ascii_isxdigit(line[end])) end += 1; if ((end - pos) & 1) return FALSE; *length = (end - pos) / 2; for (; pos < end; pos += 2) sscanf(line + pos, "%02hhx", bufpos++); if (line[end] == '"') end += 1; out: iter->line_pos = skip_to_next_field(line, end, len); if (str) *str = (guint8 *) bufpos - *length; return TRUE; } gboolean g_at_result_iter_next_number(GAtResultIter *iter, gint *number) { int pos; int end; int len; int value = 0; char *line; if (iter == NULL) return FALSE; if (iter->l == NULL) return FALSE; line = iter->l->data; len = strlen(line); pos = iter->line_pos; end = pos; while (line[end] >= '0' && line[end] <= '9') { value = value * 10 + (int)(line[end] - '0'); end += 1; } if (pos == end) return FALSE; iter->line_pos = skip_to_next_field(line, end, len); if (number) *number = value; return TRUE; } gboolean g_at_result_iter_next_number_default(GAtResultIter *iter, gint dflt, gint *number) { unsigned int pos; int len; char *line; if (iter == NULL) return FALSE; if (iter->l == NULL) return FALSE; line = iter->l->data; len = strlen(line); pos = skip_to_next_field(line, iter->line_pos, len); if (pos != iter->line_pos) { iter->line_pos = pos; if (number) *number = dflt; return TRUE; } return g_at_result_iter_next_number(iter, number); } gboolean g_at_result_iter_next_range(GAtResultIter *iter, gint *min, gint *max) { int pos; int end; int len; int low = 0; int high = 0; char *line; if (iter == NULL) return FALSE; if (iter->l == NULL) return FALSE; line = iter->l->data; len = strlen(line); pos = iter->line_pos; while (pos < len && line[pos] == ' ') pos += 1; end = pos; while (line[end] >= '0' && line[end] <= '9') { low = low * 10 + (int)(line[end] - '0'); end += 1; } if (pos == end) return FALSE; if (line[end] != '-') { high = low; goto out; } pos = end = end + 1; while (line[end] >= '0' && line[end] <= '9') { high = high * 10 + (int)(line[end] - '0'); end += 1; } if (pos == end) return FALSE; out: iter->line_pos = skip_to_next_field(line, end, len); if (min) *min = low; if (max) *max = high; return TRUE; } static gint skip_until(const char *line, int start, const char delim) { int len = strlen(line); int i = start; while (i < len) { if (line[i] == delim) return i; if (line[i] == '\"') { i += 1; while (i < len && line[i] != '\"') i += 1; if (i < len) i += 1; continue; } if (line[i] != '(') { i += 1; continue; } i = skip_until(line, i+1, ')'); if (i < len) i += 1; } return i; } gboolean g_at_result_iter_skip_next(GAtResultIter *iter) { unsigned int skipped_to; char *line; if (iter == NULL) return FALSE; if (iter->l == NULL) return FALSE; line = iter->l->data; skipped_to = skip_until(line, iter->line_pos, ','); if (skipped_to == iter->line_pos && line[skipped_to] != ',') return FALSE; iter->line_pos = skip_to_next_field(line, skipped_to, strlen(line)); return TRUE; } gboolean g_at_result_iter_open_list(GAtResultIter *iter) { char *line; unsigned int len; if (iter == NULL) return FALSE; if (iter->l == NULL) return FALSE; line = iter->l->data; len = strlen(line); if (iter->line_pos >= len) return FALSE; if (line[iter->line_pos] != '(') return FALSE; iter->line_pos += 1; while (iter->line_pos < strlen(line) && line[iter->line_pos] == ' ') iter->line_pos += 1; return TRUE; } gboolean g_at_result_iter_close_list(GAtResultIter *iter) { char *line; unsigned int len; if (iter == NULL) return FALSE; if (iter->l == NULL) return FALSE; line = iter->l->data; len = strlen(line); if (iter->line_pos >= len) return FALSE; if (line[iter->line_pos] != ')') return FALSE; iter->line_pos += 1; iter->line_pos = skip_to_next_field(line, iter->line_pos, len); return TRUE; } const char *g_at_result_final_response(GAtResult *result) { if (result == NULL) return NULL; return result->final_or_pdu; } const char *g_at_result_pdu(GAtResult *result) { if (result == NULL) return NULL; return result->final_or_pdu; } gint g_at_result_num_response_lines(GAtResult *result) { if (result == NULL) return 0; if (result->lines == NULL) return 0; return g_slist_length(result->lines); }