]> sjero.net Git - linphone/commitdiff
Add lpc2xml tool and fix xml2lpc validation
authorYann Diorcet <yann.diorcet@belledonne-communications.com>
Wed, 16 Jan 2013 13:36:31 +0000 (14:36 +0100)
committerYann Diorcet <yann.diorcet@belledonne-communications.com>
Wed, 16 Jan 2013 13:36:31 +0000 (14:36 +0100)
tools/Makefile.am
tools/lpc2xml.c [new file with mode: 0644]
tools/lpc2xml.h [new file with mode: 0644]
tools/lpc2xml_test.c [new file with mode: 0644]
tools/xml2lpc.c

index e906e29b07f02befd70ff1b7c7343ca0080ef6c5..ffb4692148335bbb8ae5c5c4634324d87fa2f701 100644 (file)
@@ -13,29 +13,46 @@ COMMON_CFLAGS=\
 
 if BUILD_TOOLS
 
-lib_LTLIBRARIES=libxml2lpc.la
+lib_LTLIBRARIES=libxml2lpc.la liblpc2xml.la
 
 libxml2lpc_la_SOURCES=\
        xml2lpc.c \
        xml2lpc.h
 
+liblpc2xml_la_SOURCES=\
+       lpc2xml.c \
+       lpc2xml.h
+
 libxml2lpc_la_CFLAGS=$(COMMON_CFLAGS)
 libxml2lpc_la_LIBADD=\
        $(top_builddir)/coreapi/liblinphone.la \
        $(LIBXML2_LIBS) 
 
+liblpc2xml_la_CFLAGS=$(COMMON_CFLAGS)
+liblpc2xml_la_LIBADD=\
+       $(top_builddir)/coreapi/liblinphone.la \
+       $(LIBXML2_LIBS) 
+
 libxml2lpc_la_LDFLAGS=-no-undefined
+liblpc2xml_la_LDFLAGS=-no-undefined
 
-bin_PROGRAMS=xml2lpc_test
+bin_PROGRAMS=xml2lpc_test lpc2xml_test
 
 xml2lpc_test_SOURCES=\
        xml2lpc_test.c
 
+lpc2xml_test_SOURCES=\
+       lpc2xml_test.c
+
 xml2lpc_test_CFLAGS=$(COMMON_CFLAGS)
 xml2lpc_test_LDADD=\
        $(top_builddir)/coreapi/liblinphone.la \
        libxml2lpc.la 
 
+lpc2xml_test_CFLAGS=$(COMMON_CFLAGS)
+lpc2xml_test_LDADD=\
+       $(top_builddir)/coreapi/liblinphone.la \
+       liblpc2xml.la 
 endif
 
 
