|
Packit |
89ede9 |
/*
|
|
Packit |
89ede9 |
* fields.c
|
|
Packit |
89ede9 |
*
|
|
Packit |
89ede9 |
* Copyright (c) Chris Putnam 2003-2018
|
|
Packit |
89ede9 |
*
|
|
Packit |
89ede9 |
* Source code released under the GPL version 2
|
|
Packit |
89ede9 |
*
|
|
Packit |
89ede9 |
*/
|
|
Packit |
89ede9 |
#include <stdio.h>
|
|
Packit |
89ede9 |
#include <stdlib.h>
|
|
Packit |
89ede9 |
#include <stdint.h>
|
|
Packit |
89ede9 |
#include <string.h>
|
|
Packit |
89ede9 |
#include "fields.h"
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
fields*
|
|
Packit |
89ede9 |
fields_new( void )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
fields *f = ( fields * ) malloc( sizeof( fields ) );
|
|
Packit |
89ede9 |
if ( f ) fields_init( f );
|
|
Packit |
89ede9 |
return f;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
void
|
|
Packit |
89ede9 |
fields_init( fields *f )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
f->used = NULL;
|
|
Packit |
89ede9 |
f->level = NULL;
|
|
Packit |
89ede9 |
f->tag = NULL;
|
|
Packit |
89ede9 |
f->data = NULL;
|
|
Packit |
89ede9 |
f->max = f->n = 0;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
void
|
|
Packit |
89ede9 |
fields_free( fields *f )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
int i;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
for ( i=0; i<f->max; ++i ) {
|
|
Packit |
89ede9 |
str_free( &(f->tag[i]) );
|
|
Packit |
89ede9 |
str_free( &(f->data[i]) );
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
if ( f->tag ) free( f->tag );
|
|
Packit |
89ede9 |
if ( f->data ) free( f->data );
|
|
Packit |
89ede9 |
if ( f->used ) free( f->used );
|
|
Packit |
89ede9 |
if ( f->level ) free( f->level );
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
fields_init( f );
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
void
|
|
Packit |
89ede9 |
fields_delete( fields *f )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
fields_free( f );
|
|
Packit |
89ede9 |
free( f );
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
static int
|
|
Packit |
89ede9 |
fields_alloc( fields *f )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
int i, alloc = 20;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
f->tag = (str *) malloc( sizeof(str) * alloc );
|
|
Packit |
89ede9 |
f->data = (str *) malloc( sizeof(str) * alloc );
|
|
Packit |
89ede9 |
f->used = (int *) calloc( alloc, sizeof(int) );
|
|
Packit |
89ede9 |
f->level = (int *) calloc( alloc, sizeof(int) );
|
|
Packit |
89ede9 |
if ( !f->tag || !f->data || !f->used || !f->level ){
|
|
Packit |
89ede9 |
if ( f->tag ) free( f->tag );
|
|
Packit |
89ede9 |
if ( f->data ) free( f->data );
|
|
Packit |
89ede9 |
if ( f->used ) free( f->used );
|
|
Packit |
89ede9 |
if ( f->level ) free( f->level );
|
|
Packit |
89ede9 |
fields_init( f );
|
|
Packit |
89ede9 |
return FIELDS_ERR;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
f->max = alloc;
|
|
Packit |
89ede9 |
f->n = 0;
|
|
Packit |
89ede9 |
for ( i=0; i
|
|
Packit |
89ede9 |
str_init( &(f->tag[i]) );
|
|
Packit |
89ede9 |
str_init( &(f->data[i]) );
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
return FIELDS_OK;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
static int
|
|
Packit |
89ede9 |
fields_realloc( fields *f )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
str *newtags, *newdata;
|
|
Packit |
89ede9 |
int *newused, *newlevel;
|
|
Packit |
89ede9 |
int i, alloc = f->max * 2;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
newtags = (str*) realloc( f->tag, sizeof(str) * alloc );
|
|
Packit |
89ede9 |
newdata = (str*) realloc( f->data, sizeof(str) * alloc );
|
|
Packit |
89ede9 |
newused = (int*) realloc( f->used, sizeof(int) * alloc );
|
|
Packit |
89ede9 |
newlevel= (int*) realloc( f->level, sizeof(int) * alloc );
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
if ( newtags ) f->tag = newtags;
|
|
Packit |
89ede9 |
if ( newdata ) f->data = newdata;
|
|
Packit |
89ede9 |
if ( newused ) f->used = newused;
|
|
Packit |
89ede9 |
if ( newlevel ) f->level = newlevel;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
if ( !newtags || !newdata || !newused || !newlevel )
|
|
Packit |
89ede9 |
return FIELDS_ERR;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
f->max = alloc;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
for ( i=f->n; i
|
|
Packit |
89ede9 |
str_init( &(f->tag[i]) );
|
|
Packit |
89ede9 |
str_init( &(f->data[i]) );
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
return FIELDS_OK;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
int
|
|
Packit |
89ede9 |
_fields_add( fields *f, char *tag, char *data, int level, int mode )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
int i, n, status;
|
|
Packit |
89ede9 |
str *t, *d;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
if ( !tag || !data ) return FIELDS_OK;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
if ( f->max==0 ) {
|
|
Packit |
89ede9 |
status = fields_alloc( f );
|
|
Packit |
89ede9 |
if ( status!=FIELDS_OK ) return status;
|
|
Packit |
89ede9 |
} else if ( f->n >= f->max ) {
|
|
Packit |
89ede9 |
status = fields_realloc( f );
|
|
Packit |
89ede9 |
if ( status!=FIELDS_OK ) return status;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
/* Don't duplicate identical entries if FIELDS_NO_DUPS */
|
|
Packit |
89ede9 |
if ( mode == FIELDS_NO_DUPS ) {
|
|
Packit |
89ede9 |
for ( i=0; i<f->n; i++ ) {
|
|
Packit |
89ede9 |
t = &(f->tag[i]);
|
|
Packit |
89ede9 |
d = &(f->data[i]);
|
|
Packit |
89ede9 |
if ( f->level[i]==level &&
|
|
Packit |
89ede9 |
!strcasecmp( str_cstr( t ), tag ) &&
|
|
Packit |
89ede9 |
!strcasecmp( str_cstr( d ), data ) )
|
|
Packit |
89ede9 |
return FIELDS_OK;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
n = f->n;
|
|
Packit |
89ede9 |
f->used[ n ] = 0;
|
|
Packit |
89ede9 |
f->level[ n ] = level;
|
|
Packit |
89ede9 |
str_strcpyc( &(f->tag[n]), tag );
|
|
Packit |
89ede9 |
str_strcpyc( &(f->data[n]), data );
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
if ( str_memerr( &(f->tag[n]) ) || str_memerr( &(f->data[n] ) ) )
|
|
Packit |
89ede9 |
return FIELDS_ERR;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
f->n++;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
return FIELDS_OK;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
int
|
|
Packit |
89ede9 |
_fields_add_tagsuffix( fields *f, char *tag, char *suffix,
|
|
Packit |
89ede9 |
char *data, int level, int mode )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
str newtag;
|
|
Packit |
89ede9 |
int ret;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
str_init( &newtag );
|
|
Packit |
89ede9 |
str_mergestrs( &newtag, tag, suffix, NULL );
|
|
Packit |
89ede9 |
if ( str_memerr( &newtag ) ) ret = FIELDS_ERR;
|
|
Packit |
89ede9 |
else ret = _fields_add( f, newtag.data, data, level, mode );
|
|
Packit |
89ede9 |
str_free( &newtag );
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
return ret;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
/* fields_match_level()
|
|
Packit |
89ede9 |
*
|
|
Packit |
89ede9 |
* returns 1 if level matched, 0 if not
|
|
Packit |
89ede9 |
*
|
|
Packit |
89ede9 |
* level==LEVEL_ANY is a special flag meaning any level can match
|
|
Packit |
89ede9 |
*/
|
|
Packit |
89ede9 |
int
|
|
Packit |
89ede9 |
fields_match_level( fields *f, int n, int level )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
if ( level==LEVEL_ANY ) return 1;
|
|
Packit |
89ede9 |
if ( fields_level( f, n )==level ) return 1;
|
|
Packit |
89ede9 |
return 0;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
/* fields_match_tag()
|
|
Packit |
89ede9 |
*
|
|
Packit |
89ede9 |
* returns 1 if tag matches, 0 if not
|
|
Packit |
89ede9 |
*
|
|
Packit |
89ede9 |
*/
|
|
Packit |
89ede9 |
int
|
|
Packit |
89ede9 |
fields_match_tag( fields *info, int n, char *tag )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
if ( !strcmp( fields_tag( info, n, FIELDS_CHRP ), tag ) ) return 1;
|
|
Packit |
89ede9 |
return 0;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
int
|
|
Packit |
89ede9 |
fields_match_casetag( fields *info, int n, char *tag )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
if ( !strcasecmp( fields_tag( info, n, FIELDS_CHRP ), tag ) ) return 1;
|
|
Packit |
89ede9 |
return 0;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
int
|
|
Packit |
89ede9 |
fields_match_tag_level( fields *info, int n, char *tag, int level )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
if ( !fields_match_level( info, n, level ) ) return 0;
|
|
Packit |
89ede9 |
return fields_match_tag( info, n, tag );
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
int
|
|
Packit |
89ede9 |
fields_match_casetag_level( fields *info, int n, char *tag, int level )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
if ( !fields_match_level( info, n, level ) ) return 0;
|
|
Packit |
89ede9 |
return fields_match_casetag( info, n, tag );
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
/* fields_find()
|
|
Packit |
89ede9 |
*
|
|
Packit |
89ede9 |
* Return position [0,f->n) for match of the tag.
|
|
Packit |
89ede9 |
* Return FIELDS_NOTFOUND if tag isn't found.
|
|
Packit |
89ede9 |
*/
|
|
Packit |
89ede9 |
int
|
|
Packit |
89ede9 |
fields_find( fields *f, char *tag, int level )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
int i;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
for ( i=0; i<f->n; ++i ) {
|
|
Packit |
89ede9 |
if ( !fields_match_casetag_level( f, i, tag, level ) )
|
|
Packit |
89ede9 |
continue;
|
|
Packit |
89ede9 |
if ( f->data[i].len ) return i;
|
|
Packit |
89ede9 |
else {
|
|
Packit |
89ede9 |
/* if there is no data for the tag, don't "find" it */
|
|
Packit |
89ede9 |
/* and set "used" so noise is suppressed */
|
|
Packit |
89ede9 |
f->used[i] = 1;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
return FIELDS_NOTFOUND;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
int
|
|
Packit |
89ede9 |
fields_maxlevel( fields *f )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
int i, max = 0;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
if ( f->n ) {
|
|
Packit |
89ede9 |
max = f->level[0];
|
|
Packit |
89ede9 |
for ( i=1; i<f->n; ++i ) {
|
|
Packit |
89ede9 |
if ( f->level[i] > max )
|
|
Packit |
89ede9 |
max = f->level[i];
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
return max;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
void
|
|
Packit |
89ede9 |
fields_clearused( fields *f )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
int i;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
for ( i=0; i<f->n; ++i )
|
|
Packit |
89ede9 |
f->used[i] = 0;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
void
|
|
Packit |
89ede9 |
fields_setused( fields *f, int n )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
if ( n >= 0 && n < f->n )
|
|
Packit |
89ede9 |
f->used[n] = 1;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
/* fields_replace_or_add()
|
|
Packit |
89ede9 |
*
|
|
Packit |
89ede9 |
* return FIELDS_OK on success, FIELDS_ERR on memory error
|
|
Packit |
89ede9 |
*/
|
|
Packit |
89ede9 |
int
|
|
Packit |
89ede9 |
fields_replace_or_add( fields *f, char *tag, char *data, int level )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
int n = fields_find( f, tag, level );
|
|
Packit |
89ede9 |
if ( n==FIELDS_NOTFOUND ) return fields_add( f, tag, data, level );
|
|
Packit |
89ede9 |
else {
|
|
Packit |
89ede9 |
str_strcpyc( &(f->data[n]), data );
|
|
Packit |
89ede9 |
if ( str_memerr( &(f->data[n]) ) ) return FIELDS_ERR;
|
|
Packit |
89ede9 |
return FIELDS_OK;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
char *fields_null_value = "\0";
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
int
|
|
Packit |
89ede9 |
fields_used( fields *f, int n )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
if ( n >= 0 && n < f->n ) return f->used[n];
|
|
Packit |
89ede9 |
else return 0;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
int
|
|
Packit |
89ede9 |
fields_notag( fields *f, int n )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
str *t;
|
|
Packit |
89ede9 |
if ( n >= 0 && n < f->n ) {
|
|
Packit |
89ede9 |
t = &( f->tag[n] );
|
|
Packit |
89ede9 |
if ( t->len > 0 ) return 0;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
return 1;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
int
|
|
Packit |
89ede9 |
fields_nodata( fields *f, int n )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
str *d;
|
|
Packit |
89ede9 |
if ( n >= 0 && n < f->n ) {
|
|
Packit |
89ede9 |
d = &( f->data[n] );
|
|
Packit |
89ede9 |
if ( d->len > 0 ) return 0;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
return 1;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
int
|
|
Packit |
89ede9 |
fields_num( fields *f )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
return f->n;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
/*
|
|
Packit |
89ede9 |
* #define FIELDS_CHRP
|
|
Packit |
89ede9 |
* #define FIELDS_STRP
|
|
Packit |
89ede9 |
* #define FIELDS_CHRP_NOLEN
|
|
Packit |
89ede9 |
* #define FIELDS_STRP_NOLEN
|
|
Packit |
89ede9 |
*
|
|
Packit |
89ede9 |
* If the length of the tagged value is zero and the mode is
|
|
Packit |
89ede9 |
* FIELDS_STRP_NOLEN or FIELDS_CHRP_NOLEN, return a pointer to
|
|
Packit |
89ede9 |
* a static null string as the data field could be new due to
|
|
Packit |
89ede9 |
* the way str handles initialized strings with no data.
|
|
Packit |
89ede9 |
*
|
|
Packit |
89ede9 |
*/
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
void *
|
|
Packit |
89ede9 |
fields_value( fields *f, int n, int mode )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
intptr_t retn;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
if ( n<0 || n>= f->n ) return NULL;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
if ( mode & FIELDS_SETUSE_FLAG )
|
|
Packit |
89ede9 |
fields_setused( f, n );
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
if ( mode & FIELDS_STRP_FLAG )
|
|
Packit |
89ede9 |
return &(f->data[n]);
|
|
Packit |
89ede9 |
else if ( mode & FIELDS_POSP_FLAG ) {
|
|
Packit |
89ede9 |
retn = n;
|
|
Packit |
89ede9 |
return ( void * ) retn; /* Rather pointless */
|
|
Packit |
89ede9 |
} else {
|
|
Packit |
89ede9 |
if ( f->data[n].len )
|
|
Packit |
89ede9 |
return f->data[n].data;
|
|
Packit |
89ede9 |
else
|
|
Packit |
89ede9 |
return fields_null_value;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
void *
|
|
Packit |
89ede9 |
fields_tag( fields *f, int n, int mode )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
intptr_t retn;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
if ( n<0 || n>= f->n ) return NULL;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
if ( mode & FIELDS_STRP_FLAG )
|
|
Packit |
89ede9 |
return &(f->tag[n]);
|
|
Packit |
89ede9 |
else if ( mode & FIELDS_POSP_FLAG ) {
|
|
Packit |
89ede9 |
retn = n;
|
|
Packit |
89ede9 |
return ( void * ) retn; /* Rather pointless */
|
|
Packit |
89ede9 |
} else {
|
|
Packit |
89ede9 |
if ( f->tag[n].len )
|
|
Packit |
89ede9 |
return f->tag[n].data;
|
|
Packit |
89ede9 |
else
|
|
Packit |
89ede9 |
return fields_null_value;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
int
|
|
Packit |
89ede9 |
fields_level( fields *f, int n )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
if ( n<0 || n>= f->n ) return 0;
|
|
Packit |
89ede9 |
return f->level[n];
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
void *
|
|
Packit |
89ede9 |
fields_findv( fields *f, int level, int mode, char *tag )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
int i, found = FIELDS_NOTFOUND;
|
|
Packit |
89ede9 |
intptr_t retn;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
for ( i=0; i<f->n && found==FIELDS_NOTFOUND; ++i ) {
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
if ( !fields_match_level( f, i, level ) ) continue;
|
|
Packit |
89ede9 |
if ( !fields_match_casetag( f, i, tag ) ) continue;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
if ( f->data[i].len!=0 ) found = i;
|
|
Packit |
89ede9 |
else {
|
|
Packit |
89ede9 |
if ( mode & FIELDS_NOLENOK_FLAG ) {
|
|
Packit |
89ede9 |
return (void *) fields_null_value;
|
|
Packit |
89ede9 |
} else if ( mode & FIELDS_SETUSE_FLAG ) {
|
|
Packit |
89ede9 |
f->used[i] = 1; /* Suppress "noise" of unused */
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
if ( found==FIELDS_NOTFOUND ) return NULL;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
if ( mode & FIELDS_SETUSE_FLAG )
|
|
Packit |
89ede9 |
fields_setused( f, found );
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
if ( mode & FIELDS_STRP_FLAG )
|
|
Packit |
89ede9 |
return (void *) &(f->data[found]);
|
|
Packit |
89ede9 |
else if ( mode & FIELDS_POSP_FLAG ) {
|
|
Packit |
89ede9 |
retn = found;
|
|
Packit |
89ede9 |
return (void *) retn;
|
|
Packit |
89ede9 |
} else
|
|
Packit |
89ede9 |
return (void *) f->data[found].data;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
void *
|
|
Packit |
89ede9 |
fields_findv_firstof( fields *f, int level, int mode, ... )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
char *tag, *value;
|
|
Packit |
89ede9 |
va_list argp;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
va_start( argp, mode );
|
|
Packit |
89ede9 |
while ( ( tag = ( char * ) va_arg( argp, char * ) ) ) {
|
|
Packit |
89ede9 |
value = fields_findv( f, level, mode, tag );
|
|
Packit |
89ede9 |
if ( value ) {
|
|
Packit |
89ede9 |
va_end( argp );
|
|
Packit |
89ede9 |
return value;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
va_end( argp );
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
return NULL;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
static int
|
|
Packit |
89ede9 |
fields_findv_each_add( fields *f, int mode, int n, vplist *a )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
int status;
|
|
Packit |
89ede9 |
void *v;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
if ( n<0 || n>= f->n ) return FIELDS_OK;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
if ( mode & FIELDS_SETUSE_FLAG )
|
|
Packit |
89ede9 |
fields_setused( f, n );
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
if ( mode & FIELDS_STRP_FLAG ) {
|
|
Packit |
89ede9 |
v = ( void * ) &( f->data[n] );
|
|
Packit |
89ede9 |
} else if ( mode & FIELDS_POSP_FLAG ) {
|
|
Packit |
89ede9 |
v = ( void * )( (long) n );
|
|
Packit |
89ede9 |
} else {
|
|
Packit |
89ede9 |
v = ( void * ) str_cstr( &( f->data[n] ) );
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
status = vplist_add( a, v );
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
if ( status==VPLIST_OK ) return FIELDS_OK;
|
|
Packit |
89ede9 |
else return FIELDS_ERR;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
int
|
|
Packit |
89ede9 |
fields_findv_each( fields *f, int level, int mode, vplist *a, char *tag )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
int i, status;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
for ( i=0; i<f->n; ++i ) {
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
if ( !fields_match_level( f, i, level ) ) continue;
|
|
Packit |
89ede9 |
if ( !fields_match_casetag( f, i, tag ) ) continue;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
if ( f->data[i].len!=0 ) {
|
|
Packit |
89ede9 |
status = fields_findv_each_add( f, mode, i, a );
|
|
Packit |
89ede9 |
if ( status!=FIELDS_OK ) return status;
|
|
Packit |
89ede9 |
} else {
|
|
Packit |
89ede9 |
if ( mode & FIELDS_NOLENOK_FLAG ) {
|
|
Packit |
89ede9 |
status = fields_findv_each_add( f, mode, i, a );
|
|
Packit |
89ede9 |
if ( status!=FIELDS_OK ) return status;
|
|
Packit |
89ede9 |
} else {
|
|
Packit |
89ede9 |
f->used[i] = 1; /* Suppress "noise" of unused */
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
return FIELDS_OK;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
static int
|
|
Packit |
89ede9 |
fields_build_tags( va_list argp, vplist *tags )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
int status;
|
|
Packit |
89ede9 |
char *tag;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
while ( ( tag = ( char * ) va_arg( argp, char * ) ) ) {
|
|
Packit |
89ede9 |
status = vplist_add( tags, tag );
|
|
Packit |
89ede9 |
if ( status!=VPLIST_OK ) return FIELDS_ERR;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
return FIELDS_OK;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
static int
|
|
Packit |
89ede9 |
fields_match_casetags( fields *f, int n, vplist *tags )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
int i;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
for ( i=0; i<tags->n; ++i )
|
|
Packit |
89ede9 |
if ( fields_match_casetag( f, n, vplist_get( tags, i ) ) ) return 1;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
return 0;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
int
|
|
Packit |
89ede9 |
fields_findv_eachof( fields *f, int level, int mode, vplist *a, ... )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
int i, status;
|
|
Packit |
89ede9 |
va_list argp;
|
|
Packit |
89ede9 |
vplist tags;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
vplist_init( &tags );
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
/* build list of tags to search for */
|
|
Packit |
89ede9 |
va_start( argp, a );
|
|
Packit |
89ede9 |
status = fields_build_tags( argp, &tags );
|
|
Packit |
89ede9 |
va_end( argp );
|
|
Packit |
89ede9 |
if ( status!=FIELDS_OK ) goto out;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
/* search list */
|
|
Packit |
89ede9 |
for ( i=0; i<f->n; ++i ) {
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
if ( !fields_match_level( f, i, level ) ) continue;
|
|
Packit |
89ede9 |
if ( !fields_match_casetags( f, i, &tags ) ) continue;
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
if ( f->data[i].len!=0 || ( mode & FIELDS_NOLENOK_FLAG ) ) {
|
|
Packit |
89ede9 |
status = fields_findv_each_add( f, mode, i, a );
|
|
Packit |
89ede9 |
if ( status!=FIELDS_OK ) goto out;
|
|
Packit |
89ede9 |
} else {
|
|
Packit |
89ede9 |
f->used[i] = 1; /* Suppress "noise" of unused */
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
out:
|
|
Packit |
89ede9 |
vplist_free( &tags );
|
|
Packit |
89ede9 |
return status;
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|
|
Packit |
89ede9 |
void
|
|
Packit |
89ede9 |
fields_report( fields *f, FILE *fp )
|
|
Packit |
89ede9 |
{
|
|
Packit |
89ede9 |
int i, n;
|
|
Packit |
89ede9 |
n = fields_num( f );
|
|
Packit |
89ede9 |
fprintf( fp, "# NUM level = LEVEL 'TAG' = 'VALUE'\n" );
|
|
Packit |
89ede9 |
for ( i=0; i
|
|
Packit |
89ede9 |
fprintf( stderr, "%d\tlevel = %d\t'%s' = '%s'\n",
|
|
Packit |
89ede9 |
i+1,
|
|
Packit |
89ede9 |
fields_level( f, i ),
|
|
Packit |
89ede9 |
(char*)fields_tag( f, i, FIELDS_CHRP_NOUSE ),
|
|
Packit |
89ede9 |
(char*)fields_value( f, i, FIELDS_CHRP_NOUSE )
|
|
Packit |
89ede9 |
);
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
}
|
|
Packit |
89ede9 |
|