blob: 577031992cc213696e07d1eac80c07011d3cab16 [file] [log] [blame]
// Copyright 2011 Google Inc. All Rights Reserved.
// Author: qianzhang@google.com (ken Zhang)
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "channel_buffer.h"
#include "utility.h"
static const char *delimiter = " \t,;\r\n:=|'\"#";
static int is_delimiter(char ch)
{
int i;
if (ch == 0)
return 1;
for (i = 0; delimiter[i]; i++)
if (ch == delimiter[i])
return 1;
return 0;
}
// format name:zzz (or name=zzzz)
int get_string_by_name(char *p, const char *name, char *string, int max_len,
char **next)
{
char *s, *e;
e = p;
while (e != NULL && *e) {
s = strstr(e, name);
if (s == NULL)
return 0;
// is a token name
if (((s > p && is_delimiter(*(s - 1))) || s == p) &&
is_delimiter(*(s + strlen(name)))) {
s += (int)strlen(name);
while (*s && (*s == ' ' || *s == '\t')) s++; // skip white space
if (*s == '=' || *s == ':') {
s++;
while (*s && (*s == ' ' || *s == '\t')) s++; // skip white space
if (*s) {
int i = 0;
while (i++ < max_len && *s && *s != ' ' && *s != '\t' && *s != '\n' &&
*s != '\r')
*string++ = *s++;
*string = 0x0; // terminator
if (next != NULL) {
while (*s && *s != ' ' && *s != '\t' && *s != '\n' && *s != '\r')
s++;
*next = s;
}
return 1;
}
}
}
e = ++s;
}
return 0;
}
// format name:zzz (or name=zzzz)
int get_string_by_token(char *p, int num, char *string, int max_len,
char **next)
{
int count = 0;
char *s;
s = p;
if (s == NULL)
return 0;
while (*s) {
while (*s && (*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n'))
s++; // skip white space
if (*s == 0)
break;
if (count++ != num) {
while (*s && !(*s == ' ' || *s == '\t' || *s == ';' || *s == ',' ||
*s == '\r' || *s == '\n'))
s++; // skip a token
} else {
if (*s) {
int i = 0;
while (i++ < max_len && *s && !(*s == ' ' || *s == '\t' || *s == ';' ||
*s == ',' || *s == '\r' || *s == '\n'))
*string++ = *s++;
*string = 0x0; // terminator
if (next != NULL) {
while (*s && !(*s == ' ' || *s == '\t' || *s == '\r' || *s == '\n'))
s++;
*next = s;
}
return 1;
}
}
if (*s)
s++;
}
return 0;
}
// format name:"zzz" (or name="zzzz")
int get_quote_string_by_name(char *p, const char *name, char *string,
int max_len, char **next)
{
char *s, *e;
e = p;
while (e != NULL && *e) {
s = strstr(e, name);
if (s == NULL)
return 0;
// is a token name
if (((s > p && is_delimiter(*(s - 1))) || s == p) &&
is_delimiter(*(s + strlen(name)))) {
s += (int)strlen(name);
while (*s && (*s == ' ' || *s == '\t')) s++; // skip white space
if (*s == '=' || *s == ':') {
s++;
while (*s && (*s == ' ' || *s == '\t')) s++; // skip white space
if (*s == '\"') {
int i = 0;
s++;
while (i++ < max_len && *s && *s != '\"') *string++ = *s++;
*string = 0x0; // terminator
if (next != NULL) {
while (*s && *s != '\"') s++;
*next = s + 1;
}
return 1;
} else
return 0;
}
}
e = ++s;
}
return 0;
}
int get_int_val_by_name(char *p, const char *name, int *val, char **next)
{
char *s, *e;
e = p;
while (e != NULL && *e) {
s = strstr(e, name);
if (s == NULL)
return 0;
// is a token name
if (((s > p && is_delimiter(*(s - 1))) || s == p) &&
is_delimiter(*(s + strlen(name)))) {
s += strlen(name);
while (*s && (*s == ' ' || *s == '\t')) s++; // skip white space
if (*s == '=' || *s == ':') {
s++;
while (*s && (*s == ' ' || *s == '\t')) s++; // skip white space
if (*s) {
*val = atoi(s);
if (*val < 0 && *s == '-')
s++;
while (*s >= '0' && *s <= '9') s++;
if (next != NULL)
*next = s;
return 1;
}
}
}
e = ++s;
}
return 0;
}
struct channel_list_t *_create_channel_list(int num)
{
if (num <= 0)
return NULL;
struct channel_list_t *cl = malloc(sizeof(struct channel_list_t));
if (cl == NULL)
return NULL;
cl->num = num;
cl->channel_num = 0;
cl->ce = malloc(sizeof(struct channel_entry_t) * num);
if (cl->ce == NULL) {
free(cl);
return NULL;
}
memset(cl->ce, 0x0, sizeof(struct channel_entry_t) * num);
return cl;
}
void _release_channel_list(struct channel_list_t *cl)
{
if (cl) {
if (cl->ce)
free(cl->ce);
free(cl);
}
}
struct channel_list_t *_joint_channel_list(struct channel_list_t *cl1,
struct channel_list_t *cl2)
{
int i, n, channel_num;
if (cl1 == NULL)
return cl2;
if (cl2 == NULL)
return cl1;
channel_num = cl1->channel_num + cl2->channel_num;
if (channel_num < cl1->num) {
n = 0;
for (i = cl1->channel_num; i < channel_num; i++) cl1->ce[i] = cl2->ce[n++];
cl2->channel_num = channel_num;
_release_channel_list(cl2);
return cl1;
} else if (channel_num < cl2->num) {
n = 0;
for (i = cl2->channel_num; i < channel_num; i++) cl2->ce[i] = cl1->ce[n++];
cl2->channel_num = channel_num;
_release_channel_list(cl1);
return cl2;
} else {
struct channel_list_t *cl = _create_channel_list(channel_num);
for (i = 0; i < cl1->channel_num; i++) cl->ce[i] = cl1->ce[i];
for (n = 0; n < cl2->channel_num; n++) cl->ce[i++] = cl2->ce[n];
_release_channel_list(cl1);
_release_channel_list(cl2);
cl->channel_num = channel_num;
return cl;
}
return NULL;
}