xrb 0.8.0 → 0.10.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6cdd134a8dbbdd3fd3840ed10b0cf3962c80489eefb36a32bef94271cb2f8faf
4
- data.tar.gz: 8abbd27c3c9c15fb58a34062b150e29247ea812e3b7c6543c8eef83368f5f08d
3
+ metadata.gz: 7576d5a9614c5ca657109b06f71b2091717cf0919be858527dd7d2d259162327
4
+ data.tar.gz: 57ecf941224ddd1b6fc7da50efc01d6a1f09c8ed63fe03249b183e171c9bf25d
5
5
  SHA512:
6
- metadata.gz: e5e2b90a6b1b50ea700fdb39c6a99cce61c670ce643575d79ea0588187a06a4927c8929bea88c3ff5b81b19e40c18e7356beccd8d76a0c9a2def48cc3eac4a93
7
- data.tar.gz: f42d5425f29420a70b44c4c974a00ce46aa53dc03acd4e4f629fa7f3a40340fde12f268bcd97e423507a1ba45617cd57dbc1414746f83c9002edbb36005c5bf8
6
+ metadata.gz: c694e8def7354e1f1c74006349faa3ccf931f056bba6d89ab564cfc998b484880ef9e87f168ecb11751156d03fb5dee216402d670fb426d40151db6a9f1a884c
7
+ data.tar.gz: a040bd3bfa83f9e3583585e79cb801d71334c978b1222f06a7be258bf936ef14ac6bd918cd4c03828a77c4956e0c539846b829957bd27bb9e3b173777a2ffefc
checksums.yaml.gz.sig CHANGED
Binary file
data/ext/Makefile ADDED
@@ -0,0 +1,270 @@
1
+
2
+ SHELL = /bin/sh
3
+
4
+ # V=0 quiet, V=1 verbose. other values don't work.
5
+ V = 0
6
+ V0 = $(V:0=)
7
+ Q1 = $(V:1=)
8
+ Q = $(Q1:0=@)
9
+ ECHO1 = $(V:1=@ :)
10
+ ECHO = $(ECHO1:0=@ echo)
11
+ NULLCMD = :
12
+
13
+ #### Start of system configuration section. ####
14
+
15
+ srcdir = .
16
+ topdir = /Users/samuel/.rubies/ruby-3.3.4/include/ruby-3.3.0
17
+ hdrdir = $(topdir)
18
+ arch_hdrdir = /Users/samuel/.rubies/ruby-3.3.4/include/ruby-3.3.0/arm64-darwin24
19
+ PATH_SEPARATOR = :
20
+ VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby:$(srcdir)/xrb
21
+ prefix = $(DESTDIR)/Users/samuel/.rubies/ruby-3.3.4
22
+ rubysitearchprefix = $(rubylibprefix)/$(sitearch)
23
+ rubyarchprefix = $(rubylibprefix)/$(arch)
24
+ rubylibprefix = $(libdir)/$(RUBY_BASE_NAME)
25
+ exec_prefix = $(prefix)
26
+ vendorarchhdrdir = $(vendorhdrdir)/$(sitearch)
27
+ sitearchhdrdir = $(sitehdrdir)/$(sitearch)
28
+ rubyarchhdrdir = $(rubyhdrdir)/$(arch)
29
+ vendorhdrdir = $(rubyhdrdir)/vendor_ruby
30
+ sitehdrdir = $(rubyhdrdir)/site_ruby
31
+ rubyhdrdir = $(includedir)/$(RUBY_VERSION_NAME)
32
+ vendorarchdir = $(vendorlibdir)/$(sitearch)
33
+ vendorlibdir = $(vendordir)/$(ruby_version)
34
+ vendordir = $(rubylibprefix)/vendor_ruby
35
+ sitearchdir = $(sitelibdir)/$(sitearch)
36
+ sitelibdir = $(sitedir)/$(ruby_version)
37
+ sitedir = $(rubylibprefix)/site_ruby
38
+ rubyarchdir = $(rubylibdir)/$(arch)
39
+ rubylibdir = $(rubylibprefix)/$(ruby_version)
40
+ sitearchincludedir = $(includedir)/$(sitearch)
41
+ archincludedir = $(includedir)/$(arch)
42
+ sitearchlibdir = $(libdir)/$(sitearch)
43
+ archlibdir = $(libdir)/$(arch)
44
+ ridir = $(datarootdir)/$(RI_BASE_NAME)
45
+ mandir = $(datarootdir)/man
46
+ localedir = $(datarootdir)/locale
47
+ libdir = $(exec_prefix)/lib
48
+ psdir = $(docdir)
49
+ pdfdir = $(docdir)
50
+ dvidir = $(docdir)
51
+ htmldir = $(docdir)
52
+ infodir = $(datarootdir)/info
53
+ docdir = $(datarootdir)/doc/$(PACKAGE)
54
+ oldincludedir = $(DESTDIR)/usr/include
55
+ includedir = $(SDKROOT)$(prefix)/include
56
+ runstatedir = $(localstatedir)/run
57
+ localstatedir = $(prefix)/var
58
+ sharedstatedir = $(prefix)/com
59
+ sysconfdir = $(prefix)/etc
60
+ datadir = $(datarootdir)
61
+ datarootdir = $(prefix)/share
62
+ libexecdir = $(exec_prefix)/libexec
63
+ sbindir = $(exec_prefix)/sbin
64
+ bindir = $(exec_prefix)/bin
65
+ archdir = $(rubyarchdir)
66
+
67
+
68
+ CC_WRAPPER =
69
+ CC = clang
70
+ CXX = clang++
71
+ LIBRUBY = $(LIBRUBY_A)
72
+ LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
73
+ LIBRUBYARG_SHARED =
74
+ LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static -framework CoreFoundation $(MAINLIBS)
75
+ empty =
76
+ OUTFLAG = -o $(empty)
77
+ COUTFLAG = -o $(empty)
78
+ CSRCFLAG = $(empty)
79
+
80
+ RUBY_EXTCONF_H = extconf.h
81
+ cflags = -fdeclspec $(optflags) $(debugflags) $(warnflags)
82
+ cxxflags =
83
+ optflags = -O3 -fno-fast-math
84
+ debugflags = -ggdb3
85
+ warnflags = -Wall -Wextra -Wextra-tokens -Wdeprecated-declarations -Wdivision-by-zero -Wdiv-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wold-style-definition -Wmissing-noreturn -Wno-cast-function-type -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wmisleading-indentation -Wundef
86
+ cppflags =
87
+ CCDLFLAGS = -fno-common
88
+ CFLAGS = $(CCDLFLAGS) $(cflags) -pipe -O3 -Wall -Wno-unknown-pragmas -std=c99 $(ARCH_FLAG)
89
+ INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir)
90
+ DEFS =
91
+ CPPFLAGS = -DRUBY_EXTCONF_H=\"$(RUBY_EXTCONF_H)\" -I/opt/local/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT $(DEFS) $(cppflags)
92
+ CXXFLAGS = $(CCDLFLAGS) -fdeclspec $(ARCH_FLAG)
93
+ ldflags = -L. -fstack-protector-strong -L/opt/local/lib
94
+ dldflags = -L/opt/local/lib -Wl,-undefined,dynamic_lookup -bundle_loader '$(BUILTRUBY)'
95
+ ARCH_FLAG = -arch arm64
96
+ DLDFLAGS = $(ldflags) $(dldflags) $(ARCH_FLAG)
97
+ LDSHARED = $(CC) -dynamic -bundle
98
+ LDSHAREDXX = $(CXX) -dynamic -bundle
99
+ AR = ar
100
+ EXEEXT =
101
+
102
+ RUBY_INSTALL_NAME = $(RUBY_BASE_NAME)
103
+ RUBY_SO_NAME = ruby.3.3
104
+ RUBYW_INSTALL_NAME =
105
+ RUBY_VERSION_NAME = $(RUBY_BASE_NAME)-$(ruby_version)
106
+ RUBYW_BASE_NAME = rubyw
107
+ RUBY_BASE_NAME = ruby
108
+
109
+ arch = arm64-darwin24
110
+ sitearch = $(arch)
111
+ ruby_version = 3.3.0
112
+ ruby = $(bindir)/$(RUBY_BASE_NAME)
113
+ RUBY = $(ruby)
114
+ BUILTRUBY = $(bindir)/$(RUBY_BASE_NAME)
115
+ ruby_headers = $(hdrdir)/ruby.h $(hdrdir)/ruby/backward.h $(hdrdir)/ruby/ruby.h $(hdrdir)/ruby/defines.h $(hdrdir)/ruby/missing.h $(hdrdir)/ruby/intern.h $(hdrdir)/ruby/st.h $(hdrdir)/ruby/subst.h $(arch_hdrdir)/ruby/config.h $(RUBY_EXTCONF_H)
116
+
117
+ RM = rm -f
118
+ RM_RF = rm -fr
119
+ RMDIRS = rmdir -p
120
+ MAKEDIRS = mkdir -p
121
+ INSTALL = /usr/bin/install -c
122
+ INSTALL_PROG = $(INSTALL) -m 0755
123
+ INSTALL_DATA = $(INSTALL) -m 644
124
+ COPY = cp
125
+ TOUCH = exit >
126
+
127
+ #### End of system configuration section. ####
128
+
129
+ preload =
130
+ libpath = . $(libdir) /opt/local/lib
131
+ LIBPATH = -L. -L$(libdir) -L/opt/local/lib
132
+ DEFFILE =
133
+
134
+ CLEANFILES = mkmf.log
135
+ DISTCLEANFILES =
136
+ DISTCLEANDIRS =
137
+
138
+ extout =
139
+ extout_prefix =
140
+ target_prefix =
141
+ LOCAL_LIBS =
142
+ LIBS = -lpthread
143
+ ORIG_SRCS =
144
+ SRCS = $(ORIG_SRCS) escape.c markup.c query.c tag.c template.c xrb.c
145
+ OBJS = escape.o markup.o query.o tag.o template.o xrb.o
146
+ HDRS = $(srcdir)/extconf.h
147
+ LOCAL_HDRS =
148
+ TARGET = XRB_Extension
149
+ TARGET_NAME = XRB_Extension
150
+ TARGET_ENTRY = Init_$(TARGET_NAME)
151
+ DLLIB = $(TARGET).bundle
152
+ EXTSTATIC =
153
+ STATIC_LIB =
154
+
155
+ TIMESTAMP_DIR = .
156
+ BINDIR = $(bindir)
157
+ RUBYCOMMONDIR = $(sitedir)$(target_prefix)
158
+ RUBYLIBDIR = $(sitelibdir)$(target_prefix)
159
+ RUBYARCHDIR = $(sitearchdir)$(target_prefix)
160
+ HDRDIR = $(sitehdrdir)$(target_prefix)
161
+ ARCHHDRDIR = $(sitearchhdrdir)$(target_prefix)
162
+ TARGET_SO_DIR =
163
+ TARGET_SO = $(TARGET_SO_DIR)$(DLLIB)
164
+ CLEANLIBS = $(TARGET_SO) $(TARGET_SO).dSYM
165
+ CLEANOBJS = $(OBJS) *.bak
166
+ TARGET_SO_DIR_TIMESTAMP = $(TIMESTAMP_DIR)/.sitearchdir.time
167
+
168
+ all: $(DLLIB)
169
+ static: $(STATIC_LIB)
170
+ .PHONY: all install static install-so install-rb
171
+ .PHONY: clean clean-so clean-static clean-rb
172
+
173
+ clean-static::
174
+ clean-rb-default::
175
+ clean-rb::
176
+ clean-so::
177
+ clean: clean-so clean-static clean-rb-default clean-rb
178
+ -$(Q)$(RM_RF) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES) .*.time
179
+
180
+ distclean-rb-default::
181
+ distclean-rb::
182
+ distclean-so::
183
+ distclean-static::
184
+ distclean: clean distclean-so distclean-static distclean-rb-default distclean-rb
185
+ -$(Q)$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
186
+ -$(Q)$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
187
+ -$(Q)$(RMDIRS) $(DISTCLEANDIRS) 2> /dev/null || true
188
+
189
+ realclean: distclean
190
+ install: install-so install-rb
191
+
192
+ install-so: $(DLLIB) $(TARGET_SO_DIR_TIMESTAMP)
193
+ $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
194
+ clean-static::
195
+ -$(Q)$(RM) $(STATIC_LIB)
196
+ install-rb: pre-install-rb do-install-rb install-rb-default
197
+ install-rb-default: pre-install-rb-default do-install-rb-default
198
+ pre-install-rb: Makefile
199
+ pre-install-rb-default: Makefile
200
+ do-install-rb:
201
+ do-install-rb-default:
202
+ pre-install-rb-default:
203
+ @$(NULLCMD)
204
+ $(TARGET_SO_DIR_TIMESTAMP):
205
+ $(Q) $(MAKEDIRS) $(@D) $(RUBYARCHDIR)
206
+ $(Q) $(TOUCH) $@
207
+
208
+ site-install: site-install-so site-install-rb
209
+ site-install-so: install-so
210
+ site-install-rb: install-rb
211
+
212
+ .SUFFIXES: .c .m .cc .mm .cxx .cpp .o .S
213
+
214
+ .cc.o:
215
+ $(ECHO) compiling $(<)
216
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
217
+
218
+ .cc.S:
219
+ $(ECHO) translating $(<)
220
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
221
+
222
+ .mm.o:
223
+ $(ECHO) compiling $(<)
224
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
225
+
226
+ .mm.S:
227
+ $(ECHO) translating $(<)
228
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
229
+
230
+ .cxx.o:
231
+ $(ECHO) compiling $(<)
232
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
233
+
234
+ .cxx.S:
235
+ $(ECHO) translating $(<)
236
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
237
+
238
+ .cpp.o:
239
+ $(ECHO) compiling $(<)
240
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
241
+
242
+ .cpp.S:
243
+ $(ECHO) translating $(<)
244
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
245
+
246
+ .c.o:
247
+ $(ECHO) compiling $(<)
248
+ $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
249
+
250
+ .c.S:
251
+ $(ECHO) translating $(<)
252
+ $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
253
+
254
+ .m.o:
255
+ $(ECHO) compiling $(<)
256
+ $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
257
+
258
+ .m.S:
259
+ $(ECHO) translating $(<)
260
+ $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
261
+
262
+ $(TARGET_SO): $(OBJS) Makefile
263
+ $(ECHO) linking shared-object $(DLLIB)
264
+ -$(Q)$(RM) $(@)
265
+ $(Q) $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
266
+ $(Q) $(POSTLINK)
267
+
268
+
269
+
270
+ $(OBJS): $(HDRS) $(ruby_headers)
Binary file
data/ext/escape.o ADDED
Binary file
data/ext/extconf.h ADDED
@@ -0,0 +1,5 @@
1
+ #ifndef EXTCONF_H
2
+ #define EXTCONF_H
3
+ #define HAVE_RB_SYM2STR 1
4
+ #define HAVE_RB_STR_CAT_CSTR 1
5
+ #endif
data/ext/markup.o ADDED
Binary file
data/ext/query.o ADDED
Binary file
data/ext/tag.o ADDED
Binary file
data/ext/template.o ADDED
Binary file
data/ext/xrb/escape.c CHANGED
@@ -2,18 +2,6 @@
2
2
  #include "escape.h"