diff --git a/tools/lpc2xml.c b/tools/lpc2xml.c
new file mode 100644 (file)
index 0000000..cd0df72
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+linphone
+Copyright (C) 2012 Belledonne Communications SARL
+Yann DIORCET (yann.diorcet@linphone.org)
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+#include "lpc2xml.h"
+#include <string.h>
+#include <libxml/xmlsave.h>
+
+
+#define LPC2XML_BZ 2048
+
+struct _lpc2xml_context {
+       const LpConfig *lpc;
+       lpc2xml_function cbf;
+       void *ctx;
+       
+       xmlDoc *doc;
+       char errorBuffer[LPC2XML_BZ];
+       char warningBuffer[LPC2XML_BZ];
+};
+
+
+lpc2xml_context* lpc2xml_context_new(lpc2xml_function cbf, void *ctx) {
+       lpc2xml_context *xmlCtx = (lpc2xml_context*)malloc(sizeof(lpc2xml_context));
+       if(xmlCtx != NULL) {
+               xmlCtx->lpc = NULL;
+               xmlCtx->cbf = cbf;
+               xmlCtx->ctx = ctx;
+               
+               xmlCtx->doc = NULL;
+               xmlCtx->errorBuffer[0]='\0';
+               xmlCtx->warningBuffer[0]='\0';
+       }
+       return xmlCtx;
+}
+
+void lpc2xml_context_destroy(lpc2xml_context *ctx) {
+       if(ctx->doc != NULL) {
+               xmlFreeDoc(ctx->doc);
+               ctx->doc = NULL;
+       }
+       free(ctx);
+}
+/*
+static void lpc2xml_context_clear_logs(lpc2xml_context *ctx) {
+       ctx->errorBuffer[0]='\0';
+       ctx->warningBuffer[0]='\0';
+}*/
+
+static void lpc2xml_log(lpc2xml_context *xmlCtx, int level, const char *fmt, ...) {
+       va_list args;   
+       va_start(args, fmt);    
+       if(xmlCtx->cbf != NULL) {
+               xmlCtx->cbf((xmlCtx)->ctx, level, fmt, args);
+       }
+       va_end(args);
+}
+/*
+static void lpc2xml_genericxml_error(void *ctx, const char *fmt, ...) {
+       lpc2xml_context *xmlCtx = (lpc2xml_context *)ctx;
+       int sl = strlen(xmlCtx->errorBuffer);
+       va_list args;   
+       va_start(args, fmt);    
+       vsnprintf(xmlCtx->errorBuffer + sl, LPC2XML_BZ-sl, fmt, args);
+       va_end(args);
+}
+
+static void lpc2xml_genericxml_warning(void *ctx, const char *fmt, ...) {
+       lpc2xml_context *xmlCtx = (lpc2xml_context *)ctx;
+       int sl = strlen(xmlCtx->warningBuffer);
+       va_list args;   
+       va_start(args, fmt);    
+       vsnprintf(xmlCtx->warningBuffer + sl, LPC2XML_BZ-sl, fmt, args);
+       va_end(args);
+}*/
+
+#if 0
+static void dumpNodes(int level, xmlNode * a_node, lpc2xml_context *ctx) {
+       xmlNode *cur_node = NULL;
+
+       for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
+               if (cur_node->type == XML_ELEMENT_NODE) {
+                       lpc2xml_log(ctx, LPC2XML_DEBUG, "node level: %d type: Element, name: %s", level, cur_node->name);
+               } else {
+                       lpc2xml_log(ctx, LPC2XML_DEBUG, "node level: %d type: %d, name: %s", level, cur_node->type, cur_node->name);
+               }
+
+               dumpNodes(level + 1, cur_node->children, ctx);
+       }
+}
+#endif
+
+#if 0
+static void dumpNode(xmlNode *node, lpc2xml_context *ctx) {
+               lpc2xml_log(ctx, LPC2XML_DEBUG, "node type: %d, name: %s", node->type, node->name);
+}
+
+static void dumpAttr(xmlNode *node, lpc2xml_context *ctx) {
+               lpc2xml_log(ctx, LPC2XML_DEBUG, "attr name: %s value:%s", node->name, node->children->content);
+}
+
+static void dumpContent(xmlNode *node, lpc2xml_context *ctx) {
+               lpc2xml_log(ctx, LPC2XML_DEBUG, "content: %s", node->children->content);
+}
+
+
+
+#endif
+
+static int processEntry(const char *section, const char *entry, xmlNode *node, lpc2xml_context *ctx) {
+       const char *content = lp_config_get_string(ctx->lpc, section, entry, NULL);
+       if(content == NULL) {
+               lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Issue when reading the lpc");
+               return -1;
+       }
+       xmlNodeSetContent(node, (const xmlChar *) content);
+       return 0;
+}
+
+struct __processSectionCtx {
+       int ret;
+       const char *section;
+       xmlNode *node;
+       lpc2xml_context *ctx;
+};
+
+static void processSection_cb(const char *entry, struct __processSectionCtx *ctx) {
+       if(ctx->ret == 0) {
+               xmlNode *node = xmlNewChild(ctx->node, NULL, (const xmlChar *)"entry", NULL);
+               if(node == NULL) {
+                       lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create \"entry\" element");
+                       ctx->ret = -1;
+                       return;
+               }
+               xmlAttr *name_attr = xmlSetProp(node, (const xmlChar *)"name", (const xmlChar *)entry);
+               if(name_attr == NULL) {
+                       lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create name attribute for \"entry\" element");
+                       ctx->ret = -1;
+                       return;
+               }
+               ctx->ret = processEntry(ctx->section, entry, node, ctx->ctx);
+       }
+}
+
+static int processSection(const char *section, xmlNode *node, lpc2xml_context *ctx) {
+       struct __processSectionCtx pc_ctx = {0, section, node, ctx};
+       lp_config_for_each_entry(ctx->lpc, section, (void (*)(const char *, void *))processSection_cb, (void*)&pc_ctx);
+       return pc_ctx.ret;
+}
+
+
+
+struct __processConfigCtx {
+       int ret;
+       xmlNode *node;
+       lpc2xml_context *ctx;
+};
+
+static void processConfig_cb(const char *section, struct __processConfigCtx *ctx) {
+       if(ctx->ret == 0) {
+               xmlNode *node = xmlNewChild(ctx->node, NULL, (const xmlChar *)"section", NULL);
+               if(node == NULL) {
+                       lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create \"section\" element");
+                       ctx->ret = -1;
+                       return;
+               }
+               xmlAttr *name_attr = xmlSetProp(node, (const xmlChar *)"name", (const xmlChar *)section);
+               if(name_attr == NULL) {
+                       lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create name attribute for \"section\" element");
+                       ctx->ret = -1;
+                       return;
+               }
+               ctx->ret = processSection(section, node, ctx->ctx);
+       }
+}
+
+static int processConfig(xmlNode *node, lpc2xml_context *ctx) {
+       struct __processConfigCtx pc_ctx = {0, node, ctx};
+       lp_config_for_each_section(ctx->lpc, (void (*)(const char *, void *))processConfig_cb, (void*)&pc_ctx);
+       return pc_ctx.ret;
+}
+
+static int processDoc(xmlDoc *doc, lpc2xml_context *ctx) {
+       int ret = 0;
+       xmlNode *root_node = xmlNewNode(NULL, (const xmlChar *)"config");
+       if(root_node == NULL) {
+               lpc2xml_log(ctx, LPC2XML_ERROR, "Can't create \"config\" element");
+               return -1;
+       }
+       xmlNs *lpc_ns = xmlNewNs(root_node, (const xmlChar *)"http://www.linphone.org/xsds/lpconfig.xsd", (const xmlChar *)"lpc");
+       if(lpc_ns == NULL) {
+               lpc2xml_log(ctx, LPC2XML_WARNING, "Can't create lpc namespace");
+       } else {
+               xmlSetNs(root_node, lpc_ns);
+       }
+       xmlNs *xsi_ns = xmlNewNs(root_node, (const xmlChar *)"http://www.w3.org/2001/XMLSchema-instance", (const xmlChar *)"xsi");
+       if(lpc_ns == NULL) {
+               lpc2xml_log(ctx, LPC2XML_WARNING, "Can't create xsi namespace");
+       }
+       xmlAttr *schemaLocation = xmlNewNsProp(root_node, xsi_ns, (const xmlChar *)"schemaLocation", (const xmlChar *)"http://www.linphone.org/xsds/lpconfig.xsd lpconfig.xsd ");
+       if(schemaLocation == NULL) {
+               lpc2xml_log(ctx, LPC2XML_WARNING, "Can't create schemaLocation");
+       }
+       ret = processConfig(root_node, ctx);
+       xmlDocSetRootElement(doc, root_node);
+       return ret;
+}
+
+static int internal_convert_lpc2xml(lpc2xml_context *ctx) {
+       int ret = 0;
+       lpc2xml_log(ctx, LPC2XML_DEBUG, "Generation started");
+       if(ctx->doc != NULL) {
+               xmlFreeDoc(ctx->doc);
+               ctx->doc = NULL;
+       }
+       xmlDoc *doc = xmlNewDoc((const xmlChar *)"1.0");
+       ret  = processDoc(doc, ctx);
+       if(ret == 0) {
+               ctx->doc = doc;
+       } else {
+               xmlFreeDoc(doc);
+       }
+       lpc2xml_log(ctx, LPC2XML_DEBUG, "Generation ended ret:%d", ret);
+       return ret;
+}
+
+int lpc2xml_set_lpc(lpc2xml_context* context, const LpConfig *lpc) {
+       context->lpc = lpc;
+       return 0;
+}
+
+int lpc2xml_convert_file(lpc2xml_context* context, const char *filename) {
+       int ret = 0;
+       xmlSaveCtxtPtr save_ctx = xmlSaveToFilename(filename, "UTF-8", XML_SAVE_FORMAT);
+       ret = internal_convert_lpc2xml(context);
+       if(ret == 0) {
+               ret = xmlSaveDoc(save_ctx, context->doc);
+       }
+       xmlSaveClose(save_ctx);
+       return ret;
+}
+
+int lpc2xml_convert_fd(lpc2xml_context* context, int fd) {
+       int ret = 0;
+       xmlSaveCtxtPtr save_ctx = xmlSaveToFd(fd, "UTF-8", XML_SAVE_FORMAT);
+       ret = internal_convert_lpc2xml(context);
+       if(ret == 0) {
+               ret = xmlSaveDoc(save_ctx, context->doc);
+       }
+       xmlSaveClose(save_ctx);
+       return ret;
+}
+
+int lpc2xml_convert_string(lpc2xml_context* context, unsigned char **content) {
+       int ret = 0;
+       xmlBufferPtr buffer = xmlBufferCreate();
+       xmlSaveCtxtPtr save_ctx = xmlSaveToBuffer(buffer, "UTF-8", XML_SAVE_FORMAT);
+       internal_convert_lpc2xml(context);
+       if(ret == 0) {
+               ret = xmlSaveDoc(save_ctx, context->doc);
+       }
+       xmlSaveClose(save_ctx);
+       if(ret == 0) {
+               *content = xmlBufferDetach(buffer);
+       }
+       xmlBufferFree(buffer);
+       return ret;
+}
diff --git a/tools/lpc2xml.h b/tools/lpc2xml.h
new file mode 100644 (file)
index 0000000..f158310
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+linphone
+Copyright (C) 2012 Belledonne Communications SARL
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+#ifndef LPC2XML_H_
+#define LPC2XML_H_
+
+#include "lpconfig.h"
+
+typedef struct _lpc2xml_context lpc2xml_context;
+
+typedef enum _lpc2xml_log_level {
+       LPC2XML_DEBUG = 0,
+       LPC2XML_MESSAGE,
+       LPC2XML_WARNING,
+       LPC2XML_ERROR
+} lpc2xml_log_level;
+
+typedef void(*lpc2xml_function)(void *ctx, lpc2xml_log_level level, const char *fmt, va_list list);
+
+lpc2xml_context* lpc2xml_context_new(lpc2xml_function cbf, void *ctx);
+void lpc2xml_context_destroy(lpc2xml_context*);
+
+int lpc2xml_set_lpc(lpc2xml_context* context, const LpConfig *lpc);
+
+int lpc2xml_convert_file(lpc2xml_context* context, const char *filename);
+int lpc2xml_convert_fd(lpc2xml_context* context, int fd);
+int lpc2xml_convert_string(lpc2xml_context* context, unsigned char **content);
+
+
+#endif //LPC2XML_H_
diff --git a/tools/lpc2xml_test.c b/tools/lpc2xml_test.c
new file mode 100644 (file)
index 0000000..cdad72f
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+linphone
+Copyright (C) 2012 Belledonne Communications SARL
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+#include <stdio.h>
+#include "lpc2xml.h"
+
+void cb_function(void *ctx, lpc2xml_log_level level, const char *msg, va_list list) {
+       const char *header = "";
+       switch(level) {
+               case LPC2XML_DEBUG:
+                       header = "DEBUG";
+                       break;
+               case LPC2XML_MESSAGE:
+                       header = "MESSAGE";
+                       break;
+               case LPC2XML_WARNING:
+                       header = "WARNING";
+                       break;
+               case LPC2XML_ERROR:
+                       header = "ERROR";
+                       break;
+       }
+       fprintf(stdout, "%s - ", header);
+       vfprintf(stdout, msg, list);
+       fprintf(stdout, "\n");
+}
+
+void show_usage(int argc, char *argv[]) {
+       fprintf(stderr, "usage %s convert <lpc_file> <xml_file>\n",
+                       argv[0]);
+}
+
+int main(int argc, char *argv[]) {
+       if(argc != 4) {
+               show_usage(argc, argv);
+               return -1;
+       }
+       
+       lpc2xml_context *ctx = lpc2xml_context_new(cb_function, NULL);
+       LpConfig *lpc = lp_config_new(argv[2]);
+       lpc2xml_set_lpc(ctx, lpc);
+       if(strcmp("convert", argv[1]) == 0) {
+               lpc2xml_convert_file(ctx, argv[3]);
+       } else {
+               show_usage(argc, argv);
+       }
+       lp_config_destroy(lpc);
+       lpc2xml_context_destroy(ctx);
+       return 0;
+}
+
index d5e2160ab22896d481eb02a1d7fa54e28587be76..9d720f1f36fec48910792dafd92f7e0d2ebefc38 100644 (file)
@@ -78,7 +78,7 @@ static void xml2lpc_log(xml2lpc_context *xmlCtx, int level, const char *fmt, ...
        va_end(args);
 }
 
