ruby-xml-smart 0.1.11-i486-linux

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }