ox 1.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ox might be problematic. Click here for more details.

Files changed (52) hide show
  1. data/LICENSE +27 -0
  2. data/README +153 -0
  3. data/ext/ox/base64.c +123 -0
  4. data/ext/ox/base64.h +44 -0
  5. data/ext/ox/cache.c +148 -0
  6. data/ext/ox/cache.h +43 -0
  7. data/ext/ox/cache8.c +80 -0
  8. data/ext/ox/cache8.h +43 -0
  9. data/ext/ox/cache8_test.c +69 -0
  10. data/ext/ox/cache_test.c +69 -0
  11. data/ext/ox/dump.c +901 -0
  12. data/ext/ox/extconf.rb +7 -0
  13. data/ext/ox/gen_load.c +196 -0
  14. data/ext/ox/obj_load.c +802 -0
  15. data/ext/ox/ox.c +456 -0
  16. data/ext/ox/ox.h +190 -0
  17. data/ext/ox/parse.c +629 -0
  18. data/lib/ox.rb +97 -0
  19. data/lib/ox/cdata.rb +12 -0
  20. data/lib/ox/comment.rb +13 -0
  21. data/lib/ox/doctype.rb +13 -0
  22. data/lib/ox/document.rb +20 -0
  23. data/lib/ox/element.rb +67 -0
  24. data/lib/ox/node.rb +24 -0
  25. data/test/Sample.graffle +2318 -0
  26. data/test/cache16_test.rb +17 -0
  27. data/test/cache8_test.rb +17 -0
  28. data/test/cache_test.rb +17 -0
  29. data/test/files.rb +34 -0
  30. data/test/func.rb +228 -0
  31. data/test/gen_sample.rb +22 -0
  32. data/test/obj_sample.rb +19 -0
  33. data/test/ox/change.rb +16 -0
  34. data/test/ox/dir.rb +21 -0
  35. data/test/ox/doc.rb +39 -0
  36. data/test/ox/file.rb +33 -0
  37. data/test/ox/group.rb +18 -0
  38. data/test/ox/hasprops.rb +18 -0
  39. data/test/ox/layer.rb +14 -0
  40. data/test/ox/line.rb +22 -0
  41. data/test/ox/oval.rb +12 -0
  42. data/test/ox/rect.rb +12 -0
  43. data/test/ox/shape.rb +37 -0
  44. data/test/ox/text.rb +23 -0
  45. data/test/perf_gen.rb +193 -0
  46. data/test/perf_mars.rb +97 -0
  47. data/test/perf_obj.rb +201 -0
  48. data/test/perf_pod.rb +88 -0
  49. data/test/perf_write.rb +80 -0
  50. data/test/sample.rb +62 -0
  51. data/test/test.rb +70 -0
  52. metadata +106 -0