-static void xml2lpc_genericxml_error(void *ctx, const char *fmt, ...) {        
+static void xml2lpc_genericxml_error(void *ctx, const char *fmt, ...) {
        xml2lpc_context *xmlCtx = (xml2lpc_context *)ctx;
        int sl = strlen(xmlCtx->errorBuffer);
        va_list args;   
@@ -87,7 +87,7 @@ static void xml2lpc_genericxml_error(void *ctx, const char *fmt, ...) {
        va_end(args);
 }
 
-static void xml2lpc_genericxml_warning(void *ctx, const char *fmt, ...) {      
+static void xml2lpc_genericxml_warning(void *ctx, const char *fmt, ...) {
        xml2lpc_context *xmlCtx = (xml2lpc_context *)ctx;
        int sl = strlen(xmlCtx->warningBuffer);
        va_list args;   
@@ -214,11 +214,11 @@ static int processDoc(xmlNode *node, xml2lpc_context *ctx) {
        return 0;
 }
 
-static int internal_convert_xml2lpc(xmlDoc *doc, xml2lpc_context *ctx) {
+static int internal_convert_xml2lpc(xml2lpc_context *ctx) {
        xml2lpc_log(ctx, XML2LPC_DEBUG, "Parse started");
-       xmlNode *rootNode = xmlDocGetRootElement(doc);
+       xmlNode *rootNode = xmlDocGetRootElement(ctx->doc);
        //dumpNodes(0, rootNode, cbf, ctx);
-        int ret = processDoc(rootNode, ctx);
+       int ret = processDoc(rootNode, ctx);
        xml2lpc_log(ctx, XML2LPC_DEBUG, "Parse ended ret:%d", ret);
        return ret;
 }
@@ -230,10 +230,10 @@ int xml2lpc_validate(xml2lpc_context *xmlCtx) {
        validCtx = xmlSchemaNewValidCtxt(xmlSchemaParse(parserCtx));
        xmlSchemaSetValidErrors(validCtx, xml2lpc_genericxml_error, xml2lpc_genericxml_warning, xmlCtx);
        int ret =  xmlSchemaValidateDoc(validCtx, xmlCtx->doc);
-       if(ret >0) {
+       if(ret > 0) {
                xml2lpc_log(xmlCtx, XML2LPC_WARNING, "%s", xmlCtx->warningBuffer);
                xml2lpc_log(xmlCtx, XML2LPC_ERROR, "%s", xmlCtx->errorBuffer);
-       } else {
+       } else if(ret < 0) {
                xml2lpc_log(xmlCtx, XML2LPC_ERROR, "Internal error");
        }
        xmlSchemaFreeValidCtxt(validCtx);
@@ -243,7 +243,7 @@ int xml2lpc_validate(xml2lpc_context *xmlCtx) {
 int xml2lpc_convert(xml2lpc_context *xmlCtx, LpConfig *lpc) {
        xml2lpc_context_clear_logs(xmlCtx);
        xmlCtx->lpc = lpc;
-       return internal_convert_xml2lpc(xmlCtx->doc, xmlCtx);
+       return internal_convert_xml2lpc(xmlCtx);
 }
 
 int xml2lpc_set_xml_file(xml2lpc_context* xmlCtx, const char *filename) {