ox 2.14.6 → 2.14.7

Sign up to get free protection for your applications and to get access to all the features.
data/ext/ox/ox.h CHANGED
@@ -16,9 +16,7 @@ extern "C" {
16
16
  #define RSTRING_NOT_MODIFIED
17
17
 
18
18
  #include "ruby.h"
19
- #if HAVE_RB_ENC_ASSOCIATE
20
19
  #include "ruby/encoding.h"
21
- #endif
22
20
 
23
21
  #if HAVE_RUBY_ST_H
24
22
  #include "ruby/st.h"
@@ -27,249 +25,229 @@ extern "C" {
27
25
  #include "st.h"
28
26
  #endif
29
27
 
30
- #include "cache.h"
31
-
32
- #include "err.h"
33
- #include "type.h"
34
28
  #include "attr.h"
29
+ #include "err.h"
35
30
  #include "helper.h"
31
+ #include "oxcache.h"
32
+ #include "type.h"
36
33
 
37
34
  #define raise_error(msg, xml, current) _ox_raise_error(msg, xml, current, __FILE__, __LINE__)
38
35
 
39
- #define MAX_TEXT_LEN 4096
36
+ #define MAX_TEXT_LEN 4096
40
37
 
41
- #define SILENT 0
42
- #define TRACE 1
43
- #define DEBUG 2
38
+ #define SILENT 0
39
+ #define TRACE 1
40
+ #define DEBUG 2
44
41
 
45
- #define XSD_DATE 0x0001
46
- #define WITH_XML 0x0002
47
- #define WITH_INST 0x0004
48
- #define WITH_DTD 0x0008
49
- #define CIRCULAR 0x0010
42
+ #define XSD_DATE 0x0001
43
+ #define WITH_XML 0x0002
44
+ #define WITH_INST 0x0004
45
+ #define WITH_DTD 0x0008
46
+ #define CIRCULAR 0x0010
50
47
 
51
- #define XSD_DATE_SET 0x0100
52
- #define WITH_XML_SET 0x0200
53
- #define WITH_INST_SET 0x0400
54
- #define WITH_DTD_SET 0x0800
55
- #define CIRCULAR_SET 0x1000
48
+ #define XSD_DATE_SET 0x0100
49
+ #define WITH_XML_SET 0x0200
50
+ #define WITH_INST_SET 0x0400
51
+ #define WITH_DTD_SET 0x0800
52
+ #define CIRCULAR_SET 0x1000
56
53
 
57
54
  typedef enum {
58
- UseObj = 1,
59
- UseAttr = 2,
60
- UseAttrSet = 3,
61
- UseArray = 4,
62
- UseAMember = 5,
63
- UseHash = 6,
64
- UseHashKey = 7,
65
- UseHashVal = 8,
66
- UseRange = 9,
67
- UseRangeAttr= 10,
68
- UseRaw = 11,
55
+ UseObj = 1,
56
+ UseAttr = 2,
57
+ UseAttrSet = 3,
58
+ UseArray = 4,
59
+ UseAMember = 5,
60
+ UseHash = 6,
61
+ UseHashKey = 7,
62
+ UseHashVal = 8,
63
+ UseRange = 9,
64
+ UseRangeAttr = 10,
65
+ UseRaw = 11,
69
66
  } Use;
70
67
 
71
68
  typedef enum {
72
- StrictEffort = 's',
73
- TolerantEffort = 't',
74
- AutoEffort = 'a',
75
- NoEffort = 0,
69
+ StrictEffort = 's',
70
+ TolerantEffort = 't',
71
+ AutoEffort = 'a',
72
+ NoEffort = 0,
76
73
  } Effort;
77
74
 
78
- typedef enum {
79
- Yes = 'y',
80
- No = 'n',
81
- NotSet = 0
82
- } YesNo;
75
+ typedef enum { Yes = 'y', No = 'n', NotSet = 0 } YesNo;
83
76
 
84
- typedef enum {
85
- ObjMode = 'o',
86
- GenMode = 'g',
87
- LimMode = 'l',
88
- HashMode = 'h',
89
- HashNoAttrMode = 'n',
90
- NoMode = 0
91
- } LoadMode;
77
+ typedef enum { ObjMode = 'o', GenMode = 'g', LimMode = 'l', HashMode = 'h', HashNoAttrMode = 'n', NoMode = 0 } LoadMode;
92
78
 
93
79
  typedef enum {
94
- OffSkip = 'o',
95
- NoSkip = 'n',
96
- CrSkip = 'r',
97
- SpcSkip = 's',
80
+ OffSkip = 'o',
81
+ NoSkip = 'n',
82
+ CrSkip = 'r',
83
+ SpcSkip = 's',
98
84
  } SkipMode;
99
85
 
100
- typedef struct _pInfo *PInfo;
86
+ typedef struct _pInfo *PInfo;
101
87
 
102
88
  typedef struct _parseCallbacks {
103
- void (*instruct)(PInfo pi, const char *target, Attr attrs, const char *content);
104
- void (*add_doctype)(PInfo pi, const char *docType);
105
- void (*add_comment)(PInfo pi, const char *comment);
106
- void (*add_cdata)(PInfo pi, const char *cdata, size_t len);
107
- void (*add_text)(PInfo pi, char *text, int closed);
108
- void (*add_element)(PInfo pi, const char *ename, Attr attrs, int hasChildren);
109
- void (*end_element)(PInfo pi, const char *ename);
110
- void (*finish)(PInfo pi);
111
- } *ParseCallbacks;
89
+ void (*instruct)(PInfo pi, const char *target, Attr attrs, const char *content);
90
+ void (*add_doctype)(PInfo pi, const char *docType);
91
+ void (*add_comment)(PInfo pi, const char *comment);
92
+ void (*add_cdata)(PInfo pi, const char *cdata, size_t len);
93
+ void (*add_text)(PInfo pi, char *text, int closed);
94
+ void (*add_element)(PInfo pi, const char *ename, Attr attrs, int hasChildren);
95
+ void (*end_element)(PInfo pi, const char *ename);
96
+ void (*finish)(PInfo pi);
97
+ } * ParseCallbacks;
112
98
 
113
99
  typedef struct _circArray {
114
- VALUE obj_array[1024];
115
- VALUE *objs;
116
- unsigned long size; /* allocated size or initial array size */
117
- unsigned long cnt;
118
- } *CircArray;
100
+ VALUE obj_array[1024];
101
+ VALUE *objs;
102
+ unsigned long size; /* allocated size or initial array size */
103
+ unsigned long cnt;
104
+ } * CircArray;
119
105
 
