fast-xml 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +164 -0
- data/ext/fastxml/extconf.rb +17 -0
- data/ext/fastxml/fastxml.c +67 -0
- data/ext/fastxml/fastxml.h +14 -0
- data/ext/fastxml/xh.c +338 -0
- data/ext/fastxml/xh.h +58 -0
- data/ext/fastxml/xh_buffer.c +40 -0
- data/ext/fastxml/xh_buffer.h +38 -0
- data/ext/fastxml/xh_buffer_helper.h +97 -0
- data/ext/fastxml/xh_config.h +74 -0
- data/ext/fastxml/xh_core.h +53 -0
- data/ext/fastxml/xh_encoder.c +193 -0
- data/ext/fastxml/xh_encoder.h +56 -0
- data/ext/fastxml/xh_h2x.c +62 -0
- data/ext/fastxml/xh_h2x.h +93 -0
- data/ext/fastxml/xh_h2x_native.c +89 -0
- data/ext/fastxml/xh_h2x_native_attr.c +161 -0
- data/ext/fastxml/xh_log.c +31 -0
- data/ext/fastxml/xh_log.h +100 -0
- data/ext/fastxml/xh_param.c +77 -0
- data/ext/fastxml/xh_param.h +56 -0
- data/ext/fastxml/xh_ruby_buffer.c +51 -0
- data/ext/fastxml/xh_ruby_buffer.h +30 -0
- data/ext/fastxml/xh_sort.c +40 -0
- data/ext/fastxml/xh_sort.h +20 -0
- data/ext/fastxml/xh_stack.c +19 -0
- data/ext/fastxml/xh_stack.h +41 -0
- data/ext/fastxml/xh_string.h +105 -0
- data/ext/fastxml/xh_writer.c +94 -0
- data/ext/fastxml/xh_writer.h +49 -0
- data/ext/fastxml/xh_xml.h +453 -0
- data/lib/fastxml.rb +59 -0
- data/lib/fastxml/error.rb +7 -0
- data/lib/fastxml/version.rb +3 -0
- metadata +139 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
#include "xh_config.h"
|
2
|
+
#include "xh_core.h"
|
3
|
+
|
4
|
+
#define XH_LOG_LEVEL XH_LOG_TRACE
|
5
|
+
|
6
|
+
static const char *LOG_LEVEL_NAME[7] = {
|
7
|
+
"CRITIC",
|
8
|
+
"ERROR",
|
9
|
+
"WARN",
|
10
|
+
"NOTICE",
|
11
|
+
"INFO",
|
12
|
+
"DEBUG",
|
13
|
+
"TRACE",
|
14
|
+
};
|
15
|
+
|
16
|
+
void
|
17
|
+
xh_log(xh_log_level_t log_level, const char *func, xh_int_t line, const char *msg, ...)
|
18
|
+
{
|
19
|
+
va_list args;
|
20
|
+
|
21
|
+
if (log_level > XH_LOG_LEVEL) return;
|
22
|
+
|
23
|
+
(void) fprintf(stderr, "(%s) %s[%.0d]: ", LOG_LEVEL_NAME[log_level], func, (int) line);
|
24
|
+
|
25
|
+
va_start(args, msg);
|
26
|
+
(void) vfprintf(stderr, msg, args);
|
27
|
+
if (msg[strlen(msg) - 1] != '\n') {
|
28
|
+
(void) fprintf(stderr, "\n");
|
29
|
+
}
|
30
|
+
va_end(args);
|
31
|
+
}
|
@@ -0,0 +1,100 @@
|
|
1
|
+
#include "xh_config.h"
|
2
|
+
#include "xh_core.h"
|
3
|
+
|
4
|
+
#ifndef _XH_LOG_H_
|
5
|
+
#define _XH_LOG_H_
|
6
|
+
|
7
|
+
typedef enum {
|
8
|
+
XH_LOG_CRITIC = 0,
|
9
|
+
XH_LOG_ERROR,
|
10
|
+
XH_LOG_WARN,
|
11
|
+
XH_LOG_NOTICE,
|
12
|
+
XH_LOG_INFO,
|
13
|
+
XH_LOG_DEBUG,
|
14
|
+
XH_LOG_TRACE
|
15
|
+
} xh_log_level_t;
|
16
|
+
|
17
|
+
#ifdef WITH_TRACE
|
18
|
+
#define xh_log_debug0(msg) \
|
19
|
+
xh_log(XH_LOG_DEBUG, __FUNCTION__, __LINE__, msg)
|
20
|
+
#define xh_log_debug1(msg, arg1) \
|
21
|
+
xh_log(XH_LOG_DEBUG, __FUNCTION__, __LINE__, msg, arg1)
|
22
|
+
#define xh_log_debug2(msg, arg1, arg2) \
|
23
|
+
xh_log(XH_LOG_DEBUG, __FUNCTION__, __LINE__, msg, arg1, arg2)
|
24
|
+
#define xh_log_debug3(msg, arg1, arg2, arg3) \
|
25
|
+
xh_log(XH_LOG_DEBUG, __FUNCTION__, __LINE__, msg, arg1, arg2, arg3)
|
26
|
+
#define xh_log_debug4(msg, arg1, arg2, arg3, arg4) \
|
27
|
+
xh_log(XH_LOG_DEBUG, __FUNCTION__, __LINE__, msg, arg1, arg2, arg3, arg4)
|
28
|
+
#define xh_log_debug5(msg, arg1, arg2, arg3, arg4, arg5) \
|
29
|
+
xh_log(XH_LOG_DEBUG, __FUNCTION__, __LINE__, msg, arg1, arg2, arg3, arg4, arg5)
|
30
|
+
#define xh_log_debug6(msg, arg1, arg2, arg3, arg4, arg5, arg6) \
|
31
|
+
xh_log(XH_LOG_DEBUG, __FUNCTION__, __LINE__, msg, arg1, arg2, arg3, arg4, arg5, arg6)
|
32
|
+
#define xh_log_debug7(msg, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
|
33
|
+
xh_log(XH_LOG_DEBUG, __FUNCTION__, __LINE__, msg, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
|
34
|
+
#define xh_log_debug8(msg, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \
|
35
|
+
xh_log(XH_LOG_DEBUG, __FUNCTION__, __LINE__, msg, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
|
36
|
+
#else
|
37
|
+
#define xh_log_debug0(msg)
|
38
|
+
#define xh_log_debug1(msg, arg1)
|
39
|
+
#define xh_log_debug2(msg, arg1, arg2)
|
40
|
+
#define xh_log_debug3(msg, arg1, arg2, arg3)
|
41
|
+
#define xh_log_debug4(msg, arg1, arg2, arg3, arg4)
|
42
|
+
#define xh_log_debug5(msg, arg1, arg2, arg3, arg4, arg5)
|
43
|
+
#define xh_log_debug6(msg, arg1, arg2, arg3, arg4, arg5, arg6)
|
44
|
+
#define xh_log_debug7(msg, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
|
45
|
+
#define xh_log_debug8(msg, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
|
46
|
+
#endif
|
47
|
+
|
48
|
+
#ifdef WITH_TRACE
|
49
|
+
#define xh_log_trace0(msg) \
|
50
|
+
xh_log(XH_LOG_TRACE, __FUNCTION__, __LINE__, msg)
|
51
|
+
#define xh_log_trace1(msg, arg1) \
|
52
|
+
xh_log(XH_LOG_TRACE, __FUNCTION__, __LINE__, msg, arg1)
|
53
|
+
#define xh_log_trace2(msg, arg1, arg2) \
|
54
|
+
xh_log(XH_LOG_TRACE, __FUNCTION__, __LINE__, msg, arg1, arg2)
|
55
|
+
#define xh_log_trace3(msg, arg1, arg2, arg3) \
|
56
|
+
xh_log(XH_LOG_TRACE, __FUNCTION__, __LINE__, msg, arg1, arg2, arg3)
|
57
|
+
#define xh_log_trace4(msg, arg1, arg2, arg3, arg4) \
|
58
|
+
xh_log(XH_LOG_TRACE, __FUNCTION__, __LINE__, msg, arg1, arg2, arg3, arg4)
|
59
|
+
#define xh_log_trace5(msg, arg1, arg2, arg3, arg4, arg5) \
|
60
|
+
xh_log(XH_LOG_TRACE, __FUNCTION__, __LINE__, msg, arg1, arg2, arg3, arg4, arg5)
|
61
|
+
#define xh_log_trace6(msg, arg1, arg2, arg3, arg4, arg5, arg6) \
|
62
|
+
xh_log(XH_LOG_TRACE, __FUNCTION__, __LINE__, msg, arg1, arg2, arg3, arg4, arg5, arg6)
|
63
|
+
#define xh_log_trace7(msg, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
|
64
|
+
xh_log(XH_LOG_TRACE, __FUNCTION__, __LINE__, msg, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
|
65
|
+
#define xh_log_trace8(msg, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \
|
66
|
+
xh_log(XH_LOG_TRACE, __FUNCTION__, __LINE__, msg, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
|
67
|
+
#else
|
68
|
+
#define xh_log_trace0(msg)
|
69
|
+
#define xh_log_trace1(msg, arg1)
|
70
|
+
#define xh_log_trace2(msg, arg1, arg2)
|
71
|
+
#define xh_log_trace3(msg, arg1, arg2, arg3)
|
72
|
+
#define xh_log_trace4(msg, arg1, arg2, arg3, arg4)
|
73
|
+
#define xh_log_trace5(msg, arg1, arg2, arg3, arg4, arg5)
|
74
|
+
#define xh_log_trace6(msg, arg1, arg2, arg3, arg4, arg5, arg6)
|
75
|
+
#define xh_log_trace7(msg, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
|
76
|
+
#define xh_log_trace8(msg, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
|
77
|
+
#endif
|
78
|
+
|
79
|
+
#define xh_log_error0(msg) \
|
80
|
+
xh_log(XH_LOG_ERROR, __FUNCTION__, __LINE__, msg)
|
81
|
+
#define xh_log_error1(msg, arg1) \
|
82
|
+
xh_log(XH_LOG_ERROR, __FUNCTION__, __LINE__, msg, arg1)
|
83
|
+
#define xh_log_error2(msg, arg1, arg2) \
|
84
|
+
xh_log(XH_LOG_ERROR, __FUNCTION__, __LINE__, msg, arg1, arg2)
|
85
|
+
#define xh_log_error3(msg, arg1, arg2, arg3) \
|
86
|
+
xh_log(XH_LOG_ERROR, __FUNCTION__, __LINE__, msg, arg1, arg2, arg3)
|
87
|
+
#define xh_log_error4(msg, arg1, arg2, arg3, arg4) \
|
88
|
+
xh_log(XH_LOG_ERROR, __FUNCTION__, __LINE__, msg, arg1, arg2, arg3, arg4)
|
89
|
+
#define xh_log_error5(msg, arg1, arg2, arg3, arg4, arg5) \
|
90
|
+
xh_log(XH_LOG_ERROR, __FUNCTION__, __LINE__, msg, arg1, arg2, arg3, arg4, arg5)
|
91
|
+
#define xh_log_error6(msg, arg1, arg2, arg3, arg4, arg5, arg6) \
|
92
|
+
xh_log(XH_LOG_ERROR, __FUNCTION__, __LINE__, msg, arg1, arg2, arg3, arg4, arg5, arg6)
|
93
|
+
#define xh_log_error7(msg, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
|
94
|
+
xh_log(XH_LOG_ERROR, __FUNCTION__, __LINE__, msg, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
|
95
|
+
#define xh_log_error8(msg, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \
|
96
|
+
xh_log(XH_LOG_ERROR, __FUNCTION__, __LINE__, msg, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
|
97
|
+
|
98
|
+
void xh_log(xh_log_level_t log_level, const char *func, xh_int_t line, const char *msg, ...);
|
99
|
+
|
100
|
+
#endif /* _XH_LOG_H_ */
|
@@ -0,0 +1,77 @@
|
|
1
|
+
#include "xh_config.h"
|
2
|
+
#include "xh_core.h"
|
3
|
+
|
4
|
+
void
|
5
|
+
xh_param_assign_string(xh_char_t param[], VALUE value)
|
6
|
+
{
|
7
|
+
xh_char_t *str;
|
8
|
+
|
9
|
+
if ( RTEST(value) ) {
|
10
|
+
str = (xh_char_t *) StringValueCStr(value);
|
11
|
+
xh_str_copy(param, str, XH_PARAM_LEN);
|
12
|
+
}
|
13
|
+
else {
|
14
|
+
*param = 0;
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
void
|
19
|
+
xh_param_assign_int(xh_char_t *name, xh_int_t *param, VALUE value)
|
20
|
+
{
|
21
|
+
Check_Type(value, T_FIXNUM);
|
22
|
+
*param = FIX2INT(value);
|
23
|
+
}
|
24
|
+
|
25
|
+
xh_bool_t
|
26
|
+
xh_param_assign_bool(VALUE value)
|
27
|
+
{
|
28
|
+
if ( RTEST(value) )
|
29
|
+
return TRUE;
|
30
|
+
|
31
|
+
return FALSE;
|
32
|
+
}
|
33
|
+
|
34
|
+
void
|
35
|
+
xh_param_assign_pattern(xh_pattern_t *patt, VALUE value)
|
36
|
+
{
|
37
|
+
if ( RTEST(value) ) {
|
38
|
+
patt->enable = TRUE;
|
39
|
+
if ( RB_TYPE_P(value, T_REGEXP) || RB_TYPE_P(value, T_ARRAY) ) {
|
40
|
+
patt->always = FALSE;
|
41
|
+
patt->expr = value;
|
42
|
+
}
|
43
|
+
else {
|
44
|
+
patt->always = TRUE;
|
45
|
+
}
|
46
|
+
}
|
47
|
+
else {
|
48
|
+
patt->enable = FALSE;
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
void
|
53
|
+
xh_param_assign_filter(xh_pattern_t *patt, VALUE value)
|
54
|
+
{
|
55
|
+
if ( RTEST(value) ) {
|
56
|
+
patt->enable = TRUE;
|
57
|
+
patt->always = FALSE;
|
58
|
+
patt->expr = value;
|
59
|
+
}
|
60
|
+
else {
|
61
|
+
patt->enable = FALSE;
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
VALUE
|
66
|
+
xh_param_assign_cb(VALUE value)
|
67
|
+
{
|
68
|
+
if ( !RTEST(value) )
|
69
|
+
return Qnil;
|
70
|
+
|
71
|
+
if (rb_cProc != rb_class_of(value) && rb_cMethod != rb_class_of(value))
|
72
|
+
rb_raise(rb_eArgError, "Expected Proc or Method callback");
|
73
|
+
|
74
|
+
//rb_funcall(value, rb_intern("call"), 0);
|
75
|
+
|
76
|
+
return value;
|
77
|
+
}
|
@@ -0,0 +1,56 @@
|
|
1
|
+
#ifndef _XH_PARAM_H_
|
2
|
+
#define _XH_PARAM_H_
|
3
|
+
|
4
|
+
#include "xh_config.h"
|
5
|
+
#include "xh_core.h"
|
6
|
+
|
7
|
+
typedef struct {
|
8
|
+
xh_bool_t enable;
|
9
|
+
xh_bool_t always;
|
10
|
+
VALUE expr;
|
11
|
+
} xh_pattern_t;
|
12
|
+
|
13
|
+
void xh_param_assign_string(xh_char_t param[], VALUE value);
|
14
|
+
void xh_param_assign_int(xh_char_t *name, xh_int_t *param, VALUE value);
|
15
|
+
xh_bool_t xh_param_assign_bool(VALUE value);
|
16
|
+
void xh_param_assign_pattern(xh_pattern_t *param, VALUE value);
|
17
|
+
void xh_param_assign_filter(xh_pattern_t *param, VALUE value);
|
18
|
+
VALUE xh_param_assign_cb(VALUE value);
|
19
|
+
|
20
|
+
#define XH_PARAM_LEN 32
|
21
|
+
|
22
|
+
#define XH_PARAM_READ_INIT \
|
23
|
+
VALUE value; \
|
24
|
+
xh_char_t *str;
|
25
|
+
|
26
|
+
#define XH_PARAM_READ_STRING(var, name) \
|
27
|
+
value = rb_iv_get(xh_module, name); \
|
28
|
+
if ( RTEST(value) ) { \
|
29
|
+
str = XH_CHAR_CAST StringValueCStr(value); \
|
30
|
+
xh_str_copy(var, str, XH_PARAM_LEN); \
|
31
|
+
} \
|
32
|
+
else { \
|
33
|
+
var[0] = '\0'; \
|
34
|
+
}
|
35
|
+
|
36
|
+
#define XH_PARAM_READ_BOOL(var, name) \
|
37
|
+
value = rb_iv_get(xh_module, name); \
|
38
|
+
if ( RTEST(value) ) { \
|
39
|
+
var = TRUE; \
|
40
|
+
} \
|
41
|
+
else { \
|
42
|
+
var = FALSE; \
|
43
|
+
}
|
44
|
+
|
45
|
+
#define XH_PARAM_READ_INT(var, name) \
|
46
|
+
value = rb_iv_get(xh_module, name); \
|
47
|
+
var = FIX2INT(value);
|
48
|
+
|
49
|
+
#define XH_PARAM_READ_REF(var, name) \
|
50
|
+
var = rb_iv_get(xh_module, name);
|
51
|
+
|
52
|
+
#define XH_PARAM_READ_PATTERN(var, name) \
|
53
|
+
value = rb_iv_get(xh_module, name); \
|
54
|
+
xh_param_assign_pattern(&(var), value);
|
55
|
+
|
56
|
+
#endif /* _XH_PARAM_H_ */
|
@@ -0,0 +1,51 @@
|
|
1
|
+
#include "xh_config.h"
|
2
|
+
#include "xh_core.h"
|
3
|
+
|
4
|
+
void
|
5
|
+
xh_ruby_buffer_init(xh_ruby_buffer_t *buf, size_t size)
|
6
|
+
{
|
7
|
+
buf->scalar = rb_str_new(NULL, size);
|
8
|
+
|
9
|
+
buf->start = buf->cur = XH_CHAR_CAST RSTRING_PTR(buf->scalar);
|
10
|
+
buf->end = buf->start + size;
|
11
|
+
|
12
|
+
xh_log_debug2("buf: %p size: %lu", buf->start, size);
|
13
|
+
}
|
14
|
+
|
15
|
+
void
|
16
|
+
xh_ruby_buffer_grow(xh_ruby_buffer_t *buf, size_t inc)
|
17
|
+
{
|
18
|
+
size_t size, use;
|
19
|
+
|
20
|
+
if (inc <= (size_t) (buf->end - buf->cur))
|
21
|
+
return;
|
22
|
+
|
23
|
+
size = xh_ruby_buffer_size(buf);
|
24
|
+
use = xh_ruby_buffer_use(buf);
|
25
|
+
|
26
|
+
xh_log_debug2("old buf: %p size: %lu", buf->start, size);
|
27
|
+
|
28
|
+
size += inc < size ? size : inc;
|
29
|
+
|
30
|
+
rb_str_set_len(buf->scalar, use);
|
31
|
+
rb_str_resize(buf->scalar, size);
|
32
|
+
|
33
|
+
buf->start = XH_CHAR_CAST RSTRING_PTR(buf->scalar);
|
34
|
+
buf->cur = buf->start + use;
|
35
|
+
buf->end = buf->start + size;
|
36
|
+
|
37
|
+
xh_log_debug2("new buf: %p size: %lu", buf->start, size);
|
38
|
+
}
|
39
|
+
|
40
|
+
void
|
41
|
+
xh_ruby_buffer_sync(xh_ruby_buffer_t *buf)
|
42
|
+
{
|
43
|
+
size_t use = buf->cur - buf->start;
|
44
|
+
size_t size = RSTRING_LEN(buf->scalar);
|
45
|
+
|
46
|
+
buf->start = XH_CHAR_CAST RSTRING_PTR(buf->scalar);
|
47
|
+
buf->end = buf->start + size;
|
48
|
+
buf->cur = buf->start + use;
|
49
|
+
|
50
|
+
xh_log_debug2("buf: %p size: %lu", buf->start, size);
|
51
|
+
}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#ifndef _XH_RUBY_BUFFER_H_
|
2
|
+
#define _XH_RUBY_BUFFER_H_
|
3
|
+
|
4
|
+
#include "xh_config.h"
|
5
|
+
#include "xh_core.h"
|
6
|
+
|
7
|
+
typedef struct _xh_ruby_buffer_t xh_ruby_buffer_t;
|
8
|
+
struct _xh_ruby_buffer_t {
|
9
|
+
VALUE scalar;
|
10
|
+
xh_char_t *start;
|
11
|
+
xh_char_t *cur;
|
12
|
+
xh_char_t *end;
|
13
|
+
};
|
14
|
+
|
15
|
+
void xh_ruby_buffer_init(xh_ruby_buffer_t *buf, size_t size);
|
16
|
+
void xh_ruby_buffer_grow(xh_ruby_buffer_t *buf, size_t inc);
|
17
|
+
void xh_ruby_buffer_sync(xh_ruby_buffer_t *buf);
|
18
|
+
|
19
|
+
#define xh_ruby_buffer_avail(b) ((b)->end - (b)->cur)
|
20
|
+
#define xh_ruby_buffer_start(b) ((b)->start)
|
21
|
+
#define xh_ruby_buffer_pos(b) ((b)->cur)
|
22
|
+
#define xh_ruby_buffer_end(b) ((b)->end)
|
23
|
+
#define xh_ruby_buffer_size(b) ((b)->end - (b)->start)
|
24
|
+
#define xh_ruby_buffer_use(b) ((b)->cur - (b)->start)
|
25
|
+
#define xh_ruby_buffer_seek(b, p) (b)->cur = p
|
26
|
+
#define xh_ruby_buffer_seek_eof(b) (b)->cur = (b)->end
|
27
|
+
#define xh_ruby_buffer_seek_top(b) (b)->cur = (b)->start
|
28
|
+
#define xh_ruby_buffer_grow50(b) xh_ruby_buffer_grow((b), xh_ruby_buffer_size(b) / 2)
|
29
|
+
|
30
|
+
#endif /* _XH_RUBY_BUFFER_H_ */
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#include "xh_config.h"
|
2
|
+
#include "xh_core.h"
|
3
|
+
|
4
|
+
static int
|
5
|
+
xh_sort_hash_cmp(const void *p1, const void *p2)
|
6
|
+
{
|
7
|
+
return xh_strcmp(((xh_sort_hash_elt_t *) p1)->key, ((xh_sort_hash_elt_t *) p2)->key);
|
8
|
+
}
|
9
|
+
|
10
|
+
static int
|
11
|
+
xh_sort_hash_iter(VALUE key, VALUE value, VALUE arg)
|
12
|
+
{
|
13
|
+
xh_sort_hash_t *sorted_hash = (xh_sort_hash_t *) arg;
|
14
|
+
|
15
|
+
if (SYMBOL_P(key)) {
|
16
|
+
key = rb_sym2str(key);
|
17
|
+
}
|
18
|
+
else {
|
19
|
+
key = rb_obj_as_string(key);
|
20
|
+
}
|
21
|
+
|
22
|
+
key = StringValue(key);
|
23
|
+
|
24
|
+
sorted_hash->elts[sorted_hash->nelts].value = value;
|
25
|
+
sorted_hash->elts[sorted_hash->nelts].key = XH_CHAR_CAST StringValueCStr(key);
|
26
|
+
sorted_hash->elts[sorted_hash->nelts].key_len = RSTRING_LEN(key);
|
27
|
+
sorted_hash->nelts++;
|
28
|
+
|
29
|
+
return ST_CONTINUE;
|
30
|
+
}
|
31
|
+
|
32
|
+
void
|
33
|
+
xh_sort_hash(xh_sort_hash_t *sorted_hash, VALUE hash)
|
34
|
+
{
|
35
|
+
sorted_hash->nelts = 0;
|
36
|
+
|
37
|
+
rb_hash_foreach(hash, xh_sort_hash_iter, (VALUE) sorted_hash);
|
38
|
+
|
39
|
+
qsort(sorted_hash->elts, sorted_hash->nelts, sizeof(xh_sort_hash_elt_t), xh_sort_hash_cmp);
|
40
|
+
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#ifndef _XH_SORT_H_
|
2
|
+
#define _XH_SORT_H_
|
3
|
+
|
4
|
+
#include "xh_config.h"
|
5
|
+
#include "xh_core.h"
|
6
|
+
|
7
|
+
typedef struct {
|
8
|
+
xh_char_t *key;
|
9
|
+
size_t key_len;
|
10
|
+
VALUE value;
|
11
|
+
} xh_sort_hash_elt_t;
|
12
|
+
|
13
|
+
typedef struct {
|
14
|
+
xh_sort_hash_elt_t *elts;
|
15
|
+
size_t nelts;
|
16
|
+
} xh_sort_hash_t;
|
17
|
+
|
18
|
+
void xh_sort_hash(xh_sort_hash_t *sorted_hash, VALUE hash);
|
19
|
+
|
20
|
+
#endif /* _XH_SORT_H_ */
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#include "xh_config.h"
|
2
|
+
#include "xh_core.h"
|
3
|
+
|
4
|
+
void
|
5
|
+
xh_stack_init(xh_stack_t *st, xh_uint_t nelts, size_t size)
|
6
|
+
{
|
7
|
+
if ((st->elts = malloc(nelts * size)) == NULL) {
|
8
|
+
rb_raise(rb_eNoMemError, "Memory allocation error");
|
9
|
+
}
|
10
|
+
st->size = size;
|
11
|
+
st->nelts = nelts;
|
12
|
+
st->top = 0;
|
13
|
+
}
|
14
|
+
|
15
|
+
void
|
16
|
+
xh_stack_destroy(xh_stack_t *st)
|
17
|
+
{
|
18
|
+
free(st->elts);
|
19
|
+
}
|
@@ -0,0 +1,41 @@
|
|
1
|
+
#ifndef _XH_STACK_H_
|
2
|
+
#define _XH_STACK_H_
|
3
|
+
|
4
|
+
#include "xh_config.h"
|
5
|
+
#include "xh_core.h"
|
6
|
+
|
7
|
+
typedef struct {
|
8
|
+
void *elts;
|
9
|
+
size_t size;
|
10
|
+
size_t nelts;
|
11
|
+
size_t top;
|
12
|
+
} xh_stack_t;
|
13
|
+
|
14
|
+
XH_INLINE void *
|
15
|
+
xh_stack_push(xh_stack_t *st)
|
16
|
+
{
|
17
|
+
if (st->top >= st->nelts) {
|
18
|
+
st->nelts *= 2;
|
19
|
+
if ((st->elts = realloc(st->elts, st->nelts * st->size)) == NULL) {
|
20
|
+
rb_raise(rb_eNoMemError, "Memory allocation error");
|
21
|
+
}
|
22
|
+
}
|
23
|
+
return (void *) (XH_CHAR_CAST st->elts + st->top++ * st->size);
|
24
|
+
}
|
25
|
+
|
26
|
+
XH_INLINE void *
|
27
|
+
xh_stack_pop(xh_stack_t *st)
|
28
|
+
{
|
29
|
+
return st->top == 0 ? NULL : (void *) (XH_CHAR_CAST st->elts + --st->top * st->size);
|
30
|
+
}
|
31
|
+
|
32
|
+
XH_INLINE xh_bool_t
|
33
|
+
xh_stack_empty(xh_stack_t *st)
|
34
|
+
{
|
35
|
+
return st->top == 0 ? TRUE : FALSE;
|
36
|
+
}
|
37
|
+
|
38
|
+
void xh_stack_init(xh_stack_t *st, xh_uint_t nelts, size_t size);
|
39
|
+
void xh_stack_destroy(xh_stack_t *st);
|
40
|
+
|
41
|
+
#endif /* _XH_STACK_H_ */
|