ruby-xml-smart 0.1.11-i486-linux

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/AUTHORS +4 -0
  2. data/COPYING +504 -0
  3. data/Changelog +192 -0
  4. data/README +52 -0
  5. data/Rakefile +112 -0
  6. data/TODO +6 -0
  7. data/examples/EXAMPLE.xml +17 -0
  8. data/examples/EXAMPLE.xml.sic +17 -0
  9. data/examples/Visualise/EXAMPLE.xml +18 -0
  10. data/examples/Visualise/term-ansicolor-0.0.4/CHANGES +11 -0
  11. data/examples/Visualise/term-ansicolor-0.0.4/GPL +340 -0
  12. data/examples/Visualise/term-ansicolor-0.0.4/README.en +23 -0
  13. data/examples/Visualise/term-ansicolor-0.0.4/Rakefile +72 -0
  14. data/examples/Visualise/term-ansicolor-0.0.4/VERSION +1 -0
  15. data/examples/Visualise/term-ansicolor-0.0.4/examples/cdiff.rb +20 -0
  16. data/examples/Visualise/term-ansicolor-0.0.4/examples/example.rb +82 -0
  17. data/examples/Visualise/term-ansicolor-0.0.4/install.rb +12 -0
  18. data/examples/Visualise/term-ansicolor-0.0.4/lib/term/ansicolor.rb +78 -0
  19. data/examples/Visualise/xpath_visual.rb +45 -0
  20. data/examples/add_children.rb +14 -0
  21. data/examples/add_elements.rb +13 -0
  22. data/examples/attrs.rb +15 -0
  23. data/examples/children.rb +14 -0
  24. data/examples/concurrent.rb +30 -0
  25. data/examples/copy.rb +23 -0
  26. data/examples/create.rb +18 -0
  27. data/examples/delete.rb +30 -0
  28. data/examples/move_elements.rb +12 -0
  29. data/examples/namespace.rb +14 -0
  30. data/examples/namespace_detailed.rb +36 -0
  31. data/examples/namespace_find.rb +20 -0
  32. data/examples/pull.rb +18 -0
  33. data/examples/qname.rb +16 -0
  34. data/examples/replace.rb +14 -0
  35. data/examples/set_OR_replace.rb +32 -0
  36. data/examples/signals.rb +28 -0
  37. data/examples/string.rb +27 -0
  38. data/examples/write.rb +11 -0
  39. data/examples/xpath_attrs.rb +19 -0
  40. data/examples/xpath_functions.rb +7 -0
  41. data/examples/xpath_root.rb +6 -0
  42. data/extconf.rb +29 -0
  43. data/rbxs.c +136 -0
  44. data/rbxs.h +53 -0
  45. data/rbxs_dom.c +483 -0
  46. data/rbxs_dom.h +32 -0
  47. data/rbxs_domattribute.c +189 -0
  48. data/rbxs_domattribute.h +18 -0
  49. data/rbxs_domattributeset.c +182 -0
  50. data/rbxs_domattributeset.h +17 -0
  51. data/rbxs_domelement.c +656 -0
  52. data/rbxs_domelement.h +18 -0
  53. data/rbxs_domnamespace.c +127 -0
  54. data/rbxs_domnamespace.h +18 -0
  55. data/rbxs_domnamespaceset.c +276 -0
  56. data/rbxs_domnamespaceset.h +17 -0
  57. data/rbxs_domnodeset.c +284 -0
  58. data/rbxs_domnodeset.h +19 -0
  59. data/rbxs_domother.c +121 -0
  60. data/rbxs_domother.h +18 -0
  61. data/rbxs_domtext.c +165 -0
  62. data/rbxs_domtext.h +18 -0
  63. data/rbxs_pull.c +244 -0
  64. data/rbxs_pull.h +17 -0
  65. data/rbxs_pullattribute.c +124 -0
  66. data/rbxs_pullattribute.h +18 -0
  67. data/rbxs_pullattributeset.c +156 -0
  68. data/rbxs_pullattributeset.h +17 -0
  69. data/rbxs_qname.c +267 -0
  70. data/rbxs_qname.h +18 -0
  71. data/rbxs_utils.h +39 -0
  72. data/test/namespace_test.rb +83 -0
  73. metadata +125 -0