120
106
  typedef struct _options {
121
- char encoding[64]; // encoding, stored in the option to avoid GC invalidation in default values
122
- char margin[128]; // left margin for dumping
123
- int indent; // indention for dump, default 2
124
- int trace; // trace level
125
- char margin_len; // margin length
126
- char with_dtd; // YesNo
127
- char with_xml; // YesNo
128
- char with_instruct; // YesNo
129
- char circular; // YesNo
130
- char xsd_date; // YesNo
131
- char mode; // LoadMode
132
- char effort; // Effort
133
- char sym_keys; // symbolize keys
134
- char skip; // skip mode
135
- char smart; // YesNo sax smart mode
136
- char convert_special;// boolean true or false
137
- char allow_invalid; // YesNo
138
- char no_empty; // boolean - no empty elements when dumping
139
- char with_cdata; // boolean - hash_load should include cdata
140
- char inv_repl[12]; // max 10 valid characters, first character is the length
141
- char strip_ns[64]; // namespace to strip, \0 is no-strip, \* is all, else only matches
142
- struct _hints *html_hints; // html hints
143
- VALUE attr_key_mod;
144
- VALUE element_key_mod;
145
- #if HAVE_RB_ENC_ASSOCIATE
146
- rb_encoding *rb_enc;
147
- #else
148
- void *rb_enc;
149
- #endif
150
- } *Options;
107
+ char encoding[64]; // encoding, stored in the option to avoid GC invalidation in default values
108
+ char margin[128]; // left margin for dumping
109
+ int indent; // indention for dump, default 2
110
+ int trace; // trace level
111
+ char margin_len; // margin length
112
+ char with_dtd; // YesNo
113
+ char with_xml; // YesNo
114
+ char with_instruct; // YesNo
115
+ char circular; // YesNo
116
+ char xsd_date; // YesNo
117
+ char mode; // LoadMode
118
+ char effort; // Effort
119
+ char sym_keys; // symbolize keys
120
+ char skip; // skip mode
121
+ char smart; // YesNo sax smart mode
122
+ char convert_special; // boolean true or false
123
+ char allow_invalid; // YesNo
124
+ char no_empty; // boolean - no empty elements when dumping
125
+ char with_cdata; // boolean - hash_load should include cdata
126
+ char inv_repl[12]; // max 10 valid characters, first character is the length
127
+ char strip_ns[64]; // namespace to strip, \0 is no-strip, \* is all, else only matches
128
+ struct _hints *html_hints; // html hints
129
+ VALUE attr_key_mod;
130
+ VALUE element_key_mod;
131
+ rb_encoding *rb_enc;
132
+ } * Options;
151
133
 
