]>
git.proxmox.com Git - ceph.git/blob - ceph/src/civetweb/src/third_party/LuaXML_lib.c
4 LuaXml is licensed under the terms of the MIT license reproduced below,
5 the same as Lua itself. This means that LuaXml is free software and can be
6 used for both academic and commercial purposes at absolutely no cost.
8 Copyright (C) 2007-2013 Gerald Franz, eludi.net
10 Permission is hereby granted, free of charge, to any person obtaining a copy
11 of this software and associated documentation files (the "Software"), to deal
12 in the Software without restriction, including without limitation the rights
13 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the Software is
15 furnished to do so, subject to the following conditions:
17 The above copyright notice and this permission notice shall be included in
18 all copies or substantial portions of the Software.
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 #if defined __WIN32__ || defined WIN32
31 # define _EXPORT __declspec(dllexport)
40 #include "civetweb_lua.h"
51 static const char ESC
=27;
52 static const char OPN
=28;
53 static const char CLS
=29;
55 //--- auxliary functions -------------------------------------------
57 static const char* char2code(unsigned char ch
, char buf
[8]) {
61 if(ch
>99) buf
[i
++]=ch
/100+48;
62 if(ch
>9) buf
[i
++]=(ch
%100)/10+48;
69 static size_t find(const char* s
, const char* pattern
, size_t start
) {
70 const char* found
=strstr(s
+start
, pattern
);
71 return found
? found
-s
: strlen(s
);
74 //--- internal tokenizer -------------------------------------------
76 typedef struct Tokenizer_s
{
77 /// stores string to be tokenized
79 /// stores size of string to be tokenized
81 /// stores current read position
83 /// stores current read context
85 /// stores next token, if already determined
87 /// size of next token
89 /// pointer to current token
91 /// size of current token
93 /// capacity of current token
94 size_t m_token_capacity
;
97 Tokenizer
* Tokenizer_new(const char* str
, size_t str_size
) {
98 Tokenizer
*tok
= (Tokenizer
*)malloc(sizeof(Tokenizer
));
99 memset(tok
, 0, sizeof(Tokenizer
));
100 tok
->s_size
= str_size
;
105 void Tokenizer_delete(Tokenizer
* tok
) {
110 //void Tokenizer_print(Tokenizer* tok) { printf(" @%u %s\n", tok->i, !tok->m_token ? "(null)" : (tok->m_token[0]==ESC)?"(esc)" : (tok->m_token[0]==OPN)?"(open)": (tok->m_token[0]==CLS)?"(close)" : tok->m_token); fflush(stdout); }
112 static const char* Tokenizer_set(Tokenizer
* tok
, const char* s
, size_t size
) {
113 if(!size
||!s
) return 0;
115 tok
->m_token
= (char*)malloc(size
+1);
116 strncpy(tok
->m_token
,s
, size
);
117 tok
->m_token
[size
] = 0;
118 tok
->m_token_size
= tok
->m_token_capacity
= size
;
119 //Tokenizer_print(tok);
123 static void Tokenizer_append(Tokenizer
* tok
, char ch
) {
124 if(tok
->m_token_size
+1>=tok
->m_token_capacity
) {
125 tok
->m_token_capacity
= (tok
->m_token_capacity
==0) ? 16 : tok
->m_token_capacity
*2;
126 tok
->m_token
= (char*)realloc(tok
->m_token
, tok
->m_token_capacity
);
128 tok
->m_token
[tok
->m_token_size
]=ch
;
129 tok
->m_token
[++tok
->m_token_size
]=0;
132 const char* Tokenizer_next(Tokenizer
* tok
) {
133 const char* ESC_str
= "\033";
134 const char* OPEN_str
= "\034";
135 const char* CLOSE_str
= "\035";
137 int tokenComplete
= 0;
142 tok
->m_token_size
=tok
->m_token_capacity
= 0;
145 while(tok
->m_next_size
|| (tok
->i
< tok
->s_size
)) {
147 if(tok
->m_next_size
) {
148 Tokenizer_set(tok
, tok
->m_next
, tok
->m_next_size
);
154 switch(tok
->s
[tok
->i
]) {
158 if(!quotMode
) quotMode
=tok
->s
[tok
->i
];
159 else if(quotMode
==tok
->s
[tok
->i
]) quotMode
=0;
161 Tokenizer_append(tok
, tok
->s
[tok
->i
]);
164 if(!quotMode
&&(tok
->i
+4<tok
->s_size
)&&(strncmp(tok
->s
+tok
->i
,"<!--",4)==0)) // strip comments
165 tok
->i
=find(tok
->s
, "-->", tok
->i
+4)+2;
166 else if(!quotMode
&&(tok
->i
+9<tok
->s_size
)&&(strncmp(tok
->s
+tok
->i
,"<![CDATA[",9)==0)) { // interpet CDATA
168 tok
->i
=find(tok
->s
, "]]>",b
)+3;
169 if(!tok
->m_token_size
) return Tokenizer_set(tok
, tok
->s
+b
, tok
->i
-b
-3);
171 tok
->m_next
= tok
->s
+b
;
172 tok
->m_next_size
= tok
->i
-b
-3;
175 else if(!quotMode
&&(tok
->i
+1<tok
->s_size
)&&((tok
->s
[tok
->i
+1]=='?')||(tok
->s
[tok
->i
+1]=='!'))) // strip meta information
176 tok
->i
=find(tok
->s
, ">", tok
->i
+2);
177 else if(!quotMode
&&!tok
->tagMode
) {
178 if((tok
->i
+1<tok
->s_size
)&&(tok
->s
[tok
->i
+1]=='/')) {
180 tok
->m_next_size
= 1;
181 tok
->i
=find(tok
->s
, ">", tok
->i
+2);
184 tok
->m_next
= OPEN_str
;
185 tok
->m_next_size
= 1;
190 else Tokenizer_append(tok
, tok
->s
[tok
->i
]);
193 if(tok
->tagMode
&&!quotMode
) {
195 if((tok
->i
+1 < tok
->s_size
) && (tok
->s
[tok
->i
+1]=='>')) {
198 tok
->m_next_size
= 1;
201 else Tokenizer_append(tok
, tok
->s
[tok
->i
]);
203 else Tokenizer_append(tok
, tok
->s
[tok
->i
]);
206 if(!quotMode
&&tok
->tagMode
) {
209 tok
->m_next
= CLOSE_str
;
210 tok
->m_next_size
= 1;
212 else Tokenizer_append(tok
, tok
->s
[tok
->i
]);
218 if(tok
->tagMode
&&!quotMode
) {
219 if(tok
->m_token_size
) tokenComplete
=1;
221 else if(tok
->m_token_size
) Tokenizer_append(tok
, tok
->s
[tok
->i
]);
223 default: Tokenizer_append(tok
, tok
->s
[tok
->i
]);
226 if((tok
->i
>=tok
->s_size
)||(tokenComplete
&&tok
->m_token_size
)) {
228 while(tok
->m_token_size
&&isspace(tok
->m_token
[tok
->m_token_size
-1])) // trim whitespace
229 tok
->m_token
[--tok
->m_token_size
]=0;
230 if(tok
->m_token_size
) break;
233 //Tokenizer_print(tok);
237 //--- local variables ----------------------------------------------
239 /// stores number of special character codes
240 static size_t sv_code_size
=0;
241 /// stores currently allocated capacity for special character codes
242 static size_t sv_code_capacity
=16;
243 /// stores code table for special characters
244 static char** sv_code
=0;
246 //--- public methods -----------------------------------------------
248 static void Xml_pushDecode(lua_State
* L
, const char* s
, size_t s_size
) {
251 const char* found
= strstr(s
, "&#");
252 size_t start
=0, pos
, i
;
257 luaL_buffinit(L
, &b
);
258 found
= strstr(s
, "&#");
259 pos
= found
? found
-s
: s_size
;
264 for(found
+= 2; i
<3; ++i
, ++found
)
266 ch
= ch
* 10 + (*found
- 48);
270 luaL_addlstring(&b
, s
+start
, pos
-start
);
271 luaL_addchar(&b
, ch
);
274 found
= strstr(found
+1, "&#");
275 pos
= found
? found
-s
: s_size
;
278 luaL_addlstring(&b
,s
+start
, pos
-start
);
281 for(i
=sv_code_size
-1; i
<sv_code_size
; i
-=2) {
282 luaL_gsub(L
, lua_tostring(L
,-1), sv_code
[i
], sv_code
[i
-1]);
287 int Xml_eval(lua_State
*L
) {
292 int firstStatement
= 1;
294 if(lua_isuserdata(L
,1))
295 str
= (char*)lua_touserdata(L
,1);
297 const char * sTmp
= luaL_checklstring(L
,1,&str_size
);
298 str
= (char*)malloc(str_size
+1);
299 memcpy(str
, sTmp
, str_size
);
302 tok
= Tokenizer_new(str
, str_size
? str_size
: strlen(str
));
305 while((token
=Tokenizer_next(tok
))!=0) if(token
[0]==OPN
) { // new tag found
307 int newIndex
=lua_rawlen(L
,-1)+1;
308 lua_pushnumber(L
,newIndex
);
311 lua_pushnumber(L
,newIndex
);
315 if (firstStatement
) {
319 else return lua_gettop(L
);
323 lua_pushliteral(L
, "__index");
324 lua_getglobal(L
, "xml");
327 lua_pushliteral(L
, "__tostring"); // set __tostring metamethod
328 lua_getglobal(L
, "xml");
329 lua_pushliteral(L
,"str");
333 lua_setmetatable(L
, -2);
335 // parse tag and content:
336 lua_pushnumber(L
,0); // use index 0 for storing the tag
337 lua_pushstring(L
, Tokenizer_next(tok
));
340 while(((token
= Tokenizer_next(tok
))!=0)&&(token
[0]!=CLS
)&&(token
[0]!=ESC
)) { // parse tag header
341 size_t sepPos
=find(token
, "=", 0);
342 if(token
[sepPos
]) { // regular attribute
343 const char* aVal
=token
+sepPos
+2;
346 lua_pushlstring(L
, token
, sepPos
);
347 lenVal
= strlen(aVal
)-1;
348 if(!lenVal
) Xml_pushDecode(L
, "", 0);
349 else Xml_pushDecode(L
, aVal
, lenVal
);
353 if(!token
||(token
[0]==ESC
)) {
354 if(lua_gettop(L
)>1) lua_settop(L
,-2); // this tag has no content, only attributes
358 else if(token
[0]==ESC
) { // previous tag is over
359 if(lua_gettop(L
)>1) lua_settop(L
,-2); // pop current table
362 else { // read elements
363 lua_pushnumber(L
,lua_rawlen(L
,-1)+1);
364 Xml_pushDecode(L
, token
, 0);
367 Tokenizer_delete(tok
);
369 return lua_gettop(L
);
372 int Xml_load (lua_State
*L
) {
373 const char * filename
= luaL_checkstring(L
,1);
374 FILE * file
=fopen(filename
,"r");
379 return luaL_error(L
,"LuaXml ERROR: \"%s\" file error or file not found!",filename
);
381 fseek (file
, 0 , SEEK_END
);
384 buffer
= (char*)malloc(sz
+1);
385 sz
= fread (buffer
,1,sz
,file
);
388 lua_pushlightuserdata(L
,buffer
);
393 int Xml_registerCode(lua_State
*L
) {
394 const char * decoded
= luaL_checkstring(L
,1);
395 const char * encoded
= luaL_checkstring(L
,2);
398 for(i
=0; i
<sv_code_size
; i
+=2)
399 if(strcmp(sv_code
[i
],decoded
)==0)
400 return luaL_error(L
,"LuaXml ERROR: code already exists.");
401 if(sv_code_size
+2>sv_code_capacity
) {
403 sv_code
= (char**)realloc(sv_code
, sv_code_capacity
*sizeof(char*));
405 sv_code
[sv_code_size
]=(char*)malloc(strlen(decoded
)+1);
406 strcpy(sv_code
[sv_code_size
++], decoded
);
407 sv_code
[sv_code_size
]=(char*)malloc(strlen(encoded
)+1);
408 strcpy(sv_code
[sv_code_size
++],encoded
);
412 int Xml_encode(lua_State
*L
) {
422 luaL_checkstring(L
,-1);
424 for(i
=0; i
<sv_code_size
; i
+=2) {
425 luaL_gsub(L
, lua_tostring(L
,-1), sv_code
[i
], sv_code
[i
+1]);
429 luaL_buffinit(L
, &b
);
430 for(start
=pos
=0; s
[pos
]!=0; ++pos
) if(s
[pos
]<0) {
431 if(pos
>start
) luaL_addlstring(&b
,s
+start
, pos
-start
);
432 luaL_addstring(&b
,char2code((unsigned char)(s
[pos
]),buf
));
436 luaL_addlstring(&b
,s
+start
, pos
-start
);
445 int _EXPORT
luaopen_LuaXML_lib (lua_State
* L
) {
446 static const struct luaL_Reg funcs
[] = {
449 {"encode", Xml_encode
},
450 {"registerCode", Xml_registerCode
},
454 luaL_newlibtable(L
, funcs
);
455 luaL_setfuncs(L
, funcs
, 0);
456 lua_setglobal(L
, "xml");
458 // register default codes:
460 sv_code
=(char**)malloc(sv_code_capacity
*sizeof(char*));
461 sv_code
[sv_code_size
++]="&";
462 sv_code
[sv_code_size
++]="&";
463 sv_code
[sv_code_size
++]="<";
464 sv_code
[sv_code_size
++]="<";
465 sv_code
[sv_code_size
++]=">";
466 sv_code
[sv_code_size
++]=">";
467 sv_code
[sv_code_size
++]="\"";
468 sv_code
[sv_code_size
++]=""";
469 sv_code
[sv_code_size
++]="'";
470 sv_code
[sv_code_size
++]="'";