3
3
  #include <assert.h>
4
4
 
5
- inline static int XRB_Markup_is_markup(VALUE value) {
6
- if (RB_IMMEDIATE_P(value))
7
- return 0;
8
-
9
- // This is a short-cut:
10
- if (rb_class_of(value) == rb_XRB_MarkupString) {
11
- return 1;
12
- }
13
-
14
- return rb_funcall(value, id_is_a, 1, rb_XRB_Markup) == Qtrue;
15
- }
16
-
17
5
  VALUE XRB_MarkupString_raw(VALUE self, VALUE string) {
18
6
  string = rb_str_dup(string);
19
7
 
@@ -91,7 +79,7 @@ static inline VALUE XRB_Markup_append_buffer(VALUE buffer, const char * s, const
91
79
  }
92
80
 
93
81
  // Escape and append a string to the output buffer.
94
- VALUE XRB_Markup_append_string(VALUE buffer, VALUE string) {
82
+ static VALUE XRB_Markup_append_string(VALUE buffer, VALUE string) {
95
83
  const char * begin = RSTRING_PTR(string);
96
84
  const char * end = begin + RSTRING_LEN(string);
97
85
 
@@ -103,38 +91,29 @@ VALUE XRB_Markup_append_string(VALUE buffer, VALUE string) {
103
91
  return XRB_Markup_append_buffer(buffer, s, p, end);
104
92
  }
105
93
 
106
- VALUE XRB_Markup_append_slow(VALUE self, VALUE buffer, VALUE value) {
107
- if (value == Qnil) return Qnil;
108
-
109
- if (!XRB_Markup_is_markup(value)) {
110
- value = XRB_Markup_escape_string(Qnil, value);
111
- }
112
-
113
- rb_funcall(buffer, id_concat, 1, value);
94
+ // Append self to the output buffer efficiently, escaping special characters.
95
+ VALUE XRB_Markup_append_markup(VALUE self, VALUE output) {
96
+ if (self == Qnil) return output;
114
97
 
115
- return buffer;
116
- }
117
-
118
- VALUE XRB_Markup_append(VALUE self, VALUE buffer, VALUE value) {
119
- if (value == Qnil) return Qnil;
98
+ VALUE value = self;
120
99
 
121
- if (RB_TYPE_P(buffer, T_STRING)) {
122
- rb_str_modify(buffer);
123
- } else {
124
- return XRB_Markup_append_slow(self, buffer, value);
100
+ // Ensure value is a string:
101
+ if (rb_type(value) != T_STRING) {
102
+ value = rb_funcall(value, id_to_s, 0);
103
+ rb_string_value(&value);
125
104
  }
126
105
 
127
- if (XRB_Markup_is_markup(value)) {
128
- rb_str_append(buffer, value);
106
+ if (RB_TYPE_P(output, T_STRING)) {
107
+ // Fast path:
108
+ rb_str_modify_expand(output, RSTRING_LEN(value));
109
+ XRB_Markup_append_string(output, value);
129
110
  } else {
130
- if (rb_type(value) != T_STRING) {
131
- value = rb_funcall(value, id_to_s, 0);
132
- }
133
-
134
- XRB_Markup_append_string(buffer, value);
111
+ // Slow path (generates temporary strings):
112
+ value = XRB_Markup_escape_string(Qnil, value);
113
+ rb_funcall(output, id_concat, 1, value);
135
114
  }
136
115
 
137
- return buffer;
116
+ return output;
138
117
  }
139
118
 
140
119
  // Convert markup special characters to entities. May return the original string if no changes were made.
@@ -158,14 +137,8 @@ VALUE XRB_Markup_escape_string(VALUE self, VALUE string) {
158
137
  }
159
138
 
160
139
  void Init_XRB_escape(void) {
161
- rb_XRB_MarkupString = rb_define_class_under(rb_XRB, "MarkupString", rb_cString);
162
- rb_include_module(rb_XRB_MarkupString, rb_XRB_Markup);
163
-
164
- rb_undef_method(rb_class_of(rb_XRB_Markup), "escape_string");
165
- rb_define_singleton_method(rb_XRB_Markup, "escape_string", XRB_Markup_escape_string, 1);
166
-
167
- rb_undef_method(rb_class_of(rb_XRB_Markup), "append");
168
- rb_define_singleton_method(rb_XRB_Markup, "append", XRB_Markup_append, 2);
140
+ rb_undef_method(rb_XRB_Markup, "append_markup");
141
+ rb_define_method(rb_XRB_Markup, "append_markup", XRB_Markup_append_markup, 1);
169
142
 
170
143
  rb_undef_method(rb_class_of(rb_XRB_Markup), "raw");
171
144
  rb_define_singleton_method(rb_XRB_Markup, "raw", XRB_MarkupString_raw, 1);
data/ext/xrb/escape.h CHANGED
@@ -9,7 +9,7 @@ void Init_XRB_escape(void);
9
9
  VALUE XRB_MarkupString_raw(VALUE self, VALUE string);
10
10
 
11
11
  // Append any value to the output buffer efficiently, escaping entities as needed.
12
- VALUE XRB_Markup_append(VALUE self, VALUE buffer, VALUE value);
12
+ VALUE XRB_Markup_append_markup(VALUE self, VALUE buffer);
13
13
 
14
14
  // Escape any entities in the given string. If no entities were found, might return the original string.
15
15
  VALUE XRB_Markup_escape_string(VALUE self, VALUE string);
data/ext/xrb/tag.c CHANGED
@@ -50,7 +50,7 @@ inline static VALUE XRB_Tag_prefix_key(VALUE prefix, VALUE key) {
50
50
  return buffer;
51
51
  }
52
52
 
53
- VALUE XRB_Tag_append_attributes(VALUE self, VALUE buffer, VALUE attributes, VALUE prefix);
53
+ VALUE XRB_Tag_append_attributes_string(VALUE self, VALUE buffer, VALUE attributes, VALUE prefix);
54
54
 
55
55
  static void XRB_Tag_append_tag_attribute(VALUE buffer, VALUE key, VALUE value, VALUE prefix) {
56
56
  // We skip over attributes with nil value:
@@ -60,37 +60,37 @@ static void XRB_Tag_append_tag_attribute(VALUE buffer, VALUE key, VALUE value, V
60
60
  key = XRB_Tag_prefix_key(prefix, key);
61
61
 
62
62
  if (XRB_Tag_valid_attributes(value)) {
63
- XRB_Tag_append_attributes(Qnil, buffer, value, key);
63
+ XRB_Tag_append_attributes_string(Qnil, buffer, value, key);
64
64
  } else {
65
65
  rb_str_cat_cstr(buffer, " ");
66
66
  rb_str_append(buffer, key);
67
67
 
68
68
  if (value != Qtrue) {
69
69
  rb_str_cat_cstr(buffer, "=\"");
70
- XRB_Markup_append(Qnil, buffer, value);
70
+ XRB_Markup_append_markup(value, buffer);
71
71
  rb_str_cat_cstr(buffer, "\"");
72
72
  }
73
73
  }
74
74
  }
75
75
 
76
- typedef struct {
76
+ struct XRB_Tag_Append_Tag_Attribute_Argument {
77
77
  VALUE buffer;
78
78
  VALUE prefix;
79
- } XRB_Tag_Accumulation;
79
+ };
80
80
 
81
81
  static int XRB_Tag_append_tag_attribute_foreach(VALUE key, VALUE value, VALUE _argument) {
82
- XRB_Tag_Accumulation * argument = (XRB_Tag_Accumulation *)_argument;
82
+ struct XRB_Tag_Append_Tag_Attribute_Argument * argument = (struct XRB_Tag_Append_Tag_Attribute_Argument *)_argument;
83
83
 
84
84
  XRB_Tag_append_tag_attribute(argument->buffer, key, value, argument->prefix);
85
85
 
86
86
  return ST_CONTINUE;
87
87
  }
88
88
 
89
- VALUE XRB_Tag_append_attributes(VALUE self, VALUE buffer, VALUE attributes, VALUE prefix) {
89
+ VALUE XRB_Tag_append_attributes_string(VALUE self, VALUE buffer, VALUE attributes, VALUE prefix) {
90
90
  int type = rb_type(attributes);
91
91
 
92
92
  if (type == T_HASH) {
93
- XRB_Tag_Accumulation argument = {buffer, prefix};
93
+ struct XRB_Tag_Append_Tag_Attribute_Argument argument = {buffer, prefix};
94
94
  rb_hash_foreach(attributes, &XRB_Tag_append_tag_attribute_foreach, (VALUE)&argument);
95
95
  } else if (type == T_ARRAY) {
96
96
  long i;
@@ -114,13 +114,45 @@ VALUE XRB_Tag_append_attributes(VALUE self, VALUE buffer, VALUE attributes, VALU
114
114
  return Qnil;
115
115
  }
116
116
 
117
- VALUE XRB_Tag_append_tag(VALUE self, VALUE buffer, VALUE name, VALUE attributes, VALUE content) {
117
+ static size_t XRB_Tag_estimate_attributes_size(VALUE attributes, VALUE prefix) {
118
+ if (attributes == Qnil) return 0;
119
+
120
+ int type = rb_type(attributes);
121
+
122
+ if (type == T_HASH) {
123
+ return rb_hash_size(attributes) * 32;
124
+ } else if (type == T_ARRAY) {
125
+ return RARRAY_LEN(attributes) * 32;
126
+ }
127
+
128
+ return 0;
129
+ }
130
+
131
+ VALUE XRB_Tag_append_attributes(VALUE self, VALUE output, VALUE attributes, VALUE prefix) {
132
+ size_t estimated_size = XRB_Tag_estimate_attributes_size(attributes, prefix);
133
+
134
+ // If there are no attributes, we return early:
135
+ if (estimated_size == 0) return Qnil;
136
+
137
+ if (rb_type(output) == T_STRING) {
138
+ rb_str_modify_expand(output, estimated_size);
139
+ XRB_Tag_append_attributes_string(self, output, attributes, prefix);
140
+ } else {
141
+ VALUE buffer = rb_str_buf_new(estimated_size);
142
+ XRB_Tag_append_attributes_string(self, buffer, attributes, prefix);
143
+ rb_funcall(output, id_concat, 1, buffer);
144
+ }
145
+
146
+ return Qnil;
147
+ }
148
+
149
+ VALUE XRB_Tag_append_tag_string(VALUE self, VALUE buffer, VALUE name, VALUE attributes, VALUE content) {
118
150
  StringValue(name);
119
151
 
120
152
  rb_str_cat_cstr(buffer, "<");
121
153
  rb_str_buf_append(buffer, name);
122
154
 
123
- XRB_Tag_append_attributes(self, buffer, attributes, Qnil);
155
+ XRB_Tag_append_attributes_string(self, buffer, attributes, Qnil);
124
156
 
125
157
  if (content == Qnil || content == Qfalse) {
126
158
  rb_str_cat_cstr(buffer, "/>");
@@ -128,7 +160,7 @@ VALUE XRB_Tag_append_tag(VALUE self, VALUE buffer, VALUE name, VALUE attributes,
128
160
  rb_str_cat_cstr(buffer, ">");
129
161
 
130
162
  if (content != Qtrue) {
131
- XRB_Markup_append(self, buffer, content);
163
+ XRB_Markup_append_markup(content, buffer);
132
164
  }
133
165
 
134
166
  rb_str_cat_cstr(buffer, "</");
@@ -139,30 +171,46 @@ VALUE XRB_Tag_append_tag(VALUE self, VALUE buffer, VALUE name, VALUE attributes,
139
171
  return Qnil;
140
172
  }
141
173
 
142
- VALUE XRB_Tag_format_tag(VALUE self, VALUE name, VALUE attributes, VALUE content) {
143
- rb_encoding *encoding = rb_enc_get(name);
174
+ static size_t XRB_Tag_estimate_size(VALUE name, VALUE attributes, VALUE content) {
175
+ size_t estimated_size = (RSTRING_LEN(name) * 2) + XRB_Tag_estimate_attributes_size(attributes, Qnil) + 5;
144
176
 
145
- VALUE buffer = rb_enc_str_new(0, 0, encoding);
146
- rb_str_modify_expand(buffer, 256);
147
-
148
- XRB_Tag_append_tag(self, buffer, name, attributes, content);
177
+ if (rb_type(content) == T_STRING) {
178
+ estimated_size += RSTRING_LEN(content);
179
+ }
149
180
 
150
- return buffer;
181
+ return estimated_size;
151
182
  }
152
183
 
153
- VALUE XRB_Tag_write_opening_tag(VALUE self, VALUE buffer) {
154
- VALUE name = rb_struct_getmember(self, id_name);
155
- VALUE attributes = rb_struct_getmember(self, id_attributes);
156
- VALUE closed = rb_struct_getmember(self, id_closed);
184
+ VALUE XRB_Tag_append_tag(VALUE self, VALUE output, VALUE name, VALUE attributes, VALUE content) {
185
+ size_t estimated_size = XRB_Tag_estimate_size(name, attributes, content);
186
+
187
+ if (rb_type(output) == T_STRING) {
188
+ rb_str_modify_expand(output, estimated_size);
189
+ XRB_Tag_append_tag_string(self, output, name, attributes, content);
190
+ } else {
191
+ VALUE buffer = rb_str_buf_new(estimated_size);
192
+ XRB_Tag_append_tag_string(self, buffer, name, attributes, content);
193
+ rb_funcall(output, id_concat, 1, buffer);
194
+ }
195
+
196
+ return Qnil;
197
+ }
157
198
 
158
- StringValue(name);
199
+ VALUE XRB_Tag_format_tag(VALUE self, VALUE name, VALUE attributes, VALUE content) {
200
+ size_t estimated_size = XRB_Tag_estimate_size(name, attributes, content);
159
201
 
160
- rb_str_modify_expand(buffer, RSTRING_LEN(name) + 256);
202
+ VALUE buffer = rb_str_buf_new(estimated_size);
161
203
 
204
+ XRB_Tag_append_tag_string(self, buffer, name, attributes, content);
205
+
206
+ return buffer;
207
+ }
208
+
209
+ VALUE XRB_Tag_write_opening_tag_string(VALUE self, VALUE buffer, VALUE name, VALUE attributes, VALUE closed) {
162
210
  rb_str_cat_cstr(buffer, "<");
163
211
  rb_str_buf_append(buffer, name);
164
212
 
165
- XRB_Tag_append_attributes(self, buffer, attributes, Qnil);
213
+ XRB_Tag_append_attributes_string(self, buffer, attributes, Qnil);
166
214
 
167
215
  if (closed == Qtrue) {
168
216
  rb_str_cat_cstr(buffer, "/>");
@@ -173,17 +221,52 @@ VALUE XRB_Tag_write_opening_tag(VALUE self, VALUE buffer) {
173
221
  return Qnil;
174
222
  }
175
223
 
176
- VALUE XRB_Tag_write_closing_tag(VALUE self, VALUE buffer) {
224
+ VALUE XRB_Tag_write_opening_tag(VALUE self, VALUE output) {
177
225
  VALUE name = rb_struct_getmember(self, id_name);
178
-
179
226
  StringValue(name);
180
227
 
181
- rb_str_modify_expand(buffer, RSTRING_LEN(name) + 3);
228
+ VALUE attributes = rb_struct_getmember(self, id_attributes);
229
+ VALUE closed = rb_struct_getmember(self, id_closed);
230
+
231
+ // The size of the tag name + attributes + at most 3 characters for the closing tag symbols.
232
+ size_t estimated_size = RSTRING_LEN(name) + XRB_Tag_estimate_attributes_size(attributes, Qnil) + 3;
233
+
234
+ if (rb_type(output) == T_STRING) {
235
+ rb_str_modify_expand(output, estimated_size);
236
+ XRB_Tag_write_opening_tag_string(self, output, name, attributes, closed);
237
+ } else {
238
+ VALUE buffer = rb_str_buf_new(estimated_size);
239
+ XRB_Tag_write_opening_tag_string(self, buffer, name, attributes, closed);
240
+ rb_funcall(output, id_concat, 1, buffer);
241
+ }
182
242
 
243
+ return Qnil;
244
+ }
245
+
246
+ VALUE XRB_Tag_write_closing_tag_string(VALUE self, VALUE buffer, VALUE name) {
183
247
  rb_str_cat_cstr(buffer, "</");
184
248
  rb_str_buf_append(buffer, name);
185
249
  rb_str_cat_cstr(buffer, ">");
186
250
 
251
+ return buffer;
252
+ }
253
+
254
+ VALUE XRB_Tag_write_closing_tag(VALUE self, VALUE output) {
255
+ VALUE name = rb_struct_getmember(self, id_name);
256
+ StringValue(name);
257
+
258
+ // The size of the tag name + 3 characters for the closing tag symbols.
259
+ size_t estimated_size = RSTRING_LEN(name) + 3;
260
+
261
+ if (rb_type(output) == T_STRING) {
262
+ rb_str_modify_expand(output, estimated_size);
263
+ XRB_Tag_write_closing_tag_string(self, output, name);
264
+ } else {
265
+ VALUE buffer = rb_str_buf_new(estimated_size);
266
+ XRB_Tag_write_closing_tag_string(self, buffer, name);
267
+ rb_funcall(output, id_concat, 1, buffer);
268
+ }
269
+
187
270
  return Qnil;
188
271
  }
189
272
 
data/ext/xrb/xrb.c CHANGED
@@ -51,6 +51,7 @@ void Init_XRB_Extension(void) {
51
51
 
52
52
  rb_XRB = rb_define_module("XRB");
53
53
  rb_XRB_Markup = rb_define_module_under(rb_XRB, "Markup");
54
+ rb_XRB_MarkupString = rb_define_class_under(rb_XRB, "MarkupString", rb_cString);
54
55
  rb_XRB_Native = rb_define_module_under(rb_XRB, "Native");
55
56
 
56
57
  Init_XRB_escape();
data/ext/xrb.o ADDED
Binary file
data/lib/xrb/builder.rb CHANGED
@@ -9,8 +9,6 @@ require_relative 'tag'
9
9
  module XRB
10
10
  # Build markup quickly and efficiently.
11
11
  class Builder
12
- include Markup
13
-
14
12
  INDENT = "\t"
15
13
 
16
14
  class Fragment
@@ -19,18 +17,20 @@ module XRB
19
17
  @builder = nil
20
18
  end
21
19
 
22
- def call(builder)
20
+ def append_markup(output)
21
+ builder = Builder.new(output)
22
+
23
+ self.build_markup(builder)
24
+
25
+ return builder.output
26
+ end
27
+
28
+ def build_markup(builder)
23
29
  @block.call(builder)
24
30
  end
25
31
 
26
32
  def to_s
27
- unless @builder
28
- @builder = Builder.new
29
-
30
- self.call(@builder)
31
- end
32
-
33
- return @builder.to_s
33
+ self.append_markup(nil)
34
34
  end
35
35
 
36
36
  def == other
@@ -84,6 +84,10 @@ module XRB
84
84
  @children = [0]
85
85
  end
86
86
 
87
+ def build_markup(builder)
88
+ builder.append(@output)
89
+ end
90
+
87
91
  attr :output
88
92
 
89
93
  def encoding
@@ -149,7 +153,7 @@ module XRB
149
153
  @output << indentation
150
154
  end
151
155
 
152
- Markup.append(@output, content)
156
+ content.build_markup(self)
153
157
 
154
158
  if @indent
155
159
  @output << "\n"
@@ -161,15 +165,7 @@ module XRB
161
165
  end
162
166
 
163
167
  def <<(content)
164
- return unless content
165
-
166
- if content.is_a?(Fragment)
167
- inline! do
168
- content.call(self)
169
- end
170
- else
171
- Markup.append(@output, content)
172
- end
168
+ content&.build_markup(self)
173
169
  end
174
170
 
175
171
  # Append pre-existing markup:
data/lib/xrb/markup.rb CHANGED
@@ -8,32 +8,33 @@ require 'cgi'
8
8
  module XRB
9
9
  # A wrapper which indicates that `value` can be appended to the output buffer without any changes.
10
10
  module Markup
11
- # Converts special characters `<`, `>`, `&`, and `"` into their equivalent entities.
12
- # @return [String] May return the original string if no changes were made.
13
- def self.escape_string(string)
14
- CGI.escape_html(string)
11
+ def self.raw(string)
12
+ MarkupString.raw(string)
15
13
  end
16
14
 
17
- # Appends a string to the output buffer, escaping if if necessary.
18
- def self.append(buffer, value)
19
- if value.is_a? Markup
20
- buffer << value
21
- elsif value
22
- buffer << self.escape_string(value.to_s)
23
- end
15
+ def self.append(output, value)
16
+ value.append_markup(output)
17
+ end
18
+
19
+ def append_markup(output)
20
+ output << ::CGI.escape_html(self.to_s)
21
+ end
22
+
23
+ def build_markup(builder)
24
+ append_markup(builder.output)
24
25
  end
25
26
  end
26
27
 
28
+ ::Object.prepend(Markup)
29
+
27
30
  # Initialized from text which is escaped to use HTML entities.
28
31
  class MarkupString < String
29
- include Markup
30
-
31
32
  # @param string [String] the string value itself.
32
33
  # @param escape [Boolean] whether or not to escape the string.
33
34
  def initialize(string = nil, escape = true)
34
35
  if string
35
36
  if escape
36
- string = Markup.escape_string(string)
37
+ string = ::CGI.escape_html(string)
37
38
  end
38
39
 
39
40
  super(string)
@@ -52,6 +53,10 @@ module XRB
52
53
  def html_safe?
53
54
  true
54
55
  end
56
+
57
+ def append_markup(output)
58
+ output << self
59
+ end
55
60
  end
56
61
 
57
62
  module Script
data/lib/xrb/tag.rb CHANGED
@@ -8,8 +8,6 @@ require_relative 'markup'
8
8
  module XRB
9
9
  # This represents an individual SGML tag, e.g. <a>, </a> or <a />, with attributes. Attribute values must be escaped.
10
10
  Tag = Struct.new(:name, :closed, :attributes) do
11
- include XRB::Markup
12
-
13
11
  def self.split(qualified_name)
14
12
  if i = qualified_name.index(':')
15
13
  return qualified_name.slice(0...i), qualified_name.slice(i+1..-1)
@@ -80,7 +78,7 @@ module XRB
80
78
  else
81
79
  buffer << '>'
82
80
  unless content == true
83
- Markup.append(buffer, content)
81
+ content.append_markup(buffer)
84
82
  end
85
83
  buffer << '</' << name.to_s << '>'
86
84
  end
@@ -108,7 +106,7 @@ module XRB
108
106
  buffer << ' ' << attribute_key.to_s
109
107
  else
110
108
  buffer << ' ' << attribute_key.to_s << '="'
111
- Markup.append(buffer, value)
109
+ value.append_markup(buffer)
112
110
  buffer << '"'
113
111
  end
114
112
  end
data/lib/xrb/version.rb CHANGED
@@ -4,5 +4,5 @@
4
4
  # Copyright, 2012-2024, by Samuel Williams.
5
5
 
6
6
  module XRB
7
- VERSION = "0.8.0"
7
+ VERSION = "0.10.0"
8
8
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xrb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -40,7 +40,7 @@ cert_chain:
40
40
  Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
41
41
  voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
42
42
  -----END CERTIFICATE-----
43
- date: 2024-10-24 00:00:00.000000000 Z
43
+ date: 2024-10-27 00:00:00.000000000 Z
44
44
  dependencies: []
45
45
  description:
46
46
  email:
@@ -51,7 +51,16 @@ extra_rdoc_files: []
51
51
  files:
52
52
  - bake/xrb/entities.rb
53
53
  - bake/xrb/parsers.rb
54
+ - ext/Makefile
55
+ - ext/XRB_Extension.bundle
56
+ - ext/escape.o
57
+ - ext/extconf.h
54
58
  - ext/extconf.rb
59
+ - ext/markup.o
60
+ - ext/query.o
61
+ - ext/tag.o
62
+ - ext/template.o
63
+ - ext/xrb.o
55
64
  - ext/xrb/escape.c
56
65
  - ext/xrb/escape.h
57
66
  - ext/xrb/markup.c
metadata.gz.sig CHANGED
@@ -1,2 +1,2 @@
1
- #1�{�
2
- ^�E�K�� H��\��:�a��F鿆Ȑ
1
+ ϑb��5���Uk,�Q{�I'���D=��AZS�L�F��d;��o֗�F��!޳
2
+ ����Z���ķǖlT S�>ǃ���d�}ps�����p�b�G1�dҧ������cVB�*�܎��e Q���\��L(K��s��Vdjh��4���yFfՙ�k��€`[����k��i�=1�����3x����F{��Dh%���.