152
134
  // parse information structure
153
135
  struct _pInfo {
154
- struct _helperStack helpers;
155
- struct _err err;
156
- char *str; // buffer being read from
157
- char *end; // end of original string
158
- char *s; // current position in buffer
159
- VALUE obj;
160
- ParseCallbacks pcb;
161
- CircArray circ_array;
162
- unsigned long id; // set for text types when cirs_array is set
163
- Options options;
164
- VALUE *marked;
165
- int mark_size; // allocated size
166
- int mark_cnt;
167
- char last; // last character read, rarely set
136
+ struct _helperStack helpers;
137
+ struct _err err;
138
+ char *str; // buffer being read from
139
+ char *end; // end of original string
140
+ char *s; // current position in buffer
141
+ VALUE obj;
142
+ ParseCallbacks pcb;
143
+ CircArray circ_array;
144
+ unsigned long id; // set for text types when cirs_array is set
145
+ Options options;
146
+ VALUE *marked;
147
+ int mark_size; // allocated size
148
+ int mark_cnt;
149
+ char last; // last character read, rarely set
168
150
  };
169
151
 
170
- extern VALUE ox_parse(char *xml, size_t len, ParseCallbacks pcb, char **endp, Options options, Err err);
171
- extern void _ox_raise_error(const char *msg, const char *xml, const char *current, const char* file, int line);
172
-
173
- extern void ox_sax_define(void);
174
-
175
- extern char* ox_write_obj_to_str(VALUE obj, Options copts);
176
- extern void ox_write_obj_to_file(VALUE obj, const char *path, Options copts);
177
-
178
- extern struct _options ox_default_options;
179
-
180
- extern VALUE Ox;
181
-
182
- extern ID ox_abort_id;
183
- extern ID ox_at_column_id;
184
- extern ID ox_at_content_id;
185
- extern ID ox_at_id;
186
- extern ID ox_at_line_id;
187
- extern ID ox_at_pos_id;
188
- extern ID ox_at_value_id;
189
- extern ID ox_attr_id;
190
- extern ID ox_attr_value_id;
191
- extern ID ox_attrs_done_id;
192
- extern ID ox_attributes_id;
193
- extern ID ox_beg_id;
194
- extern ID ox_bigdecimal_id;
195
- extern ID ox_call_id;
196
- extern ID ox_cdata_id;
197
- extern ID ox_comment_id;
198
- extern ID ox_den_id;
199
- extern ID ox_doctype_id;
200
- extern ID ox_end_element_id;
201
- extern ID ox_end_id;
202
- extern ID ox_end_instruct_id;
203
- extern ID ox_error_id;
204
- extern ID ox_excl_id;
205
- extern ID ox_external_encoding_id;
206
- extern ID ox_fileno_id;
207
- extern ID ox_force_encoding_id;
208
- extern ID ox_inspect_id;
209
- extern ID ox_instruct_id;
210
- extern ID ox_jd_id;
211
- extern ID ox_keys_id;
212
- extern ID ox_local_id;
213
- extern ID ox_mesg_id;
214
- extern ID ox_message_id;
215
- extern ID ox_new_id;
216
- extern ID ox_nodes_id;
217
- extern ID ox_num_id;
218
- extern ID ox_parse_id;
219
- extern ID ox_pos_id;
220
- extern ID ox_read_id;
221
- extern ID ox_readpartial_id;
222
- extern ID ox_start_element_id;
223
- extern ID ox_string_id;
224
- extern ID ox_text_id;
225
- extern ID ox_to_c_id;
226
- extern ID ox_to_s_id;
227
- extern ID ox_to_sym_id;
228
- extern ID ox_tv_sec_id;
229
- extern ID ox_tv_nsec_id;
230
- extern ID ox_tv_usec_id;
231
- extern ID ox_value_id;
232
-
233
- #if HAVE_RB_ENC_ASSOCIATE
234
- extern rb_encoding *ox_utf8_encoding;
235
- #else
236
- extern void *ox_utf8_encoding;
237
- #endif
238
-
239
- extern VALUE ox_empty_string;
240
- extern VALUE ox_encoding_sym;
241
- extern VALUE ox_indent_sym;
242
- extern VALUE ox_size_sym;
243
- extern VALUE ox_standalone_sym;
244
- extern VALUE ox_sym_bank; // Array
245
- extern VALUE ox_version_sym;
246
- extern VALUE ox_zero_fixnum;
247
-
248
- extern VALUE ox_bigdecimal_class;
249
- extern VALUE ox_date_class;
250
- extern VALUE ox_stringio_class;
251
- extern VALUE ox_struct_class;
252
- extern VALUE ox_time_class;
253
-
254
- extern VALUE ox_document_clas;
255
- extern VALUE ox_element_clas;
256
- extern VALUE ox_instruct_clas;
257
- extern VALUE ox_bag_clas;
258
- extern VALUE ox_comment_clas;
259
- extern VALUE ox_raw_clas;
260
- extern VALUE ox_doctype_clas;
261
- extern VALUE ox_cdata_clas;
262
-
263
- extern Cache ox_symbol_cache;
264
- extern Cache ox_class_cache;
265
- extern Cache ox_attr_cache;
266
-
267
- extern void ox_init_builder(VALUE ox);
152
+ extern VALUE ox_parse(char *xml, size_t len, ParseCallbacks pcb, char **endp, Options options, Err err);
153
+ extern void _ox_raise_error(const char *msg, const char *xml, const char *current, const char *file, int line);
154
+
155
+ extern void ox_sax_define(void);
156
+
157
+ extern char *ox_write_obj_to_str(VALUE obj, Options copts);
158
+ extern void ox_write_obj_to_file(VALUE obj, const char *path, Options copts);
159
+
160
+ extern struct _options ox_default_options;
161
+
162
+ extern VALUE Ox;
163
+
164
+ extern ID ox_abort_id;
165
+ extern ID ox_at_column_id;
166
+ extern ID ox_at_content_id;
167
+ extern ID ox_at_id;
168
+ extern ID ox_at_line_id;
169
+ extern ID ox_at_pos_id;
170
+ extern ID ox_at_value_id;
171
+ extern ID ox_attr_id;
172
+ extern ID ox_attr_value_id;
173
+ extern ID ox_attrs_done_id;
174
+ extern ID ox_attributes_id;
175
+ extern ID ox_beg_id;
176
+ extern ID ox_bigdecimal_id;
177
+ extern ID ox_call_id;
178
+ extern ID ox_cdata_id;
179
+ extern ID ox_comment_id;
180
+ extern ID ox_den_id;
181
+ extern ID ox_doctype_id;
182
+ extern ID ox_end_element_id;
183
+ extern ID ox_end_id;
184
+ extern ID ox_end_instruct_id;
185
+ extern ID ox_error_id;
186
+ extern ID ox_excl_id;
187
+ extern ID ox_external_encoding_id;
188
+ extern ID ox_fileno_id;
189
+ extern ID ox_force_encoding_id;
190
+ extern ID ox_inspect_id;
191
+ extern ID ox_instruct_id;
192
+ extern ID ox_jd_id;
193
+ extern ID ox_keys_id;
194
+ extern ID ox_local_id;
195
+ extern ID ox_mesg_id;
196
+ extern ID ox_message_id;
197
+ extern ID ox_new_id;
198
+ extern ID ox_nodes_id;
199
+ extern ID ox_num_id;
200
+ extern ID ox_parse_id;
201
+ extern ID ox_pos_id;
202
+ extern ID ox_read_id;
203
+ extern ID ox_readpartial_id;
204
+ extern ID ox_start_element_id;
205
+ extern ID ox_string_id;
206
+ extern ID ox_text_id;
207
+ extern ID ox_to_c_id;
208
+ extern ID ox_to_s_id;
209
+ extern ID ox_to_sym_id;
210
+ extern ID ox_tv_sec_id;
211
+ extern ID ox_tv_nsec_id;
212
+ extern ID ox_tv_usec_id;
213
+ extern ID ox_value_id;
214
+
215
+ extern rb_encoding *ox_utf8_encoding;
216
+
217
+ extern VALUE ox_empty_string;
218
+ extern VALUE ox_encoding_sym;
219
+ extern VALUE ox_indent_sym;
220
+ extern VALUE ox_size_sym;
221
+ extern VALUE ox_standalone_sym;
222
+ extern VALUE ox_sym_bank; // Array
223
+ extern VALUE ox_version_sym;
224
+ extern VALUE ox_zero_fixnum;
225
+
226
+ extern VALUE ox_bigdecimal_class;
227
+ extern VALUE ox_date_class;
228
+ extern VALUE ox_stringio_class;
229
+ extern VALUE ox_struct_class;
230
+ extern VALUE ox_time_class;
231
+
232
+ extern VALUE ox_document_clas;
233
+ extern VALUE ox_element_clas;
234
+ extern VALUE ox_instruct_clas;
235
+ extern VALUE ox_bag_clas;
236
+ extern VALUE ox_comment_clas;
237
+ extern VALUE ox_raw_clas;
238
+ extern VALUE ox_doctype_clas;
239
+ extern VALUE ox_cdata_clas;
240
+
241
+ extern Cache ox_symbol_cache;
242
+ extern Cache ox_class_cache;
243
+ extern Cache ox_attr_cache;
244
+
245
+ extern void ox_init_builder(VALUE ox);
268
246
 
