]> sjero.net Git - linphone/blob - tools/lpc2xml.c
Aac-eld add missing header according to RFC3640 3.3.6
[linphone] / tools / lpc2xml.c
1 /*
2 linphone
3 Copyright (C) 2012 Belledonne Communications SARL
4 Yann DIORCET (yann.diorcet@linphone.org)
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 */
20
21 #include "lpc2xml.h"
22 #include <string.h>
23 #include <libxml/xmlsave.h>
24 #include <libxml/xmlversion.h>
25
26 #define LPC2XML_BZ 2048
27
28 struct _lpc2xml_context {
29         const LpConfig *lpc;
30         lpc2xml_function cbf;
31         void *ctx;
32         
33         xmlDoc *doc;
34         char errorBuffer[LPC2XML_BZ];
35         char warningBuffer[LPC2XML_BZ];
36 };
37
38
39 lpc2xml_context* lpc2xml_context_new(lpc2xml_function cbf, void *ctx) {
40         lpc2xml_context *xmlCtx = (lpc2xml_context*)malloc(sizeof(lpc2xml_context));
41         if(xmlCtx != NULL) {
42                 xmlCtx->lpc = NULL;
43                 xmlCtx->cbf = cbf;
44                 xmlCtx->ctx = ctx;
45                 
46                 xmlCtx->doc = NULL;
47                 xmlCtx->errorBuffer[0]='\0';
48                 xmlCtx->warningBuffer[0]='\0';
49         }
50         return xmlCtx;
51 }
52
53 void lpc2xml_context_destroy(lpc2xml_context *ctx) {
54         if(ctx->doc != NULL) {
55                 xmlFreeDoc(ctx->doc);
56                 ctx->doc = NULL;
57         }
58         free(ctx);
59 }
60
61 static void lpc2xml_context_clear_logs(lpc2xml_context *ctx) {
62         ctx->errorBuffer[0]='\0';
63         ctx->warningBuffer[0]='\0';
64 }
65
66 static void lpc2xml_log(lpc2xml_context *xmlCtx, int level, const char *fmt, ...) {
67         va_list args;   
68         va_start(args, fmt);    
69         if(xmlCtx->cbf != NULL) {
70                 xmlCtx->cbf((xmlCtx)->ctx, level, fmt, args);
71         }
72         va_end(args);
73 }
74
75 static void lpc2xml_genericxml_error(void *ctx, const char *fmt, ...) {
76         lpc2xml_context *xmlCtx = (lpc2xml_context *)ctx;
77         int sl = strlen(xmlCtx->errorBuffer);
78         va_list args;   
79         va_start(args, fmt);    
80         vsnprintf(xmlCtx->errorBuffer + sl, LPC2XML_BZ-sl, fmt, args);
81         va_end(args);
82 }
83
84 /*
85 static void lpc2xml_genericxml_warning(void *ctx, const char *fmt, ...) {
86         lpc2xml_context *xmlCtx = (lpc2xml_context *)ctx;
87         int sl = strlen(xmlCtx->warningBuffer);
88         va_list args;   
89         va_start(args, fmt);    
90         vsnprintf(xmlCtx->warningBuffer + sl, LPC2XML_BZ-sl, fmt, args);
91         va_end(args);
92 }
93 */
94
95 static int processEntry(const char *section, const char *entry, xmlNode *node, lpc2xml_context *ctx) {
96         const char *content = lp_config_get_string(ctx->lpc, section, entry, NULL);
97         if(content == NULL) {
98                 lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Issue when reading the lpc");
99                 return -1;
100         }
101         
102         lpc2xml_log(ctx, LPC2XML_MESSAGE, "Set %s|%s = %s", section, entry, content);
103         xmlNodeSetContent(node, (const xmlChar *) content);
104         return 0;
105 }
106
107 struct __processSectionCtx {
108         int ret;
109         const char *section;
110         xmlNode *node;
111         lpc2xml_context *ctx;
112 };
113
114 static void processSection_cb(const char *entry, struct __processSectionCtx *ctx) {
115         if(ctx->ret == 0) {
116                 xmlNode *node = xmlNewChild(ctx->node, NULL, (const xmlChar *)"entry", NULL);
117                 if(node == NULL) {
118                         lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create \"entry\" element");
119                         ctx->ret = -1;
120                         return;
121                 }
122                 xmlAttr *name_attr = xmlSetProp(node, (const xmlChar *)"name", (const xmlChar *)entry);
123                 if(name_attr == NULL) {
124                         lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create name attribute for \"entry\" element");
125                         ctx->ret = -1;
126                         return;
127                 }
128         
129                 ctx->ret = processEntry(ctx->section, entry, node, ctx->ctx);
130         }
131 }
132
133 static int processSection(const char *section, xmlNode *node, lpc2xml_context *ctx) {
134         struct __processSectionCtx pc_ctx = {0, section, node, ctx};
135         lp_config_for_each_entry(ctx->lpc, section, (void (*)(const char *, void *))processSection_cb, (void*)&pc_ctx);
136         return pc_ctx.ret;
137 }
138
139
140
141 struct __processConfigCtx {
142         int ret;
143         xmlNode *node;
144         lpc2xml_context *ctx;
145 };
146
147 static void processConfig_cb(const char *section, struct __processConfigCtx *ctx) {
148         if(ctx->ret == 0) {
149                 xmlNode *node = xmlNewChild(ctx->node, NULL, (const xmlChar *)"section", NULL);
150                 if(node == NULL) {
151                         lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create \"section\" element");
152                         ctx->ret = -1;
153                         return;
154                 }
155                 xmlAttr *name_attr = xmlSetProp(node, (const xmlChar *)"name", (const xmlChar *)section);
156                 if(name_attr == NULL) {
157                         lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create name attribute for \"section\" element");
158                         ctx->ret = -1;
159                         return;
160                 }
161                 ctx->ret = processSection(section, node, ctx->ctx);
162         }
163 }
164
165 static int processConfig(xmlNode *node, lpc2xml_context *ctx) {
166         struct __processConfigCtx pc_ctx = {0, node, ctx};
167         lp_config_for_each_section(ctx->lpc, (void (*)(const char *, void *))processConfig_cb, (void*)&pc_ctx);
168         return pc_ctx.ret;
169 }
170
171 static int processDoc(xmlDoc *doc, lpc2xml_context *ctx) {
172         int ret = 0;
173         xmlNode *root_node = xmlNewNode(NULL, (const xmlChar *)"config");
174         if(root_node == NULL) {
175                 lpc2xml_log(ctx, LPC2XML_ERROR, "Can't create \"config\" element");
176                 return -1;
177         }
178         xmlNs *lpc_ns = xmlNewNs(root_node, (const xmlChar *)"http://www.linphone.org/xsds/lpconfig.xsd", NULL);
179         if(lpc_ns == NULL) {
180                 lpc2xml_log(ctx, LPC2XML_WARNING, "Can't create lpc namespace");
181         } else {
182                 xmlSetNs(root_node, lpc_ns);
183         }
184         xmlNs *xsi_ns = xmlNewNs(root_node, (const xmlChar *)"http://www.w3.org/2001/XMLSchema-instance", (const xmlChar *)"xsi");
185         if(lpc_ns == NULL) {
186                 lpc2xml_log(ctx, LPC2XML_WARNING, "Can't create xsi namespace");
187         }
188         xmlAttr *schemaLocation = xmlNewNsProp(root_node, xsi_ns, (const xmlChar *)"schemaLocation", (const xmlChar *)"http://www.linphone.org/xsds/lpconfig.xsd lpconfig.xsd");
189         if(schemaLocation == NULL) {
190                 lpc2xml_log(ctx, LPC2XML_WARNING, "Can't create schemaLocation");
191         }
192         ret = processConfig(root_node, ctx);
193         xmlDocSetRootElement(doc, root_node);
194         return ret;
195 }
196
197 static int internal_convert_lpc2xml(lpc2xml_context *ctx) {
198         int ret = 0;
199         lpc2xml_log(ctx, LPC2XML_DEBUG, "Generation started");
200         if(ctx->doc != NULL) {
201                 xmlFreeDoc(ctx->doc);
202                 ctx->doc = NULL;
203         }
204         xmlDoc *doc = xmlNewDoc((const xmlChar *)"1.0");
205         ret  = processDoc(doc, ctx);
206         if(ret == 0) {
207                 ctx->doc = doc;
208         } else {
209                 xmlFreeDoc(doc);
210         }
211         lpc2xml_log(ctx, LPC2XML_DEBUG, "Generation ended ret:%d", ret);
212         return ret;
213 }
214
215 int lpc2xml_set_lpc(lpc2xml_context* context, const LpConfig *lpc) {
216         context->lpc = lpc;
217         return 0;
218 }
219
220 int lpc2xml_convert_file(lpc2xml_context* context, const char *filename) {
221         int ret = -1;
222         lpc2xml_context_clear_logs(context);
223         xmlSetGenericErrorFunc(context, lpc2xml_genericxml_error);
224         xmlSaveCtxtPtr save_ctx = xmlSaveToFilename(filename, "UTF-8", XML_SAVE_FORMAT);
225         if(save_ctx != NULL) {
226                 ret = internal_convert_lpc2xml(context);
227                 if(ret == 0) {
228                         ret = xmlSaveDoc(save_ctx, context->doc);
229                         if(ret != 0) {
230                                 lpc2xml_log(context, LPC2XML_ERROR, "Can't save document");
231                                 lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer);
232                         }
233                 }
234                 xmlSaveClose(save_ctx);
235         } else {
236                 lpc2xml_log(context, LPC2XML_ERROR, "Can't open file:%s", filename);
237                 lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer);
238         }
239         return ret;
240 }
241
242 int lpc2xml_convert_fd(lpc2xml_context* context, int fd) {
243         int ret = -1;
244         lpc2xml_context_clear_logs(context);
245         xmlSetGenericErrorFunc(context, lpc2xml_genericxml_error);
246         xmlSaveCtxtPtr save_ctx = xmlSaveToFd(fd, "UTF-8", XML_SAVE_FORMAT);
247         if(save_ctx != NULL) {
248                 ret = internal_convert_lpc2xml(context);
249                 if(ret == 0) {
250                         ret = xmlSaveDoc(save_ctx, context->doc);
251                         if(ret != 0) {
252                                 lpc2xml_log(context, LPC2XML_ERROR, "Can't save document");
253                                 lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer);
254                         }
255                 }
256                 xmlSaveClose(save_ctx);
257         } else {
258                 lpc2xml_log(context, LPC2XML_ERROR, "Can't open fd:%d", fd);
259                 lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer);
260         }
261         return ret;
262 }
263
264 int lpc2xml_convert_string(lpc2xml_context* context, char **content) {
265         int ret = -1;
266         xmlBufferPtr buffer = xmlBufferCreate();
267         lpc2xml_context_clear_logs(context);
268         xmlSetGenericErrorFunc(context, lpc2xml_genericxml_error);
269         xmlSaveCtxtPtr save_ctx = xmlSaveToBuffer(buffer, "UTF-8", XML_SAVE_FORMAT);
270         if(save_ctx != NULL) {
271                 ret = internal_convert_lpc2xml(context);
272                 if(ret == 0) {
273                         ret = xmlSaveDoc(save_ctx, context->doc);
274                         if(ret != 0) {
275                                 lpc2xml_log(context, LPC2XML_ERROR, "Can't save document");
276                                 lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer);
277                         }
278                 }
279                 xmlSaveClose(save_ctx);
280         } else {
281                 lpc2xml_log(context, LPC2XML_ERROR, "Can't initialize internal buffer");
282                 lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer);
283         }
284         if(ret == 0) {
285 #if LIBXML_VERSION >= 20800
286                 *content = (char *)xmlBufferDetach(buffer);
287 #else
288                 *content = strdup((const char *)xmlBufferContent(buffer));
289 #endif
290         }
291         xmlBufferFree(buffer);
292         return ret;
293 }