data/LICENSE ADDED
@@ -0,0 +1,27 @@
1
+ Copyright (c) 2011, Peter Ohler
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ - Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+
10
+ - Redistributions in binary form must reproduce the above copyright notice,
11
+ this list of conditions and the following disclaimer in the documentation
12
+ and/or other materials provided with the distribution.
13
+
14
+ - Neither the name of Peter Ohler nor the names of its contributors may be
15
+ used to endorse or promote products derived from this software without
16
+ specific prior written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README ADDED
@@ -0,0 +1,153 @@
1
+ = Ox: A fast XML parser and Object marshaller.
2
+
3
+ *GitHub* *repo*: https://github.com/ohler55/ox
4
+
5
+ === Description:
6
+
7
+ Optimized XML (Ox), as the name implies was written to provide speed optimized
8
+ XML handling. It was designed to be an alternative to Nokogiri in generic XML
9
+ parsing and as an alternative to Marshal for Object serialization.
10
+
11
+ Nokogiri relies on libXml while Ox is self contained. Ox uses nothing other
12
+ than standard C libraries so version issues with libXml are not an issue.
13
+
14
+ Marshal uses a binary format for serializing Objects. That binary format
15
+ changes with releases making Marshal dumped Object incompatible between some
16
+ versions. The use of a binary format make debugging message streams or file
17
+ contents next to impossible unless the same version of Ruby and only Ruby is
18
+ used for inspecting the serialize Object. Ox on the other hand uses human
19
+ readable XML.
20
+
21
+ It is possible to write an XML serialization gem with Nokogiri but writing
22
+ such a package in Ruby results in a module significantly slower than
23
+ Marshal. This is what triggered the start of Ox development.
24
+
25
+ Ox handles XML documents in two ways. It is a generic XML parser and writer as
26
+ well as a fast Object / XML marshaller. Ox was written for speed as a
27
+ replacement for Nokogiri and for Marshal.
28
+
29
+ As an XML parser it is 2 or more times faster than Nokogiri and as a generic
30
+ XML writer it is as much as 20 times faster than Nokogiri. Of course different
31
+ files may result in slightly different times.
32
+
33
+ As an Object serializer Ox is up to 6 times faster than the standard Ruby
34
+ Marshal.dump() and up to 3 times faster than Marshal.load().
35
+
36
+
37
+ === Object Dump Sample:
38
+
39
+ require 'ox'
40
+
41
+ class Sample
42
+ attr_accessor :a, :b, :c
43
+
44
+ def initialize(a, b, c)
45
+ @a = a
46
+ @b = b
47
+ @c = c
48
+ end
49
+ end
50
+
51
+ # Create Object
52
+ obj = Sample.new(1, "bee", ['x', :y, 7.0])
53
+ # Now dump the Object to an XML String.
54
+ xml = Ox.dump(obj)
55
+ # Convert the object back into a Sample Object.
56
+ obj2 = Ox.parse_obj(xml)
57
+
58
+ === Generic XML Writing and Parsing:
59
+
60
+ require 'ox'
61
+
62
+ doc = Ox::Document.new(:version => '1.0')
63
+
64
+ top = Ox::Element.new('top')
65
+ top[:name] = 'sample'
66
+ doc << top
67
+
68
+ mid = Ox::Element.new('middle')
69
+ mid[:name] = 'second'
70
+ top << mid
71
+
72
+ bot = Ox::Element.new('bottom')
73
+ bot[:name] = 'third'
74
+ mid << bot
75
+
76
+ xml = Ox.dump(doc)
77
+ puts xml
78
+ doc2 = Ox.parse(xml)
79
+ puts "Same? #{doc == doc2}"
80
+
81
+
82
+ === Object XML format
83
+
84
+ The XML format used for Object encoding follows the structure of the
85
+ Object. Each XML element is encoded so that the XML element name is a type
86
+ indicator. Attributes of the element provide additional information such as
87
+ the Class if relevant, the Object attribute name, and Object ID if
88
+ necessary.
89
+
90
+ The type indicator map is:
91
+
92
+ - +a+ => Array
93
+ - +b+ => Base64
94
+ - +c+ => Class
95
+ - +f+ => Float
96
+ - +g+ => Regexp
97
+ - +h+ => Hash
98
+ - +i+ => Fixnum
99
+ - +j+ => Bignum
100
+ - +l+ => Rational
101
+ - +m+ => Symbol
102
+ - +n+ => FalseClass
103
+ - +o+ => Object
104
+ - +p+ => Ref
105
+ - +r+ => Range
106
+ - +s+ => String
107
+ - +t+ => Time
108
+ - +u+ => Struct
109
+ - +v+ => Complex
110
+ - +x+ => Raw
111
+ - +y+ => TrueClass
112
+ - +z+ => NilClass
113
+
114
+ If the type is an Object, type 'o' then an attribute named 'c' should be set
115
+ with the full Class name including the Module names. If the XML element
116
+ represents an Object then a sub-elements is included for each attribute of
117
+ the Object. An XML element attribute 'a' is set with a value that is the
118
+ name of the Ruby Object attribute. In all cases, except for the Exception
119
+ attribute hack the attribute names begin with an @ character. (Exception are
120
+ strange in that the attributes of the Exception Class are not named with a @
121
+ suffix. A hack since it has to be done in C and can not be done through the
122
+ interpreter.)
123
+
124
+ Values are encoded as the text portion of an element or in the sub-elements
125
+ of the principle. For example, a Fixnum is encoded as:
126
+
127
+ <i>123</i>
128
+
129
+ An Array has sub-elements and is encoded similar to this example.
130
+
131
+ <a>
132
+ <i>1</i>
133
+ <s>abc</s>
134
+ </a>
135
+
136
+ A Hash is encoded with an even number of elements where the first element is
137
+ the key and the second is the value. This is repeated for each entry in the
138
+ Hash. An example is of { 1 => 'one', 2 => 'two' } encoding is:
139
+
140
+ <h>
141
+ <i>1</i>
142
+ <s>one</s>
143
+ <i>2</i>
144
+ <s>two</s>
145
+ </h>
146
+
147
+ Strings with characters not allowed in XML are base64 encoded amd will be
148
+ converted back into a String when loaded.
149
+
150
+ Ox supports circular references where attributes of one Object can refer to
151
+ an Object that refers back to the first Object. When this option is used an
152
+ Object ID is added to each XML Object element as the value of the 'a'
153
+ attribute.
data/ext/ox/base64.c ADDED
@@ -0,0 +1,123 @@
1
+ /* base64.c
2
+ * Copyright (c) 2011, Peter Ohler
3
+ * All rights reserved.
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * - Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * - Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * - Neither the name of Peter Ohler nor the names of its contributors may be
16
+ * used to endorse or promote products derived from this software without
17
+ * specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ */
30
+
31
+ #include <stdlib.h>
32
+
33
+ #include "base64.h"
34
+
35
+ static char digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
36
+
37
+ // invalid or terminating characters are set to 'X' or \x58
38
+ static u_char s_digits[256] = "\
39
+ \x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\
40
+ \x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\
41
+ \x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x3E\x58\x58\x58\x3F\
42
+ \x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x58\x58\x58\x58\x58\x58\
43
+ \x58\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\
44
+ \x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x58\x58\x58\x58\x58\
45
+ \x58\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\
46
+ \x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x58\x58\x58\x58\x58\
47
+ \x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\
48
+ \x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\
49
+ \x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\
50
+ \x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\
51
+ \x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\
52
+ \x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\
53
+ \x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\
54
+ \x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58\x58";
55
+
56
+ void
57
+ to_base64(const u_char *src, int len, char *b64) {
58
+ const u_char *end3;
59
+ int len3 = len % 3;
60
+ u_char b1, b2, b3;
61
+
62
+ end3 = src + (len - len3);
63
+ while (src < end3) {
64
+ b1 = *src++;
65
+ b2 = *src++;
66
+ b3 = *src++;
67
+ *b64++ = digits[b1 >> 2];
68
+ *b64++ = digits[((b1 & 0x03) << 4) | (b2 >> 4)];
69
+ *b64++ = digits[((b2 & 0x0F) << 2) | (b3 >> 6)];
70
+ *b64++ = digits[b3 & 0x3F];
71
+ }
72
+ if (1 == len3) {
73
+ b1 = *src++;
74
+ *b64++ = digits[b1 >> 2];
75
+ *b64++ = digits[(b1 & 0x03) << 4];
76
+ *b64++ = '=';
77
+ *b64++ = '=';
78
+ } else if (2 == len3) {
79
+ b1 = *src++;
80
+ b2 = *src++;
81
+ *b64++ = digits[b1 >> 2];
82
+ *b64++ = digits[((b1 & 0x03) << 4) | (b2 >> 4)];
83
+ *b64++ = digits[(b2 & 0x0F) << 2];
84
+ *b64++ = '=';
85
+ }
86
+ *b64 = '\0';
87
+ }
88
+
89
+ unsigned long
90
+ b64_orig_size(const char *text) {
91
+ const char *start = text;
92
+ unsigned long size = 0;
93
+
94
+ if ('\0' != *text) {
95
+ for (; 0 != *text; text++) { }
96
+ size = (text - start) * 3 / 4;
97
+ text--;
98
+ if ('=' == *text) {
99
+ size--;
100
+ text--;
101
+ if ('=' == *text) {
102
+ size--;
103
+ }
104
+ }
105
+ }
106
+ return size;
107
+ }
108
+
109
+ void
110
+ from_base64(const char *b64, u_char *str) {
111
+ u_char b0, b1, b2, b3;
112
+
113
+ while (1) {
114
+ if ('X' == (b0 = s_digits[(u_char)*b64++])) { break; }
115
+ if ('X' == (b1 = s_digits[(u_char)*b64++])) { break; }
116
+ *str++ = (b0 << 2) | ((b1 >> 4) & 0x03);
117
+ if ('X' == (b2 = s_digits[(u_char)*b64++])) { break; }
118
+ *str++ = (b1 << 4) | ((b2 >> 2) & 0x0F);
119
+ if ('X' == (b3 = s_digits[(u_char)*b64++])) { break; }
120
+ *str++ = (b2 << 6) | b3;
121
+ }
122
+ *str = '\0';
123
+ }
data/ext/ox/base64.h ADDED
@@ -0,0 +1,44 @@
1
+ /* base64.h
2
+ * Copyright (c) 2011, Peter Ohler
3
+ * All rights reserved.
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * - Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * - Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * - Neither the name of Peter Ohler nor the names of its contributors may be
16
+ * used to endorse or promote products derived from this software without
17
+ * specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ */
30
+
31
+ #ifndef __BASE64_H__
32
+ #define __BASE64_H__
33
+
34
+ #include <sys/types.h>
35
+
36
+
37
+ #define b64_size(len) ((len + 2) / 3 * 4)
38
+
39
+ extern unsigned long b64_orig_size(const char *text);
40
+
41
+ extern void to_base64(const u_char *src, int len, char *b64);
42
+ extern void from_base64(const char *b64, u_char *str);
43
+
44
+ #endif /* __BASE64_H__ */
data/ext/ox/cache.c ADDED
@@ -0,0 +1,148 @@
1
+ /* cache.c
2
+ * Copyright (c) 2011, Peter Ohler
3
+ * All rights reserved.
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * - Redistributions of source code must retain the above copyright notice, this
9
+ * list of conditions and the following disclaimer.
10
+ *
11
+ * - Redistributions in binary form must reproduce the above copyright notice,
12
+ * this list of conditions and the following disclaimer in the documentation
13
+ * and/or other materials provided with the distribution.
14
+ *
15
+ * - Neither the name of Peter Ohler nor the names of its contributors may be
16
+ * used to endorse or promote products derived from this software without
17
+ * specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ */
30
+
31
+ #include <stdlib.h>
32
+ #include <errno.h>
33
+ #include <stdio.h>
34
+ #include <string.h>
35
+ #include <stdarg.h>
36
+
37
+ #include "cache.h"
38
+
39
+ struct _Cache {
40
+ char *key; // only set if the node has a value, and it is not an exact match
41
+ VALUE value;
42
+ struct _Cache *slots[16];
43
+ };
44
+
45
+ static void slot_print(Cache cache, unsigned int depth);
46
+
47
+ void
48
+ ox_cache_new(Cache *cache) {
49
+ if (0 == (*cache = (Cache)malloc(sizeof(struct _Cache)))) {
50
+ rb_raise(rb_eNoMemError, "not enough memory\n");
51
+ }
52
+ (*cache)->key = 0;
53
+ (*cache)->value = Qundef;
54
+ bzero((*cache)->slots, sizeof((*cache)->slots));
55
+ }
56
+
57
+ VALUE
58
+ ox_cache_get(Cache cache, const char *key, VALUE **slot) {
59
+ unsigned char *k = (unsigned char*)key;
60
+ Cache *cp;
61
+
62
+ for (; '\0' != *k; k++) {
63
+ cp = cache->slots + (unsigned int)(*k >> 4); // upper 4 bits
64
+ if (0 == *cp) {
65
+ ox_cache_new(cp);
66
+ }
67
+ cache = *cp;
68
+ cp = cache->slots + (unsigned int)(*k & 0x0F); // lower 4 bits
69
+ if (0 == *cp) {
70
+ ox_cache_new(cp);
71
+ cache = *cp;
72
+ cache->key = ('\0' == *(k + 1)) ? 0 : strdup(key);
73
+ break;
74
+ } else {
75
+ cache = *cp;
76
+ if (Qundef != cache->value && 0 != cache->key) {
77
+ unsigned char *ck = (unsigned char*)(cache->key + (unsigned int)(k - (unsigned char*)key + 1));
78
+
79
+ if (0 == strcmp((char*)ck, (char*)(k + 1))) {
80
+ break;
81
+ } else {
82
+ Cache *cp2 = cp;
83
+
84
+ // if value was set along with the key then there are no slots filled yet
85
+ cp2 = (*cp2)->slots + (*ck >> 4);
86
+ ox_cache_new(cp2);
87
+ cp2 = (*cp2)->slots + (*ck & 0x0F);
88
+ ox_cache_new(cp2);
89
+ if ('\0' == *(ck + 1)) {
90
+ free(cache->key);
91
+ } else {
92
+ (*cp2)->key = cache->key;
93
+ }
94
+ (*cp2)->value = cache->value;
95
+ cache->key = 0;
96
+ cache->value = Qundef;
97
+ }
98
+ }
99
+ }
100
+ }
101
+ *slot = &cache->value;
102
+
103
+ return cache->value;
104
+ }
105
+
106
+ void
107
+ ox_cache_print(Cache cache) {
108
+ //printf("-------------------------------------------\n");
109
+ slot_print(cache, 0);
110
+ }
111
+
112
+ static void
113
+ slot_print(Cache c, unsigned int depth) {
114
+ char indent[256];
115
+ Cache *cp;
116
+ unsigned int i;
117
+
118
+ if (sizeof(indent) - 1 < depth) {
119
+ depth = ((int)sizeof(indent) - 1);
120
+ }
121
+ memset(indent, ' ', depth);
122
+ indent[depth] = '\0';
123
+ for (i = 0, cp = c->slots; i < 16; i++, cp++) {
124
+ if (0 == *cp) {
125
+ //printf("%s%02u:\n", indent, i);
126
+ } else {
127
+ if (0 == (*cp)->key && Qundef == (*cp)->value) {
128
+ printf("%s%02u:\n", indent, i);
129
+ } else {
130
+ const char *key = (0 == (*cp)->key) ? "*" : (*cp)->key;
131
+ const char *vs;
132
+ const char *clas;
133
+
134
+ if (Qundef == (*cp)->value) {
135
+ vs = "undefined";
136
+ clas = "";
137
+ } else {
138
+ VALUE rs = rb_funcall2((*cp)->value, rb_intern("to_s"), 0, 0);
139
+
140
+ vs = StringValuePtr(rs);
141
+ clas = rb_class2name(rb_obj_class((*cp)->value));
142
+ }
143
+ printf("%s%02u: %s = %s (%s)\n", indent, i, key, vs, clas);
144
+ }
145
+ slot_print(*cp, depth + 2);
146
+ }
147
+ }
148
+ }