269
247
  #if defined(__cplusplus)
270
248
  #if 0
271
249
  { /* satisfy cc-mode */
272
250
  #endif
273
- } /* extern "C" { */
251
+ } /* extern "C" { */
274
252
  #endif
275
253
  #endif /* OX_H */
data/ext/ox/oxcache.c ADDED
@@ -0,0 +1,160 @@
1
+ /* cache.c
2
+ * Copyright (c) 2011, Peter Ohler
3
+ * All rights reserved.
4
+ */
5
+
6
+ #include <stdlib.h>
7
+ #include <errno.h>
8
+ #include <stdio.h>
9
+ #include <string.h>
10
+ #include <strings.h>
11
+ #include <stdarg.h>
12
+ #include <stdint.h>
13
+
14
+ #include "oxcache.h"
15
+
16
+ struct _cache {
17
+ /* The key is a length byte followed by the key as a string. If the key is longer than 254 characters then the
18
+ length is 255. The key can be for a premature value and in that case the length byte is greater than the length
19
+ of the key. */
20
+ char *key;
21
+ VALUE value;
22
+ struct _cache *slots[16];
23
+ };
24
+
25
+ static void slot_print(Cache cache, unsigned int depth);
26
+
27
+ static char* form_key(const char *s) {
28
+ size_t len = strlen(s);
29
+ char *d = ALLOC_N(char, len + 2);
30
+
31
+ *(uint8_t*)d = (255 <= len) ? 255 : len;
32
+ memcpy(d + 1, s, len + 1);
33
+
34
+ return d;
35
+ }
36
+
37
+ void
38
+ ox_cache_new(Cache *cache) {
39
+ *cache = ALLOC(struct _cache);
40
+ (*cache)->key = 0;
41
+ (*cache)->value = Qundef;
42
+ memset((*cache)->slots, 0, sizeof((*cache)->slots));
43
+ }
44
+
45
+ VALUE
46
+ ox_cache_get(Cache cache, const char *key, VALUE **slot, const char **keyp) {
47
+ unsigned char *k = (unsigned char*)key;
48
+ Cache *cp;
49
+
50
+ for (; '\0' != *k; k++) {
51
+ cp = cache->slots + (unsigned int)(*k >> 4); /* upper 4 bits */
52
+ if (0 == *cp) {
53
+ ox_cache_new(cp);
54
+ }
55
+ cache = *cp;
56
+ cp = cache->slots + (unsigned int)(*k & 0x0F); /* lower 4 bits */
57
+ if (0 == *cp) { /* nothing on this tree so set key and value as a premature key/value pair */
58
+ ox_cache_new(cp);
59
+ cache = *cp;
60
+ cache->key = form_key(key);
61
+ break;
62
+ } else {
63
+ int depth = (int)(k - (unsigned char*)key + 1);
64
+
65
+ cache = *cp;
66
+
67
+ if ('\0' == *(k + 1)) { /* exact match */
68
+ if (0 == cache->key) { /* nothing in this spot so take it */
69
+ cache->key = form_key(key);
70
+ break;
71
+ } else if ((depth == *cache->key || 255 < depth) && 0 == strcmp(key, cache->key + 1)) { /* match */
72
+ break;
73
+ } else { /* have to move the current premature key/value deeper */
74
+ unsigned char *ck = (unsigned char*)(cache->key + depth + 1);
75
+ Cache orig = *cp;
76
+
77
+ cp = (*cp)->slots + (*ck >> 4);
78
+ ox_cache_new(cp);
79
+ cp = (*cp)->slots + (*ck & 0x0F);
80
+ ox_cache_new(cp);
81
+ (*cp)->key = cache->key;
82
+ (*cp)->value = cache->value;
83
+ orig->key = form_key(key);
84
+ orig->value = Qundef;
85
+ }
86
+ } else { /* not exact match but on the path */
87
+ if (0 != cache->key) { /* there is a key/value here already */
88
+ if (depth == *cache->key || (255 <= depth && 0 == strncmp(cache->key, key, depth) && '\0' == cache->key[depth])) { /* key belongs here */
89
+ continue;
90
+ } else {
91
+ unsigned char *ck = (unsigned char*)(cache->key + depth + 1);
92
+ Cache orig = *cp;
93
+
94
+ cp = (*cp)->slots + (*ck >> 4);
95
+ ox_cache_new(cp);
96
+ cp = (*cp)->slots + (*ck & 0x0F);
97
+ ox_cache_new(cp);
98
+ (*cp)->key = cache->key;
99
+ (*cp)->value = cache->value;
100
+ orig->key = 0;
101
+ orig->value = Qundef;
102
+ }
103
+ }
104
+ }
105
+ }
106
+ }
107
+ *slot = &cache->value;
108
+ if (0 != keyp) {
109
+ if (0 == cache->key) {
110
+ printf("*** Error: failed to set the key for '%s'\n", key);
111
+ *keyp = 0;
112
+ } else {
113
+ *keyp = cache->key + 1;
114
+ }
115
+ }
116
+ return cache->value;
117
+ }
118
+
119
+ void
120
+ ox_cache_print(Cache cache) {
121
+ /*printf("-------------------------------------------\n");*/
122
+ slot_print(cache, 0);
123
+ }
124
+
125
+ static void
126
+ slot_print(Cache c, unsigned int depth) {
127
+ char indent[256];
128
+ Cache *cp;
129
+ unsigned int i;
130
+
131
+ if (sizeof(indent) - 1 < depth) {
132
+ depth = ((int)sizeof(indent) - 1);
133
+ }
134
+ memset(indent, ' ', depth);
135
+ indent[depth] = '\0';
136
+ for (i = 0, cp = c->slots; i < 16; i++, cp++) {
137
+ if (0 == *cp) {
138
+ /*printf("%s%02u:\n", indent, i);*/
139
+ } else {
140
+ if (0 == (*cp)->key && Qundef == (*cp)->value) {
141
+ printf("%s%02u:\n", indent, i);
142
+ } else {
143
+ const char *vs;
144
+ const char *clas;
145
+
146
+ if (Qundef == (*cp)->value) {
147
+ vs = "undefined";
148
+ clas = "";
149
+ } else {
150
+ VALUE rs = rb_funcall2((*cp)->value, rb_intern("to_s"), 0, 0);
151
+
152
+ vs = StringValuePtr(rs);
153
+ clas = rb_class2name(rb_obj_class((*cp)->value));
154
+ }
155
+ printf("%s%02u: %s = %s (%s)\n", indent, i, (*cp)->key, vs, clas);
156
+ }
157
+ slot_print(*cp, depth + 2);
158
+ }
159
+ }
160
+ }
data/ext/ox/oxcache.h ADDED
@@ -0,0 +1,19 @@
1
+ /* cache.h
2
+ * Copyright (c) 2011, Peter Ohler
3
+ * All rights reserved.
4
+ */
5
+
6
+ #ifndef OX_CACHE_H
7
+ #define OX_CACHE_H
8
+
9
+ #include "ruby.h"
10
+
11
+ typedef struct _cache *Cache;
12
+
13
+ extern void ox_cache_new(Cache *cache);
14
+
15
+ extern VALUE ox_cache_get(Cache cache, const char *key, VALUE **slot, const char **keyp);
16
+
17
+ extern void ox_cache_print(Cache cache);
18
+
19
+ #endif /* OX_CACHE_H */