ofono/gatchat/gatresult.c

531 lines
8.4 KiB
C

/*
*
* 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 <config.h>
#endif
#include <string.h>
#include <stdio.h>
#include <glib.h>
#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);
}