data/rbxs_dom.c ADDED
@@ -0,0 +1,483 @@
1
+ #include "rbxs_dom.h"
2
+ #include "rbxs_domelement.h"
3
+ #include "rbxs_domnodeset.h"
4
+
5
+ #include <sys/types.h>
6
+ #include <sys/stat.h>
7
+ #include <time.h>
8
+ #include <fcntl.h>
9
+ #include <unistd.h>
10
+
11
+ /* -- */
12
+ // ***********************************************************************************
13
+ // GC
14
+ // ***********************************************************************************
15
+ void rbxs_dom_free(rbxs_dom *prbxs_dom) {
16
+ if (prbxs_dom != NULL) {
17
+ xmlFreeDoc(prbxs_dom->doc);
18
+ xmlCleanupParser();
19
+ free(prbxs_dom);
20
+ }
21
+ }
22
+
23
+ void rbxs_dom_mark(rbxs_dom *prbxs_dom) {
24
+ if (prbxs_dom == NULL) return;
25
+ if (!NIL_P(prbxs_dom->changeHandlers)) rb_gc_mark(prbxs_dom->changeHandlers);
26
+ if (!NIL_P(prbxs_dom->namespaces)) rb_gc_mark(prbxs_dom->namespaces);
27
+ }
28
+
29
+ //***********************************************************************************
30
+ // Methods
31
+ //***********************************************************************************
32
+ /* ++ */
33
+ static int nslist_each(VALUE key, VALUE value, xmlXPathContextPtr arg) {
34
+ if (xmlXPathRegisterNs(arg,(unsigned char *)StringValuePtr(key),(unsigned char *)StringValuePtr(value)) != 0) {
35
+ xmlXPathFreeContext(arg);
36
+ rb_raise(rb_eRuntimeError, "Couldn't add namespace");
37
+ }
38
+ return ST_CONTINUE;
39
+ }
40
+
41
+ static int nslistset_each(VALUE key, VALUE value) {
42
+ Check_Type(key, T_STRING);
43
+ Check_Type(value, T_STRING);
44
+ return ST_CONTINUE;
45
+ }
46
+
47
+ /*
48
+ * Documentation
49
+ */
50
+ VALUE rbxs_dom_inspect(VALUE self)
51
+ {
52
+ VALUE *argv;
53
+
54
+ argv = ALLOCA_N(VALUE, 3);
55
+ argv[0] = rb_str_new2("#<%s:0x%x>");
56
+ argv[1] = CLASS_OF(self);
57
+ argv[2] = rb_obj_id(self);
58
+ return(rb_f_sprintf(3, argv));
59
+ }
60
+
61
+ /*
62
+ * Documentation
63
+ */
64
+ VALUE rbxs_dom_to_s(VALUE self)
65
+ {
66
+ rbxs_dom *prbxs_dom;
67
+ xmlChar *result;
68
+ VALUE ret;
69
+ int len;
70
+
71
+ Data_Get_Struct(self, rbxs_dom, prbxs_dom);
72
+ if (prbxs_dom->doc == NULL) {
73
+ return(Qnil);
74
+ } else if (prbxs_dom->doc->encoding != NULL) {
75
+ xmlDocDumpFormatMemoryEnc(prbxs_dom->doc, &result, &len, (char *)prbxs_dom->doc->encoding, 1);
76
+ } else {
77
+ xmlDocDumpFormatMemory(prbxs_dom->doc, &result, &len, 1);
78
+ }
79
+
80
+ ret = rb_str_new2((char *)result);
81
+ xmlFree(result);
82
+ return(ret);
83
+ }
84
+
85
+ /*
86
+ * Documentation
87
+ */
88
+ VALUE rbxs_dom_root_set(VALUE self, VALUE element)
89
+ {
90
+ rbxs_dom *prbxs_dom;
91
+ rbxs_domelement *prbxs_domelement;
92
+ xmlNodePtr root,newnode;
93
+
94
+ if (rb_obj_is_kind_of(element, cSmartDomElement)) {
95
+ Data_Get_Struct(self, rbxs_dom, prbxs_dom);
96
+ Data_Get_Struct(element, rbxs_domelement, prbxs_domelement);
97
+ newnode = xmlCopyNode(prbxs_domelement->node,1); // 1 == deep
98
+ root = xmlDocGetRootElement(prbxs_dom->doc);
99
+ xmlUnlinkNode(root);
100
+ xmlFreeNode (root);
101
+ root = xmlDocSetRootElement(prbxs_dom->doc,newnode);
102
+ if (root) {
103
+ VALUE ret = rbxs_domelement_new(cSmartDomElement, self, root);
104
+ rbxs_dom_change_handlers_execute(prbxs_dom,RBXS_DOM_SIGNAL_CHANGE,ret);
105
+ return(ret);
106
+ }
107
+ } else
108
+ rb_raise(rb_eArgError, "takes an element as argument");
109
+ return(Qnil);
110
+ }
111
+
112
+ /*
113
+ * Documentation
114
+ */
115
+ VALUE rbxs_dom_encode_entities_set(VALUE self, VALUE value)
116
+ {
117
+ rbxs_dom *prbxs_dom;
118
+ Data_Get_Struct(self, rbxs_dom, prbxs_dom);
119
+ switch (TYPE(value)) {
120
+ case T_FALSE:
121
+ prbxs_dom->encodeEntities = 0;
122
+ return Qfalse;
123
+ case T_TRUE:
124
+ prbxs_dom->encodeEntities = 1;
125
+ return Qtrue;
126
+ default:
127
+ rb_raise(rb_eArgError, "can be set to TRUE or FALSE");
128
+ }
129
+ }
130
+
131
+ /*
132
+ * Documentation
133
+ */
134
+ VALUE rbxs_dom_encode_entities_q(VALUE self)
135
+ {
136
+ rbxs_dom *prbxs_dom;
137
+ Data_Get_Struct(self, rbxs_dom, prbxs_dom);
138
+ if (prbxs_dom->encodeEntities == 0)
139
+ return(Qfalse);
140
+ else
141
+ return(Qtrue);
142
+ }
143
+
144
+ /*
145
+ * Documentation
146
+ */
147
+ VALUE rbxs_dom_root(VALUE self)
148
+ {
149
+ rbxs_dom *prbxs_dom;
150
+ xmlNodePtr root;
151
+
152
+ Data_Get_Struct(self, rbxs_dom, prbxs_dom);
153
+ root = xmlDocGetRootElement(prbxs_dom->doc);
154
+ if (root)
155
+ return(rbxs_domelement_new(cSmartDomElement, self, root));
156
+ else
157
+ return(Qnil);
158
+ }
159
+
160
+ /*
161
+ * Documentation
162
+ */
163
+ VALUE rbxs_dom_save_as(VALUE self, VALUE file)
164
+ {
165
+ Check_Type(file, T_FILE);
166
+ rb_io_write(file,rbxs_dom_to_s(self));
167
+ return(Qtrue);
168
+ }
169
+
170
+ /*
171
+ * Documentation
172
+ */
173
+ VALUE rbxs_dom_find(int argc, VALUE *argv, VALUE self)
174
+ {
175
+ rbxs_dom *prbxs_dom;
176
+ xmlXPathContextPtr ctxt;
177
+ xmlXPathObjectPtr obj;
178
+ xmlNodePtr root;
179
+ VALUE set;
180
+
181
+ if (argc > 2 || argc < 1)
182
+ rb_raise(rb_eArgError, "wrong number of arguments (need 1 or 2)");
183
+ Check_Type(argv[0], T_STRING);
184
+
185
+ Data_Get_Struct(self, rbxs_dom, prbxs_dom);
186
+
187
+ ctxt = xmlXPathNewContext(prbxs_dom->doc);
188
+ if(ctxt == NULL)
189
+ rb_raise(rb_eRuntimeError, "Couldn't create XPath context");
190
+ root = xmlDocGetRootElement(prbxs_dom->doc);
191
+ ctxt->node = root->parent;
192
+
193
+ if (argc == 2) {
194
+ Check_Type(argv[1], T_HASH);
195
+ if (!RHASH_EMPTY_P(argv[1]))
196
+ rb_hash_foreach(argv[1], nslist_each, (st_data_t)ctxt);
197
+ }
198
+ if (!RHASH_EMPTY_P(prbxs_dom->namespaces))
199
+ rb_hash_foreach(prbxs_dom->namespaces, nslist_each, (st_data_t)ctxt);
200
+
201
+ obj = xmlXPathEvalExpression((unsigned char *)StringValuePtr(argv[0]), ctxt);
202
+ ctxt->node = NULL;
203
+ if(obj == NULL) {
204
+ xmlXPathFreeContext(ctxt);
205
+ rb_raise(rb_eRuntimeError, "Error in xpath");
206
+ }
207
+ switch (obj->type) {
208
+ case XPATH_NODESET:
209
+ set = rbxs_domnodeset_new(cSmartDomNodeSet,self,obj);
210
+ break;
211
+ case XPATH_BOOLEAN:
212
+ set = obj->boolval > 0 ? Qtrue : Qfalse;
213
+ xmlXPathFreeObject(obj);
214
+ break;
215
+ case XPATH_NUMBER:
216
+ set = rb_float_new(obj->floatval);
217
+ xmlXPathFreeObject(obj);
218
+ break;
219
+ case XPATH_STRING:
220
+ set = rb_str_new2((char *)obj->stringval);
221
+ xmlXPathFreeObject(obj);
222
+ break;
223
+ default:
224
+ set = Qnil;
225
+ }
226
+ xmlXPathFreeContext(ctxt);
227
+
228
+ return set;
229
+ }
230
+
231
+ /*
232
+ * Documentation
233
+ */
234
+ VALUE rbxs_dom_change_handler_set(VALUE self)
235
+ {
236
+ rbxs_dom *prbxs_dom;
237
+
238
+ Data_Get_Struct(self, rbxs_dom, prbxs_dom);
239
+ if (!rb_block_given_p())
240
+ rb_raise(rb_eArgError, "you need to supply a block with #on_change");
241
+
242
+ rb_ary_push(prbxs_dom->changeHandlers,rb_block_proc());
243
+ return(Qtrue);
244
+ }
245
+
246
+
247
+ /*
248
+ * Documentation
249
+ */
250
+ VALUE rbxs_dom_change_handlers(VALUE self)
251
+ {
252
+ rbxs_dom *prbxs_dom;
253
+ Data_Get_Struct(self, rbxs_dom, prbxs_dom);
254
+ return(prbxs_dom->changeHandlers);
255
+ }
256
+
257
+ /*
258
+ * Documentation
259
+ */
260
+ VALUE rbxs_dom_namespaces_get(VALUE self)
261
+ {
262
+ rbxs_dom *prbxs_dom;
263
+ Data_Get_Struct(self, rbxs_dom, prbxs_dom);
264
+ rb_ary_push(prbxs_dom->changeHandlers,rb_block_proc());
265
+ return(prbxs_dom->namespaces);
266
+ }
267
+ /*
268
+ * Documentation
269
+ */
270
+ VALUE rbxs_dom_namespaces_set(VALUE self, VALUE ns)
271
+ {
272
+ rbxs_dom *prbxs_dom;
273
+ Data_Get_Struct(self, rbxs_dom, prbxs_dom);
274
+ Check_Type(ns, T_HASH);
275
+ if (!RHASH_EMPTY_P(ns))
276
+ rb_hash_foreach(ns, nslistset_each, Qnil);
277
+ prbxs_dom->namespaces = ns;
278
+ return(Qnil);
279
+ }
280
+
281
+ void rbxs_dom_change_handlers_execute(rbxs_dom *prbxs_dom, unsigned short int type, VALUE node) {
282
+ long i;
283
+ for (i = 0; i < RARRAY_LEN(prbxs_dom->changeHandlers); i++) {
284
+ VALUE args = rb_ary_new2(2);
285
+
286
+ VALUE e = RARRAY_PTR(prbxs_dom->changeHandlers)[i];
287
+ rb_ary_push(args,INT2FIX(type));
288
+ rb_ary_push(args,node);
289
+ rb_eval_cmd(e,args,1);
290
+ }
291
+ }
292
+
293
+ //***********************************************************************************
294
+ // Constructors
295
+ //***********************************************************************************
296
+ VALUE rbxs_dom_string(VALUE string) {
297
+ rbxs_dom *prbxs_dom;
298
+ xmlParserCtxtPtr ctxt;
299
+
300
+ Check_Type(string, T_STRING);
301
+
302
+ prbxs_dom = (rbxs_dom *)malloc(sizeof(rbxs_dom));
303
+ if (prbxs_dom == NULL)
304
+ rb_raise(rb_eNoMemError, "No memory left for XML::Smart::Dom struct");
305
+
306
+ xmlInitParser();
307
+
308
+ ctxt = xmlCreateMemoryParserCtxt(StringValuePtr(string),strlen(StringValuePtr(string)));
309
+ if (ctxt == NULL)
310
+ rb_sys_fail(StringValuePtr(string));
311
+
312
+ if (xmlParseDocument(ctxt) == -1) {
313
+ xmlFreeDoc(ctxt->myDoc);
314
+ xmlFreeParserCtxt(ctxt);
315
+ rb_raise(rb_eRuntimeError, "Document didn't parse");
316
+ }
317
+
318
+ if (!ctxt->wellFormed) {
319
+ xmlFreeDoc(ctxt->myDoc);
320
+ xmlFreeParserCtxt(ctxt);
321
+ ctxt = NULL;
322
+ rb_raise(rb_eRuntimeError, "Document is not wellformed");
323
+ }
324
+
325
+ prbxs_dom->type = RBXS_DOM_TYPE_STRING;
326
+ prbxs_dom->lock = 0;
327
+ prbxs_dom->changeHandlers = rb_ary_new2(0);
328
+ prbxs_dom->namespaces = rb_hash_new();
329
+ prbxs_dom->encodeEntities = 1;
330
+ prbxs_dom->doc = ctxt->myDoc;
331
+
332
+ xmlFreeParserCtxt(ctxt);
333
+
334
+ return(Data_Wrap_Struct(cSmartDom, rbxs_dom_mark, rbxs_dom_free, prbxs_dom));
335
+ }
336
+
337
+ VALUE rbxs_dom_open(VALUE name, char *root, unsigned short int lock, unsigned short int save) {
338
+ rbxs_dom *prbxs_dom;
339
+ xmlParserCtxtPtr ctxt;
340
+ char *lockfile;
341
+
342
+ ctxt = NULL;
343
+ lockfile = NULL;
344
+
345
+ if ((!rb_block_given_p()) && save>0)
346
+ rb_raise(rb_eArgError, "you need to supply a block with #modify");
347
+
348
+ prbxs_dom = (rbxs_dom *)malloc(sizeof(rbxs_dom));
349
+ if (prbxs_dom == NULL)
350
+ rb_raise(rb_eNoMemError, "No memory left for XML::Smart::Dom struct");
351
+
352
+ if (root != NULL) {
353
+ int fd;
354
+ fd = open(StringValuePtr(name), O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR);
355
+ if (fd < 0) {
356
+ if (errno != EEXIST)
357
+ rb_raise(rb_eRuntimeError, "Failed to create new file");
358
+ } else {
359
+ char *wr;
360
+ wr = (char *)calloc(strlen("<?xml version='1.0'?>\n") + strlen(root) + 1,sizeof(char));
361
+ strncat(wr,"<?xml version='1.0'?>\n",strlen("<?xml version='1.0'?>\n"));
362
+ strncat(wr,root,strlen(root));
363
+ if (!(write(fd,wr,strlen(wr)) > 0))
364
+ rb_raise(rb_eRuntimeError, "Failed to write new file");
365
+ free(wr);
366
+ }
367
+ close(fd);
368
+ }
369
+
370
+ if (save > 0 && lock > 0) {
371
+ struct stat buffer;
372
+ lockfile = (char *)calloc(strlen(StringValuePtr(name)) + 6,sizeof(char));
373
+ strncat(lockfile,StringValuePtr(name),strlen(StringValuePtr(name)));
374
+ strncat(lockfile,".lock",5);
375
+ int fd;
376
+ do {
377
+ fd = open(lockfile, O_CREAT|O_EXCL, S_IRUSR|S_IWUSR);
378
+ if (fd < 0) {
379
+ if (errno != EEXIST) {
380
+ xmlFreeDoc(ctxt->myDoc);
381
+ ctxt = NULL;
382
+ free(lockfile);
383
+ rb_raise(rb_eRuntimeError, "Failed to create lockfile");
384
+ } else {
385
+ stat(lockfile, &buffer);
386
+ if (buffer.st_mtime < time(NULL) - lock)
387
+ unlink(lockfile);
388
+ }
389
+ }
390
+ rb_thread_polling();
391
+ } while (fd < 0);
392
+ close(fd);
393
+ }
394
+
395
+ xmlInitParser();
396
+ ctxt = xmlCreateFileParserCtxt(StringValuePtr(name));
397
+
398
+ prbxs_dom->type = RBXS_DOM_TYPE_FILE;
399
+ prbxs_dom->encodeEntities = 1;
400
+ prbxs_dom->changeHandlers = rb_ary_new2(0);
401
+ prbxs_dom->namespaces = rb_hash_new();
402
+ prbxs_dom->lock = lock;
403
+
404
+ if (ctxt == NULL) {
405
+ if (save>0 && prbxs_dom->lock>0) {
406
+ unlink(lockfile);
407
+ free(lockfile);
408
+ }
409
+ rb_sys_fail(StringValuePtr(name));
410
+ }
411
+
412
+ if (xmlParseDocument(ctxt) == -1) {
413
+ if (save>0 && prbxs_dom->lock>0) {
414
+ unlink(lockfile);
415
+ free(lockfile);
416
+ }
417
+ xmlFreeDoc(ctxt->myDoc);
418
+ xmlFreeParserCtxt(ctxt);
419
+ rb_raise(rb_eRuntimeError, "Document didn't parse");
420
+ }
421
+
422
+ if (!ctxt->wellFormed) {
423
+ if (save>0 && prbxs_dom->lock>0) {
424
+ unlink(lockfile);
425
+ free(lockfile);
426
+ }
427
+ xmlFreeDoc(ctxt->myDoc);
428
+ xmlFreeParserCtxt(ctxt);
429
+ ctxt = NULL;
430
+ rb_raise(rb_eRuntimeError, "Document is not wellformed");
431
+ }
432
+
433
+ prbxs_dom->doc = ctxt->myDoc;
434
+ xmlFreeParserCtxt(ctxt);
435
+ xmlCleanupParser(); // Hmmm, no problem to call it as this point
436
+
437
+ if (rb_block_given_p()) {
438
+ rb_yield(Data_Wrap_Struct(cSmartDom, rbxs_dom_mark, rbxs_dom_free, prbxs_dom));
439
+ if (save > 0) {
440
+ int status = -1;
441
+ status = xmlSaveFormatFile(StringValuePtr(name), prbxs_dom->doc, 1);
442
+ if (prbxs_dom->lock > 0) {
443
+ unlink(lockfile);
444
+ free(lockfile);
445
+ }
446
+ if (status == -1)
447
+ rb_raise(rb_eRuntimeError, "Unable to write file back to disk");
448
+ }
449
+ return(Qnil);
450
+ }
451
+
452
+ return(Data_Wrap_Struct(cSmartDom, rbxs_dom_mark, rbxs_dom_free, prbxs_dom));
453
+ }
454
+
455
+ //***********************************************************************************
456
+ // Initialize module and class
457
+ //***********************************************************************************
458
+ #ifdef RDOC__
459
+ mXML = rb_define_module( "XML" );
460
+ cSmart = rb_define_class_under( mXML, "Smart", rb_cObject );
461
+ #endif
462
+ VALUE cSmartDom;
463
+
464
+ void init_rbxs_dom( void ) {
465
+ cSmartDom = rb_define_class_under( cSmart, "Dom", rb_cObject );
466
+
467
+ rb_define_const(cSmartDom, "SIGNAL_ADD", INT2NUM(RBXS_DOM_SIGNAL_ADD ));
468
+ rb_define_const(cSmartDom, "SIGNAL_CHANGE", INT2NUM(RBXS_DOM_SIGNAL_CHANGE));
469
+ rb_define_const(cSmartDom, "SIGNAL_DELETE", INT2NUM(RBXS_DOM_SIGNAL_DELETE));
470
+
471
+ rb_define_method(cSmartDom, "inspect", rbxs_dom_inspect, 0);
472
+ rb_define_method(cSmartDom, "to_s", rbxs_dom_to_s, 0);
473
+ rb_define_method(cSmartDom, "root", rbxs_dom_root, 0);
474
+ rb_define_method(cSmartDom, "root=", rbxs_dom_root_set, 1);
475
+ rb_define_method(cSmartDom, "find", rbxs_dom_find, -1);
476
+ rb_define_method(cSmartDom, "on_change", rbxs_dom_change_handler_set, 0);
477
+ rb_define_method(cSmartDom, "change_handlers", rbxs_dom_change_handlers, 0);
478
+ rb_define_method(cSmartDom, "save_as", rbxs_dom_save_as, 1);
479
+ rb_define_method(cSmartDom, "namespaces=", rbxs_dom_namespaces_set, 1);
480
+ rb_define_method(cSmartDom, "namespaces", rbxs_dom_namespaces_get, 0);
481
+ rb_define_method(cSmartDom, "encode_entities=", rbxs_dom_encode_entities_set, 1);
482
+ rb_define_method(cSmartDom, "encode_entities?", rbxs_dom_encode_entities_q, 0);
483
+ }
data/rbxs_dom.h ADDED
@@ -0,0 +1,32 @@
1
+ /* Please see the COPYING file for copyright and distribution information */
2
+
3
+ #ifndef __RBXS_DOM_H__
4
+ #define __RBXS_DOM_H__
5
+
6
+ #include "rbxs.h"
7
+
8
+ #define RBXS_DOM_TYPE_STRING 0
9
+ #define RBXS_DOM_TYPE_FILE 1
10
+
11
+ #define RBXS_DOM_SIGNAL_ADD 0
12
+ #define RBXS_DOM_SIGNAL_CHANGE 1
13
+ #define RBXS_DOM_SIGNAL_DELETE 2
14
+
15
+ RUBY_EXTERN VALUE cSmartDom;
16
+
17
+ typedef struct rbxs_dom {
18
+ unsigned short int encodeEntities;
19
+ int type;
20
+ unsigned short int lock;
21
+ xmlDocPtr doc;
22
+ VALUE changeHandlers;
23
+ VALUE namespaces;
24
+ } rbxs_dom;
25
+
26
+ void rbxs_dom_change_handlers_execute(rbxs_dom *prbxs_dom, unsigned short int type, VALUE node);
27
+
28
+ RUBY_EXTERN VALUE rbxs_dom_open(VALUE name, char *root, unsigned short int lock, unsigned short int save);
29
+ RUBY_EXTERN VALUE rbxs_dom_string(VALUE string);
30
+ RUBY_EXTERN void init_rbxs_dom(void);
31
+
32
+ #endif
@@ -0,0 +1,189 @@
1
+ #include "rbxs_domattribute.h"
2
+ #include "rbxs_domelement.h"
3
+ #include "rbxs_dom.h"
4
+
5
+ /* -- */
6
+ //***********************************************************************************
7
+ // GC
8
+ //***********************************************************************************
9
+ void rbxs_domattribute_free(rbxs_domattribute *prbxs_domattribute) {
10
+ if (prbxs_domattribute != NULL) {
11
+ free(prbxs_domattribute);
12
+ }
13
+ }
14
+
15
+ void rbxs_domattribute_mark(rbxs_domattribute *prbxs_domattribute) {
16
+ if (prbxs_domattribute == NULL) return;
17
+ if (!NIL_P(prbxs_domattribute->doc)) rb_gc_mark(prbxs_domattribute->doc);
18
+ }
19
+
20
+ //***********************************************************************************
21
+ // Methods
22
+ //***********************************************************************************
23
+ /* ++ */
24
+
25
+ /*
26
+ * Documentation
27
+ */
28
+ VALUE rbxs_domattribute_inspect(VALUE self)
29
+ {
30
+ rbxs_domattribute *prbxs_domattribute;
31
+ xmlBufferPtr ret;
32
+ VALUE *argv;
33
+
34
+ argv = ALLOCA_N(VALUE, 4);
35
+ argv[0] = rb_str_new2("#<%s:0x%x @%s>");
36
+ argv[1] = CLASS_OF(self);
37
+ argv[2] = rb_obj_id(self);
38
+
39
+ Data_Get_Struct(self, rbxs_domattribute, prbxs_domattribute);
40
+ ret = xmlBufferCreate();
41
+ xmlNodeDump(ret, prbxs_domattribute->attribute->doc, (xmlNodePtr)prbxs_domattribute->attribute, 0, 1);
42
+ argv[3] = rb_str_new2((char *)ret->content);
43
+ argv[3] = rb_str_substr(argv[3],1,RSTRING_LEN(argv[3]));
44
+
45
+ xmlBufferFree(ret);
46
+ return(rb_f_sprintf(4, argv));
47
+ }
48
+
49
+ /*
50
+ * Documentation
51
+ */
52
+ VALUE rbxs_domattribute_value_get(VALUE self)
53
+ {
54
+ rbxs_domattribute *prbxs_domattribute;
55
+ xmlChar *ret;
56
+ VALUE val;
57
+
58
+ Data_Get_Struct(self, rbxs_domattribute, prbxs_domattribute);
59
+ ret = xmlGetProp(prbxs_domattribute->attribute->parent,prbxs_domattribute->attribute->name);
60
+ val = rb_str_new2((char *)ret);
61
+ xmlFree(ret);
62
+ return(val);
63
+ }
64
+
65
+ /*
66
+ * Documentation
67
+ */
68
+ VALUE rbxs_domattribute_path(VALUE self)
69
+ {
70
+ rbxs_domattribute *prbxs_domattribute;
71
+ xmlChar *ret;
72
+ VALUE val;
73
+
74
+ Data_Get_Struct(self, rbxs_domattribute, prbxs_domattribute);
75
+ ret = xmlGetNodePath((xmlNodePtr)prbxs_domattribute->attribute);
76
+ val = rb_str_new2((char *)ret);
77
+ xmlFree(ret);
78
+ return(val);
79
+ }
80
+
81
+ /*
82
+ * Documentation
83
+ */
84
+ VALUE rbxs_domattribute_to_i(int argc, VALUE *argv, VALUE self)
85
+ {
86
+ VALUE b;
87
+ int base;
88
+
89
+ rb_scan_args(argc, argv, "01", &b);
90
+ if (argc == 0) base = 10;
91
+ else base = NUM2INT(b);
92
+
93
+ if (base < 0)
94
+ rb_raise(rb_eArgError, "illegal radix %d", base);
95
+ return(rb_str_to_inum(rbxs_domattribute_value_get(self),base,Qfalse));
96
+ }
97
+
98
+ /*
99
+ * Documentation
100
+ */
101
+ VALUE rbxs_domattribute_to_f(VALUE self)
102
+ {
103
+ return rb_float_new(rb_str_to_dbl(rbxs_domattribute_value_get(self), Qfalse));
104
+ }
105
+
106
+ /*
107
+ * Documentation
108
+ */
109
+ VALUE rbxs_domattribute_name_get(VALUE self)
110
+ {
111
+ rbxs_domattribute *prbxs_domattribute;
112
+ Data_Get_Struct(self, rbxs_domattribute, prbxs_domattribute);
113
+ return(rb_str_new2((char *)prbxs_domattribute->attribute->name));
114
+ }
115
+
116
+ /*
117
+ * Documentation
118
+ */
119
+ VALUE rbxs_domattribute_value_set(VALUE self, VALUE value)
120
+ {
121
+ rbxs_domattribute *prbxs_domattribute;
122
+ rbxs_dom *prbxs_dom;
123
+ unsigned char *tc;
124
+ VALUE str;
125
+
126
+ Data_Get_Struct(self, rbxs_domattribute, prbxs_domattribute);
127
+ Data_Get_Struct(prbxs_domattribute->doc, rbxs_dom, prbxs_dom);
128
+
129
+ str = rb_obj_as_string(value);
130
+ if (NIL_P(str) || TYPE(str) != T_STRING)
131
+ rb_raise(rb_eTypeError, "cannot convert obj to string");
132
+ tc = (unsigned char *)StringValuePtr(str);
133
+ if (!xmlCheckUTF8(tc))
134
+ rb_raise(rb_eArgError, "text must be utf8 encoded");
135
+ xmlNodeSetContent((xmlNodePtr)prbxs_domattribute->attribute,tc);
136
+
137
+ rbxs_dom_change_handlers_execute(prbxs_dom,RBXS_DOM_SIGNAL_CHANGE,self);
138
+ return(value);
139
+ }
140
+
141
+ /*
142
+ * Documentation
143
+ */
144
+ VALUE rbxs_domattribute_element(VALUE self)
145
+ {
146
+ rbxs_domattribute *prbxs_domattribute;
147
+ Data_Get_Struct(self, rbxs_domattribute, prbxs_domattribute);
148
+ return(rbxs_domelement_new(cSmartDomElement,prbxs_domattribute->doc,prbxs_domattribute->attribute->parent));
149
+ }
150
+
151
+ //***********************************************************************************
152
+ // Constructors
153
+ //***********************************************************************************
154
+ VALUE rbxs_domattribute_new(VALUE class, VALUE doc, xmlAttrPtr attribute) {
155
+ rbxs_domattribute *prbxs_domattribute;
156
+
157
+ prbxs_domattribute = (rbxs_domattribute *)malloc(sizeof(rbxs_domattribute));
158
+ if (prbxs_domattribute == NULL )
159
+ rb_raise(rb_eNoMemError, "No memory left for XML::Smart::Dom::Attribute struct");
160
+
161
+ prbxs_domattribute->doc = doc;
162
+ prbxs_domattribute->attribute = attribute;
163
+
164
+ return(Data_Wrap_Struct(class, rbxs_domattribute_mark, rbxs_domattribute_free, prbxs_domattribute));
165
+ }
166
+
167
+ //***********************************************************************************
168
+ // Initialize class Node
169
+ //***********************************************************************************
170
+ #ifdef RDOC__
171
+ mXML = rb_define_module( "XML" );
172
+ cSmart = rb_define_class_under( mXML, "Smart", rb_cObject );
173
+ cSmartDom = rb_define_class_under( cSmart, "Dom", rb_cObject );
174
+ #endif
175
+ VALUE cSmartDomAttribute;
176
+
177
+ void init_rbxs_domattribute(void) {
178
+ cSmartDomAttribute = rb_define_class_under( cSmartDom, "Attribute", rb_cObject );
179
+
180
+ rb_define_method(cSmartDomAttribute, "inspect", rbxs_domattribute_inspect, 0);
181
+ rb_define_method(cSmartDomAttribute, "to_s", rbxs_domattribute_value_get, 0);
182
+ rb_define_method(cSmartDomAttribute, "to_i", rbxs_domattribute_to_i, -1);
183
+ rb_define_method(cSmartDomAttribute, "to_f", rbxs_domattribute_to_f, 0);
184
+ rb_define_method(cSmartDomAttribute, "name", rbxs_domattribute_name_get, 0);
185
+ rb_define_method(cSmartDomAttribute, "path", rbxs_domattribute_path, 0);
186
+ rb_define_method(cSmartDomAttribute, "value", rbxs_domattribute_value_get, 0);
187
+ rb_define_method(cSmartDomAttribute, "value=", rbxs_domattribute_value_set, 1);
188
+ rb_define_method(cSmartDomAttribute, "element", rbxs_domattribute_element, 0);
189
+ }