summaryrefslogtreecommitdiffstats
path: root/collection
diff options
context:
space:
mode:
authorDmitri Pal <dpal@redhat.com>2009-02-26 16:32:20 -0500
committerDmitri Pal <dpal@redhat.com>2009-02-26 16:32:20 -0500
commit8fb404ff3d803964764452f7e027ded5bf1d85b3 (patch)
tree472d7b69f545208fc54780fa8dbfcef1b6f4eb70 /collection
parentacb92e98ab01d5582d52737a7ad89919a00458aa (diff)
downloadelapi_draft-8fb404ff3d803964764452f7e027ded5bf1d85b3.tar.gz
elapi_draft-8fb404ff3d803964764452f7e027ded5bf1d85b3.tar.xz
elapi_draft-8fb404ff3d803964764452f7e027ded5bf1d85b3.zip
Major changes. Added high level API. Unstable. Checkin before testing.
Diffstat (limited to 'collection')
-rw-r--r--collection/elapi_collection.c229
-rw-r--r--collection/elapi_collection.h29
-rw-r--r--collection/elapi_util.c411
-rw-r--r--collection/elapi_util.h5
4 files changed, 671 insertions, 3 deletions
diff --git a/collection/elapi_collection.c b/collection/elapi_collection.c
index 50809ae..7045130 100644
--- a/collection/elapi_collection.c
+++ b/collection/elapi_collection.c
@@ -35,6 +35,13 @@
/* Special internal error code to indicate that collection search was interrupted */
#define EINTR_INTERNAL 10000
+
+/* Potential subjest for management with libtools */
+#define DATE_FORMAT "%+"
+
+#define TIME_ARRAY_SIZE 100
+
+
/* Struct used for passing parameter for update operation */
struct update_property {
int type;
@@ -712,10 +719,10 @@ static int update_item(struct collection_item *current,
int error = EOK;
DEBUG_STRING("update_item","Entry");
- /* If type is different or samew but it is string or binary we need to replace the storage */
+ /* If type is different or same but it is string or binary we need to replace the storage */
if((current->type != update_data->type) ||
((current->type == update_data->type) &&
- ((current->type != ELAPI_TYPE_STRING) || (current->type != ELAPI_TYPE_BINARY)))) {
+ ((current->type == ELAPI_TYPE_STRING) || (current->type == ELAPI_TYPE_BINARY)))) {
DEBUG_STRING("Replacing item data buffer","");
free(current->data);
current->data = malloc(update_data->length);
@@ -1174,6 +1181,224 @@ int add_any_property(struct collection_item *ci,
return error;
}
+/* Add a string property.
+ If length equals 0, the length is determined based on the string.
+ Lenght INCLUDES the terminating 0 */
+int add_str_property_with_ref(struct collection_item *ci,char *subcollection, char *property,char *string,int length,
+ struct collection_item **ref_ret)
+{
+ int error = EOK;
+ struct collection_item *item;
+
+ DEBUG_STRING("add_str_property_with_ref","Entry.");
+
+ if(length == 0) length = strlen(string) + 1;
+ item = add_property(ci,subcollection,property,(void *)(string),length, ELAPI_TYPE_STRING, &error);
+
+ if(ref_ret != (struct collection_item **)(NULL)) *ref_ret = item;
+
+ DEBUG_NUMBER("add_str_property_with_ref returning",error);
+ return error;
+}
+
+/* Add a binary property. */
+int add_binary_property_with_ref(struct collection_item *ci,char *subcollection, char *property,void *binary_data,int length,
+ struct collection_item **ref_ret)
+{
+ int error = EOK;
+ struct collection_item *item;
+
+ DEBUG_STRING("add_binary_property_with_ref","Entry.");
+
+ item = add_property(ci,subcollection,property,binary_data,length, ELAPI_TYPE_BINARY, &error);
+
+ if(ref_ret != (struct collection_item **)(NULL)) *ref_ret = item;
+
+ DEBUG_NUMBER("add_binary_property_with_ref returning",error);
+ return error;
+}
+
+/* Add an int property. */
+int add_int_property_with_ref(struct collection_item *ci,char *subcollection, char *property,int number,
+ struct collection_item **ref_ret)
+{
+ int error = EOK;
+ struct collection_item *item;
+
+ DEBUG_STRING("add_int_property_with_ref","Entry.");
+
+ item = add_property(ci,subcollection,property,(void *)(&number),sizeof(int), ELAPI_TYPE_INTEGER, &error);
+
+ if(ref_ret != (struct collection_item **)(NULL)) *ref_ret = item;
+
+ DEBUG_NUMBER("add_int_property_with_ref returning",error);
+ return error;
+}
+
+/* Add an unsigned int property. */
+int add_unsigned_property_with_ref(struct collection_item *ci,char *subcollection, char *property,unsigned int number,
+ struct collection_item **ref_ret)
+{
+ int error = EOK;
+ struct collection_item *item;
+
+ DEBUG_STRING("add_unsigned_property_with_ref","Entry.");
+
+ item = add_property(ci,subcollection,property,(void *)(&number),sizeof(int), ELAPI_TYPE_UNSIGNED, &error);
+
+ if(ref_ret != (struct collection_item **)(NULL)) *ref_ret = item;
+
+ DEBUG_NUMBER("add_unsigned_property_with_ref returning",error);
+ return error;
+}
+
+/* Add an long property. */
+int add_long_property_with_ref(struct collection_item *ci,char *subcollection, char *property,long number,
+ struct collection_item **ref_ret)
+{
+ int error = EOK;
+ struct collection_item *item;
+
+ DEBUG_STRING("add_long_property_with_ref","Entry.");
+
+ item = add_property(ci,subcollection,property,(void *)(&number),sizeof(long), ELAPI_TYPE_LONG, &error);
+
+ if(ref_ret != (struct collection_item **)(NULL)) *ref_ret = item;
+
+ DEBUG_NUMBER("add_long_property_with_ref returning",error);
+ return error;
+}
+
+/* Add an unsigned long property. */
+int add_ulong_property_with_ref(struct collection_item *ci,char *subcollection, char *property,unsigned long number,
+ struct collection_item **ref_ret)
+{
+ int error = EOK;
+ struct collection_item *item;
+
+ DEBUG_STRING("add_ulong_property_with_ref","Entry.");
+
+ item = add_property(ci,subcollection,property,(void *)(&number),sizeof(long), ELAPI_TYPE_ULONG, &error);
+
+ if(ref_ret != (struct collection_item **)(NULL)) *ref_ret = item;
+
+ DEBUG_NUMBER("add_ulong_property_with_ref returning",error);
+ return error;
+}
+
+/* Add a double property. */
+int add_double_property_with_ref(struct collection_item *ci,char *subcollection, char *property,double number,
+ struct collection_item **ref_ret)
+{
+ int error = EOK;
+ struct collection_item *item;
+
+ DEBUG_STRING("add_double_property_with_ref","Entry.");
+
+ item = add_property(ci,subcollection,property,(void *)(&number),sizeof(double), ELAPI_TYPE_DOUBLE, &error);
+
+ if(ref_ret != (struct collection_item **)(NULL)) *ref_ret = item;
+
+ DEBUG_NUMBER("add_double_property_with_ref returning",error);
+ return error;
+}
+
+/* A function to add a property */
+int add_any_property_with_ref(struct collection_item *ci,
+ char *subcollection,
+ char *property,
+ int type,
+ void *data,
+ int length,
+ struct collection_item **ref_ret)
+{
+ int error = EOK;
+ struct collection_item *item;
+
+ DEBUG_STRING("add_any_property_with_ref","Entry.");
+
+ item = add_property(ci,subcollection,property,data,length, type, &error);
+
+ if(ref_ret != (struct collection_item **)(NULL)) *ref_ret = item;
+
+ DEBUG_NUMBER("add_any_property_with_ref returning",error);
+ return error;
+}
+
+/* Set time stamp in the collection */
+int set_timestamp(struct collection_item *ci,struct collection_item **timestr_ref,struct collection_item **timeint_ref)
+{
+ time_t utctime;
+ struct tm time_struct;
+ char time_array[TIME_ARRAY_SIZE+1];
+ int len;
+ struct collection_item *timestr = (struct collection_item *)(NULL);
+ struct collection_item *timeint = (struct collection_item *)(NULL);
+
+ DEBUG_STRING("set_timestamp","Entry point");
+
+ utctime = time(NULL);
+ localtime_r(&utctime,&time_struct);
+
+ len = strftime(time_array, TIME_ARRAY_SIZE, date_format, &time_struct);
+ if(len == 0) {
+ DEBUG_STRING("add_time","CODING ERROR - INCREASE THE BUFFER");
+ return EMSGSIZE;
+ }
+
+ /* Check if we have the timestamp item already */
+ error = get_item(event, TS_NAME, ELAPI_TYPE_STRING,ELAPI_TRAVERSE_IGNORE,&timestr);
+ if(error) {
+ DEBUG_NUMBER("search failed with error:",error);
+ return error;
+ }
+
+ if(timestr != (struct collection_item *)(NULL)) {
+ /* There is a timestamp */
+ free(timestr->data);
+ timestr->data = strdup(time_array);
+ if(timestr->data == NULL) {
+ DEBUG_NUMBER("failed to add timestamp property:",error);
+ return ENOMEM;
+ }
+ timestr->length = len+1;
+ *timestr_ref = timestr;
+ }
+ else {
+ /* Add timestamp to the collection */
+ error = add_str_property_with_ref(event,NULL, TS_NAME,time_array,len+1,timestr_ref);
+ if(error) {
+ DEBUG_NUMBER("failed to add timestamp property:",error);
+ return error;
+ }
+ }
+
+ /* Check if we have the time item already */
+ error = get_item(event, T_NAME, ELAPI_TYPE_INTEGER,ELAPI_TRAVERSE_IGNORE,&timeint);
+ if(error) {
+ DEBUG_NUMBER("search failed with error:",error);
+ return error;
+ }
+
+ if(timeint != (struct collection_item *)(NULL)) {
+ /* There is a time property */
+ *((int *)(timeint->data)) = utctime;
+ *timeint_ref = timeint;
+ }
+ else {
+ /* Add time to the collection */
+ error = add_int_property_with_ref(event,NULL, T_NAME,utctime,timeint_ref);
+ if(error) {
+ DEBUG_NUMBER("failed to add time property:",error);
+ return error;
+ }
+ }
+
+ DEBUG_STRING("set_timestamp","Exit point");
+ return EOK;
+}
+
+
/* COPY */
diff --git a/collection/elapi_collection.h b/collection/elapi_collection.h
index 361c0c6..1451484 100644
--- a/collection/elapi_collection.h
+++ b/collection/elapi_collection.h
@@ -55,6 +55,10 @@
#define ELAPI_TRAVERSE_END 0x00000002 /* Call handler once more when end of the collection is reached - good for processing nested collections */
#define ELAPI_TRAVERSE_IGNORE 0x00000004 /* Ignore sub collections at all as if there are none */
+/* Time stamp property name */
+#define TS_NAME "timestamp"
+/* Time property name */
+#define T_NAME "time"
/* Match values */
#define ELAPI_NOMATCH 0
@@ -110,6 +114,29 @@ int add_any_property(struct collection_item *ci, /* Collection to find things
void *data, /* Pointer to the new data */
int length); /* Length of the data. For strings should include trailing 0 */
+/* The functions that add an item and immediately return you this item in the ret_ref paramter */
+int add_str_property_with_ref(struct collection_item *ci,char *subcollection, char *property,char *string,int length,
+ struct collection_item **ret_ref);
+int add_binary_property_with_ref(struct collection_item *ci,char *subcollection, char *property,void *binary_data,int length,
+ struct collection_item **ret_ref);
+int add_int_property_with_ref(struct collection_item *ci,char *subcollection, char *property,int number,
+ struct collection_item **ret_ref);
+int add_unsigned_property_with_ref(struct collection_item *ci,char *subcollection, char *property,unsigned int number,
+ struct collection_item **ret_ref);
+int add_long_property_with_ref(struct collection_item *ci,char *subcollection, char *property,long number,
+ struct collection_item **ret_ref);
+int add_ulong_property_with_ref(struct collection_item *ci,char *subcollection, char *property,unsigned long number,
+ struct collection_item **ret_ref);
+int add_double_property_with_ref(struct collection_item *ci,char *subcollection, char *property,double number,
+ struct collection_item **ret_ref);
+int add_any_property_with_ref(struct collection_item *ci,char *subcollection,char *property,int type,void *data,int length,
+ struct collection_item **ret_ref);
+
+/* Function to create a timestamp */
+/* Automatically adds/updates time and timestamp properties in the collection returning references */
+int set_timestamp(struct collection_item *ci,
+ struct collection_item **timestr_ref,
+ struct collection_item **timeint_ref);
/* Update functions */
@@ -192,7 +219,7 @@ int get_item_and_do(struct collection_item *ci, /* Collection to find thin
/* Convenience function to get individual item */
/* Caller should be aware that this is not a copy of the item
* but the pointer to actual item stored in the collection.
- * The retuned pointer should never be altered or freed by caller of the function.
+ * The returned pointer should never be altered or freed by caller of the function.
* The caller should be sure that the collection does not go out of scope
* while the pointer to its data is in use. */
int get_item(struct collection_item *ci, /* Collection to find things in */
diff --git a/collection/elapi_util.c b/collection/elapi_util.c
index e275703..b5fbf59 100644
--- a/collection/elapi_util.c
+++ b/collection/elapi_util.c
@@ -26,6 +26,23 @@
#include "elapi_debug.h"
#include "elapi_util.h"
+
+/* Internal defines used in different places */
+#define UNKNOWN "<unknown:>"
+#define UNKNOWN_LEN sizeof(UNKNOWN)-1
+#define BAD_FORMAT "<bad format>"
+#define BAD_FORMAT_LEN sizeof(BAD_FORMAT)-1
+
+#define FMT_STRING 0
+#define FMT_INTEGER 1
+#define FMT_UNSIGNED 2
+#define FMT_LONG 3
+#define FMT_ULONG 4
+#define FMT_DOUBLE 5
+
+#define TIMESTAMP "(" TS_NAME ")"
+#define TIMESTAMP_LEN sizeof(TS_NAME) + 1
+
/* Return a static string based on type of the element */
const char *get_type(int type)
{
@@ -515,3 +532,397 @@ int xml_add(char *property,
return EOK;
}
+
+
+/* Extracet and lookup item */
+static int extract_item(char *start,
+ struct collection_item *event,
+ struct collection_item **item,
+ int *index)
+{
+ char *end;
+
+ DEBUG_STRING("extract_item","Entry point");
+
+ start++;
+ end = start;
+ while((*end != ')') && (*end != '\0')) end++;
+
+ if(*end == '\0') return EINVAL;
+
+ *end = '\0';
+ error = get_item(event,start,ELAPI_TYPE_ANY,
+ ELAPI_TRAVERSE_DEFAULT,item);
+ *end = ')';
+ *index += (end-start)+1;
+
+ DEBUG_STRING("extract_item","Exit point");
+ return error;
+}
+
+
+/* Function to serialize one item using provided format if any */
+int sprintf_item(struct serial_data *data,
+ struct collection_item *item,
+ char *one_format)
+{
+ int len;
+ int length;
+ int error = EOK;
+ int i;
+ int len_format = 0;
+ char *formats[] = {"\"%s\"","%d","%u","%ld","%lu","%.4f"};
+ char *fmt;
+ int block;
+ char *start;
+
+ DEBUG_STRING("sprintf_item","Entry point");
+
+ DEBUG_NUMBER("Buffer len: ", data->length);
+ DEBUG_NUMBER("Buffer size: ", data->size);
+ DEBUG_STRING("Buffer: ", data->buffer);
+
+
+ if(one_format!=NULL) len_format = strlen(one_format);
+
+ /* Handle special binary case - ignore format for it */
+ if(item->type == ELAPI_TYPE_BINARY) {
+ /* Bake sure we have enough memory */
+ if((error=grow_buffer(data,item->length * 2 + 2))) return error;
+ /* Put opening quote */
+ *(data->buffer+data->length) = '\'';
+ data->length++;
+ for(i=0;i<item->length;i++) sprintf(data->buffer+data->length+i*2,"%02X",*((unsigned char *)(item->data+i)));
+ data->length+=item->length*2;
+ *(buf_data->buffer+buf_data->length) = '\'';
+ buf_data->length++
+ *(buf_data->buffer+buf_data->length) = '\0';
+ }
+ else {
+
+ /* For other types use a version of sprintf, but determine format first */
+ switch(item->type) {
+ case ELAPI_TYPE_STRING: if((len_format > 0) && (*(one_format+len_format-1) == 's') fmt=one_format;
+ else fmt = formats[FMT_STRING];
+ break;
+ case ELAPI_TYPE_INTEGER: if((len_format > 0) && (*(one_format+len_format-1) != 's')) fmt=one_format;
+ else fmt = formats[FMT_INTEGER];
+ break;
+ case ELAPI_TYPE_UNSIGNED: if((len_format > 0) && (*(one_format+len_format-1) != 's')) fmt=one_format;
+ else fmt = formats[FMT_UNSIGNED];
+ break;
+ case ELAPI_TYPE_LONG: if((len_format > 0) && (*(one_format+len_format-1) != 's')) fmt=one_format;
+ else fmt = formats[FMT_LONG];
+ break;
+ case ELAPI_TYPE_ULONG: if((len_format > 0) && (*(one_format+len_format-1) != 's')) fmt=one_format;
+ else fmt = formats[FMT_ULONG];
+ break;
+ case ELAPI_TYPE_DOUBLE: if((len_format > 0) &&
+ (*(one_format+len_format-1) != 's') &&
+ (*(one_format+len_format-1) != 'c')) fmt=one_format;
+ else fmt = formats[FMT_INTEGER];
+ break;
+ default:
+ /* In case we do not know the type */
+ error = put_marker(data,UNKNOWN,UNKNOWN_LEN);
+ if(error) {
+ DEBUG_NUMBER("put_marker returned error:",error);
+ return error;
+ }
+ error = put_marker(data,item->property,item->property_len);
+ if(error) {
+ DEBUG_NUMBER("put_marker returned error:",error);
+ return error;
+ }
+ DEBUG_STRING("sprintf_item","Unknown item exit point");
+ return EOK;
+ }
+
+ start = buf_data->buffer+buf_data->length;
+ block = buf_data->size-buf_data->length-1;
+
+ while (1) {
+ switch(item->type) {
+ case ELAPI_TYPE_STRING: len = snprintf(start,block,
+ fmt, (char *)(item->data));
+ break;
+ case ELAPI_TYPE_INTEGER: len = snprintf(start,block,
+ fmt, *((int *)(item->data)));
+ break;
+ case ELAPI_TYPE_UNSIGNED: len = snprintf(start,block,
+ fmt, *((unsigned *)(item->data)));
+ break;
+ case ELAPI_TYPE_LONG: len = snprintf(start,block,
+ fmt, *((long *)(item->data)));
+ break;
+ case ELAPI_TYPE_ULONG: len = snprintf(start,block,
+ fmt, *((unsigned long *)(item->data)));
+ break;
+ case ELAPI_TYPE_DOUBLE: len = snprintf(start,block,
+ fmt, *((double *)(item->data)));
+ break;
+ default: /* Not possible */
+ DEBUG_STRING("sprintf_item","Unknown item exit point 2.");
+ return EOK;
+ }
+
+ /* Did it fit? */
+ if (len > -1 && len < block) break;
+
+ /* Else try again with more space. Based on printf example. */
+ if (len > -1) block = MAX(n+1,BLOCK_SIZE);
+ else block = MAX(block *2,BLOCK_SIZE);
+
+ if((error=grow_buffer(data,block))) return error;
+ }
+
+ /* Adjust length */
+ buf_data->length+=len;
+ *(buf_data->buffer+buf_data->length) = '\0';
+ }
+ DEBUG_STRING("Data: ",buf_data->buffer);
+ DEBUG_STRING("sprintf_item","Exit point");
+ return EOK;
+
+}
+
+
+/* If time is missing add it */
+static int add_time(struct serial_data *data,
+ struct collection_item *event)
+{
+ struct collection_item *timestamp;
+
+ DEBUG_STRING("add_time","Entry point");
+
+ error = set_timestamp(event,&timestamp,NULL);
+ if(error) {
+ DEBUG_NUMBER("set_timestamp returned error:",error);
+ return error;
+ }
+
+ error = put_marker(data,timestamp->data,timestamp->length-1);
+ if(error) {
+ DEBUG_NUMBER("put_marker returned error:",error);
+ return error;
+ }
+
+ DEBUG_STRING("add_time","Exit point");
+}
+
+
+/* Internal function to parse out item and put the item data based on the lookup */
+static int process_item(struct serial_data *data,
+ char *format_str,
+ int *index,
+ struct collection_item *event,
+ char *one_format,
+ int *brk)
+{
+ char *start;
+ char *end;
+ int block;
+ struct collection_item *item = (struct collection_item *)(NULL);
+
+ DEBUG_STRING("process_item","Entry point");
+
+ start = format_str + *index;
+ error = extract_item(start,event,&item,index);
+ if(error) {
+ /* This is a problem with format not with memory */
+ error = put_marker(data,BAD_FORMAT,BAD_FORMAT_LEN);
+ if(error) {
+ DEBUG_NUMBER("put_marker bad format returned error:",error);
+ return error;
+ }
+ /* Bad format - we are done */
+ *brk = 1;
+ }
+ else {
+ /* Check if item exists */
+ if(item == (struct collection_item *)(NULL)) {
+
+ if(strncmp(start,TIMESTAMP,TIMESTAMP_LEN) == 0) {
+ DEBUG_STRING("process_item","Adding time");
+ /* Add a timestamp automatically */
+ error = add_time(data,event);
+
+ }
+ else {
+ /* We will put placeholder instead */
+ error = put_marker(data,UNKNOWN,UNKNOWN_LEN);
+ if(error) {
+ DEBUG_NUMBER("put_marker returned error:",error);
+ return error;
+ }
+
+ /* Then put the piece we could not find */
+ error = put_marker(data,start+1,*index-(start-format_str)-2);
+ }
+ if(error) {
+ DEBUG_NUMBER("put_marker/add_time returned error:",error);
+ return error;
+ }
+ (*index)++;
+ DEBUG_STRING("Format after processing not found item:",format_str+*index);
+ }
+ else {
+ /* Item found - call sprintf_item using native format ! */
+ error = sprintf_item(data,item,one_format);
+ if(error) {
+ DEBUG_NUMBER("sprintf_item returned error:",error);
+ return error;
+ }
+ (*index)++;
+ DEBUG_STRING("Format after processing item:",format_str+*index);
+ }
+ }
+ DEBUG_STRING("process_item","Exit");
+ return EOK;
+}
+
+#define CHECK_VALID(x) ((x == 'd')||(x == 'i')||(x == 'o')||(x == 'u')||\
+ (x == 'x')||(x == 'X')||(x == 'c')||(x == 's')||\
+ (x == 'e')||(x == 'E')||(x == 'g')||(x == 'G')||\
+ (x == 'f')||(x == 'F')||(x == 'a')||(x == 'A'))
+
+
+/* Serialize using format */
+int serialize_with_format(struct collection_item *event,
+ char *format_str,
+ struct serial_data *data)
+{
+
+ int i=0;
+ char *one_format;
+ int brk;
+
+ DEBUG_STRING("serialize_with_format","Entry point");
+
+
+ /* Allocate output buffer */
+ errno = 0;
+ data->buffer = malloc(BLOCK_SIZE);
+ if(data->buffer == NULL) {
+ DEBUG_NUMBER("Out of memory",errno);
+ return ENOMEM;
+ }
+ data->size = BLOCK_SIZE;
+ data->length = 0;
+
+ /* Create buffer for format specifier */
+ errno = 0;
+ one_format = malloc(len+1);
+ if(one_format == NULL) {
+ DEBUG_NUMBER("Out of memory",errno);
+ free(data->buffer);
+ data->buffer=NULL;
+ return ENOMEM;
+ }
+
+ while(1) {
+ /* Copy characters directly into output */
+ start = format_str+i;
+ end = start;
+ block = 0;
+ while((*end != '%') && (*end != '\0')) end++;
+ if(end > start) {
+ /* We have a block to copy to output buffer */
+ block = end-start;
+ error = put_marker(data,start,block);
+ if(error) {
+ DEBUG_NUMBER("put_marker returned error:",error);
+ free(data->buffer);
+ data->buffer=NULL;
+ free(one_format);
+ return ENOMEM;
+ }
+ }
+ /* Check if we are done */
+ if(*end == '\0') break;
+
+ /* We are not done - we have %*/
+ i+=block+1;
+
+ /* Here we are at the beginning of the string after % */
+ DEBUG_STRING("Format after %:",format_str+i);
+
+ /* Handle special case */
+ if(*(format_str+i) == '%') {
+ error = put_marker(data,"%",1);
+ if(error) {
+ DEBUG_NUMBER("put_marker returned error:",error);
+ free(data->buffer);
+ data->buffer=NULL;
+ free(one_format);
+ return error;
+ }
+ i++;
+ DEBUG_STRING("Format after processing %%:",format_str+i);
+ continue;
+ }
+
+ /* We are here in case there is a real format token */
+ if(*(format_str+i) == '(') {
+ /* This is our special case when we have a event item specifier () */
+ brk = 0;
+ error = process_item(data,format_str,&i,event,NULL,&brk);
+ if(error) {
+ DEBUG_NUMBER("put_marker bad format returned error:",error);
+ free(data->buffer);
+ data->buffer=NULL;
+ free(one_format);
+ return error;
+ }
+ if(brk) break;
+ continue;
+ }
+
+ /* There is a format specifier ! */
+ start = format_str+i;
+ end = start;
+ block = 0;
+ while((*end != '(') && (*end != '\0')) end++;
+
+ /* Check why we stopped */
+ if((*end == '\0') || (!(CHECK_VALID(*(end-1))))) {
+ /* Someything is not right - put marker and we are done */
+ error = put_marker(data,BAD_FORMAT,BAD_FORMAT_LEN);
+ if(error) {
+ DEBUG_NUMBER("put_marker bad format returned error:",error);
+ free(data->buffer);
+ data->buffer=NULL;
+ free(one_format);
+ return error;
+ }
+ /* We are done */
+ break;
+ }
+
+ /* We are here becuase we have a valid (hopefully) format */
+ block = end - start - 1;
+ memcpy(one_format,start,block);
+ *(one_format+block) = '\0';
+
+ i = end - format_str;
+ brk = 0;
+ error = process_item(data,format_str,&i,event,one_format);
+ if(error) {
+ DEBUG_NUMBER("put_marker bad format returned error:",error);
+ free(data->buffer);
+ data->buffer=NULL;
+ free(one_format);
+ return error;
+ }
+
+ if(brk) break;
+ DEBUG_STRING("Format after another item:",format_str+i);
+ }
+
+ /* Out of the loop */
+ DEBUG_STRING("serialize_with_format","Success Exit");
+ return EOK;
+}
+
+
+
diff --git a/collection/elapi_util.h b/collection/elapi_util.h
index a379ec3..3c2a650 100644
--- a/collection/elapi_util.h
+++ b/collection/elapi_util.h
@@ -22,6 +22,7 @@
#define ELAPI_UTIL_H
#include <libxml/xmlwriter.h>
+#include "elapi_collection.h"
#define DEFAULT_ENCODING "ISO-8859-1"
@@ -90,5 +91,9 @@ int xml_add(char *property,
void *custom_data,
int *dummy);
+/* Serialize using format */
+int serialize_with_format(struct collection_item *event,
+ char *format_str,
+ struct serial_data *data);
#endif