ray 0.0.1 → 0.1.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (188) hide show
  1. data/.gemtest +0 -0
  2. data/.yardopts +4 -0
  3. data/README.md +17 -21
  4. data/Rakefile +18 -139
  5. data/VERSION +1 -1
  6. data/ext/audio.cpp +723 -0
  7. data/ext/{color.c → color.cpp} +25 -13
  8. data/ext/drawable.cpp +91 -0
  9. data/ext/event.cpp +460 -0
  10. data/ext/extconf.rb +5 -104
  11. data/ext/font.cpp +190 -0
  12. data/ext/image.cpp +733 -0
  13. data/ext/input.cpp +74 -0
  14. data/ext/ray.cpp +168 -0
  15. data/ext/ray.hpp +356 -0
  16. data/ext/{rect.c → rect.cpp} +51 -37
  17. data/ext/shader.cpp +169 -0
  18. data/ext/shape.cpp +409 -0
  19. data/ext/sprite.cpp +306 -0
  20. data/ext/text.cpp +181 -0
  21. data/ext/vector.cpp +215 -0
  22. data/guide.md +619 -0
  23. data/lib/ray/audio.rb +0 -41
  24. data/lib/ray/color.rb +32 -10
  25. data/lib/ray/drawable.rb +16 -0
  26. data/lib/ray/dsl/event_listener.rb +25 -2
  27. data/lib/ray/dsl/event_runner.rb +33 -5
  28. data/lib/ray/dsl/event_translator.rb +66 -30
  29. data/lib/ray/dsl/handler.rb +3 -2
  30. data/lib/ray/dsl/matcher.rb +58 -14
  31. data/lib/ray/font.rb +38 -96
  32. data/lib/ray/font_set.rb +8 -8
  33. data/lib/ray/game.rb +87 -66
  34. data/lib/ray/helper.rb +105 -10
  35. data/lib/ray/image.rb +150 -24
  36. data/lib/ray/image_set.rb +3 -1
  37. data/lib/ray/input.rb +10 -0
  38. data/lib/ray/music_set.rb +5 -3
  39. data/lib/ray/ray.rb +21 -9
  40. data/lib/ray/rect.rb +48 -7
  41. data/lib/ray/rmagick.rb +41 -0
  42. data/lib/ray/scene.rb +99 -43
  43. data/lib/ray/scene_list.rb +67 -0
  44. data/lib/ray/shape.rb +132 -0
  45. data/lib/ray/sound_set.rb +4 -2
  46. data/lib/ray/sprite.rb +49 -111
  47. data/lib/ray/text.rb +101 -0
  48. data/lib/ray/text_helper.rb +37 -0
  49. data/lib/ray/turtle.rb +215 -0
  50. data/lib/ray/vector.rb +226 -0
  51. data/samples/audio/spacial.rb +44 -0
  52. data/samples/hello_world/hello.rb +9 -13
  53. data/samples/hello_world/hello_dsl.rb +8 -12
  54. data/samples/hello_world/text.rb +15 -0
  55. data/samples/opengl/binding.rb +38 -0
  56. data/samples/opengl/image.rb +32 -0
  57. data/samples/opengl/opengl.rb +34 -0
  58. data/samples/opengl/shader.rb +42 -0
  59. data/samples/pong/pong.rb +14 -10
  60. data/samples/run_scene.rb +53 -0
  61. data/samples/shaders/scene.rb +40 -0
  62. data/samples/shaders/shaders.rb +42 -0
  63. data/samples/shaders/shape.rb +34 -0
  64. data/samples/sokoban/sokoban.rb +18 -18
  65. data/samples/test/actual_scene.rb +41 -0
  66. data/samples/test/scene_riot.rb +39 -0
  67. data/samples/test/scene_spec.rb +32 -0
  68. data/samples/test/scene_test_unit.rb +25 -0
  69. data/samples/turtle/byzantium.rb +45 -0
  70. data/samples/turtle/hilbert.rb +48 -0
  71. data/samples/turtle/koch.rb +55 -0
  72. data/samples/turtle/mandala.rb +61 -0
  73. data/samples/turtle/tree.rb +57 -0
  74. data/test/audio_test.rb +69 -0
  75. data/test/color_test.rb +77 -0
  76. data/test/drawable_test.rb +19 -0
  77. data/test/dsl_test.rb +93 -0
  78. data/test/font_test.rb +57 -0
  79. data/test/helpers.rb +94 -0
  80. data/test/image_test.rb +82 -0
  81. data/test/ray_test.rb +25 -0
  82. data/test/rect_test.rb +121 -0
  83. data/{spec → test}/res/VeraMono.ttf +0 -0
  84. data/{spec → test}/res/aqua.bmp +0 -0
  85. data/{spec → test}/res/aqua.png +0 -0
  86. data/{spec → test}/res/aqua2.bmp +0 -0
  87. data/{spec → test}/res/not_a_jpeg.jpeg +0 -0
  88. data/{spec → test}/res/pop.wav +0 -0
  89. data/test/resource_set_test.rb +99 -0
  90. data/test/run_all.rb +7 -0
  91. data/test/shape_test.rb +101 -0
  92. data/test/sprite_test.rb +89 -0
  93. data/test/text_test.rb +78 -0
  94. data/test/turtle_test.rb +176 -0
  95. data/test/vector_test.rb +111 -0
  96. data/yard_ext.rb +0 -28
  97. metadata +95 -139
  98. data/.gitignore +0 -23
  99. data/.gitmodules +0 -3
  100. data/.rspec +0 -3
  101. data/ext/audio.c +0 -473
  102. data/ext/event.c +0 -557
  103. data/ext/font.c +0 -287
  104. data/ext/image.c +0 -933
  105. data/ext/joystick.c +0 -145
  106. data/ext/ray.c +0 -489
  107. data/ext/ray.h +0 -245
  108. data/ext/ray_osx.m +0 -161
  109. data/lib/ray/joystick.rb +0 -30
  110. data/psp/SDL_psp_main.c +0 -84
  111. data/psp/bigdecimal/README +0 -60
  112. data/psp/bigdecimal/bigdecimal.c +0 -4697
  113. data/psp/bigdecimal/bigdecimal.h +0 -216
  114. data/psp/bigdecimal/lib/bigdecimal/jacobian.rb +0 -85
  115. data/psp/bigdecimal/lib/bigdecimal/ludcmp.rb +0 -84
  116. data/psp/bigdecimal/lib/bigdecimal/math.rb +0 -235
  117. data/psp/bigdecimal/lib/bigdecimal/newton.rb +0 -77
  118. data/psp/bigdecimal/lib/bigdecimal/util.rb +0 -65
  119. data/psp/digest/bubblebabble/bubblebabble.c +0 -142
  120. data/psp/digest/defs.h +0 -20
  121. data/psp/digest/digest.c +0 -643
  122. data/psp/digest/digest.h +0 -32
  123. data/psp/digest/lib/digest.rb +0 -50
  124. data/psp/digest/lib/md5.rb +0 -27
  125. data/psp/digest/lib/sha1.rb +0 -27
  126. data/psp/digest/md5/md5.c +0 -420
  127. data/psp/digest/md5/md5.h +0 -80
  128. data/psp/digest/md5/md5init.c +0 -40
  129. data/psp/digest/rmd160/rmd160.c +0 -457
  130. data/psp/digest/rmd160/rmd160.h +0 -56
  131. data/psp/digest/rmd160/rmd160init.c +0 -40
  132. data/psp/digest/sha1/sha1.c +0 -269
  133. data/psp/digest/sha1/sha1.h +0 -39
  134. data/psp/digest/sha1/sha1init.c +0 -40
  135. data/psp/digest/sha2/lib/sha2.rb +0 -73
  136. data/psp/digest/sha2/sha2.c +0 -919
  137. data/psp/digest/sha2/sha2.h +0 -109
  138. data/psp/digest/sha2/sha2init.c +0 -52
  139. data/psp/enumerator/enumerator.c +0 -298
  140. data/psp/etc/etc.c +0 -559
  141. data/psp/ext.c +0 -289
  142. data/psp/fcntl/fcntl.c +0 -187
  143. data/psp/lib/rbconfig.rb +0 -178
  144. data/psp/nkf/lib/kconv.rb +0 -367
  145. data/psp/nkf/nkf-utf8/config.h +0 -88
  146. data/psp/nkf/nkf-utf8/nkf.c +0 -6040
  147. data/psp/nkf/nkf-utf8/utf8tbl.c +0 -8500
  148. data/psp/nkf/nkf-utf8/utf8tbl.h +0 -34
  149. data/psp/nkf/nkf.c +0 -654
  150. data/psp/socket/addrinfo.h +0 -173
  151. data/psp/socket/getaddrinfo.c +0 -676
  152. data/psp/socket/getnameinfo.c +0 -270
  153. data/psp/socket/pspsocket.c +0 -71
  154. data/psp/socket/pspsocket.h +0 -28
  155. data/psp/socket/socket.c +0 -4662
  156. data/psp/socket/sockport.h +0 -76
  157. data/psp/stringio/stringio.c +0 -1306
  158. data/psp/strscan/strscan.c +0 -1320
  159. data/psp/syck/bytecode.c +0 -1166
  160. data/psp/syck/emitter.c +0 -1242
  161. data/psp/syck/gram.c +0 -1894
  162. data/psp/syck/gram.h +0 -79
  163. data/psp/syck/handler.c +0 -174
  164. data/psp/syck/implicit.c +0 -2990
  165. data/psp/syck/node.c +0 -408
  166. data/psp/syck/rubyext.c +0 -2367
  167. data/psp/syck/syck.c +0 -504
  168. data/psp/syck/syck.h +0 -456
  169. data/psp/syck/token.c +0 -2725
  170. data/psp/syck/yaml2byte.c +0 -257
  171. data/psp/syck/yamlbyte.h +0 -170
  172. data/psp/thread/thread.c +0 -1175
  173. data/psp/zlib/zlib.c +0 -3547
  174. data/script.rb +0 -10
  175. data/spec/ray/audio_spec.rb +0 -146
  176. data/spec/ray/color_spec.rb +0 -57
  177. data/spec/ray/event_spec.rb +0 -80
  178. data/spec/ray/font_spec.rb +0 -93
  179. data/spec/ray/image_set_spec.rb +0 -48
  180. data/spec/ray/image_spec.rb +0 -162
  181. data/spec/ray/joystick_spec.rb +0 -21
  182. data/spec/ray/matcher_spec.rb +0 -50
  183. data/spec/ray/ray_spec.rb +0 -88
  184. data/spec/ray/rect_spec.rb +0 -154
  185. data/spec/ray/resource_set_spec.rb +0 -105
  186. data/spec/ray/sprite_spec.rb +0 -163
  187. data/spec/spec.opts +0 -4
  188. data/spec/spec_helper.rb +0 -8
@@ -1,1320 +0,0 @@
1
- /*
2
- $Id: strscan.c 11708 2007-02-12 23:01:19Z shyouhei $
3
-
4
- Copyright (c) 1999-2006 Minero Aoki
5
-
6
- This program is free software.
7
- You can distribute/modify this program under the terms of
8
- the Ruby License. For details, see the file COPYING.
9
- */
10
-
11
- #include <ruby/ruby.h>
12
- #include <ruby/re.h>
13
-
14
- #define STRSCAN_VERSION "0.7.0"
15
-
16
- /* =======================================================================
17
- Data Type Definitions
18
- ======================================================================= */
19
-
20
- static VALUE StringScanner;
21
- static VALUE ScanError;
22
-
23
- struct strscanner
24
- {
25
- /* multi-purpose flags */
26
- unsigned long flags;
27
- #define FLAG_MATCHED (1 << 0)
28
-
29
- /* the string to scan */
30
- VALUE str;
31
-
32
- /* scan pointers */
33
- long prev; /* legal only when MATCHED_P(s) */
34
- long curr; /* always legal */
35
-
36
- /* the regexp register; legal only when MATCHED_P(s) */
37
- struct re_registers regs;
38
- };
39
-
40
- #define MATCHED_P(s) ((s)->flags & FLAG_MATCHED)
41
- #define MATCHED(s) (s)->flags |= FLAG_MATCHED
42
- #define CLEAR_MATCH_STATUS(s) (s)->flags &= ~FLAG_MATCHED
43
-
44
- #define S_PBEG(s) (RSTRING((s)->str)->ptr)
45
- #define S_LEN(s) (RSTRING((s)->str)->len)
46
- #define S_PEND(s) (S_PBEG(s) + S_LEN(s))
47
- #define CURPTR(s) (S_PBEG(s) + (s)->curr)
48
- #define S_RESTLEN(s) (S_LEN(s) - (s)->curr)
49
-
50
- #define EOS_P(s) ((s)->curr >= RSTRING(p->str)->len)
51
-
52
- #define GET_SCANNER(obj,var) do {\
53
- Data_Get_Struct(obj, struct strscanner, var);\
54
- if (NIL_P(var->str)) rb_raise(rb_eArgError, "uninitialized StringScanner object");\
55
- } while (0)
56
-
57
- /* =======================================================================
58
- Function Prototypes
59
- ======================================================================= */
60
-
61
- static VALUE infect _((VALUE str, struct strscanner *p));
62
- static VALUE extract_range _((struct strscanner *p, long beg_i, long end_i));
63
- static VALUE extract_beg_len _((struct strscanner *p, long beg_i, long len));
64
-
65
- static void check_strscan _((VALUE obj));
66
- static void strscan_mark _((struct strscanner *p));
67
- static void strscan_free _((struct strscanner *p));
68
- static VALUE strscan_s_allocate _((VALUE klass));
69
- static VALUE strscan_initialize _((int argc, VALUE *argv, VALUE self));
70
- static VALUE strscan_init_copy _((VALUE vself, VALUE vorig));
71
-
72
- static VALUE strscan_s_mustc _((VALUE self));
73
- static VALUE strscan_terminate _((VALUE self));
74
- static VALUE strscan_clear _((VALUE self));
75
- static VALUE strscan_get_string _((VALUE self));
76
- static VALUE strscan_set_string _((VALUE self, VALUE str));
77
- static VALUE strscan_concat _((VALUE self, VALUE str));
78
- static VALUE strscan_get_pos _((VALUE self));
79
- static VALUE strscan_set_pos _((VALUE self, VALUE pos));
80
- static VALUE strscan_do_scan _((VALUE self, VALUE regex,
81
- int succptr, int getstr, int headonly));
82
- static VALUE strscan_scan _((VALUE self, VALUE re));
83
- static VALUE strscan_match_p _((VALUE self, VALUE re));
84
- static VALUE strscan_skip _((VALUE self, VALUE re));
85
- static VALUE strscan_check _((VALUE self, VALUE re));
86
- static VALUE strscan_scan_full _((VALUE self, VALUE re,
87
- VALUE succp, VALUE getp));
88
- static VALUE strscan_scan_until _((VALUE self, VALUE re));
89
- static VALUE strscan_skip_until _((VALUE self, VALUE re));
90
- static VALUE strscan_check_until _((VALUE self, VALUE re));
91
- static VALUE strscan_search_full _((VALUE self, VALUE re,
92
- VALUE succp, VALUE getp));
93
- static void adjust_registers_to_matched _((struct strscanner *p));
94
- static VALUE strscan_getch _((VALUE self));
95
- static VALUE strscan_get_byte _((VALUE self));
96
- static VALUE strscan_getbyte _((VALUE self));
97
- static VALUE strscan_peek _((VALUE self, VALUE len));
98
- static VALUE strscan_peep _((VALUE self, VALUE len));
99
- static VALUE strscan_unscan _((VALUE self));
100
- static VALUE strscan_bol_p _((VALUE self));
101
- static VALUE strscan_eos_p _((VALUE self));
102
- static VALUE strscan_empty_p _((VALUE self));
103
- static VALUE strscan_rest_p _((VALUE self));
104
- static VALUE strscan_matched_p _((VALUE self));
105
- static VALUE strscan_matched _((VALUE self));
106
- static VALUE strscan_matched_size _((VALUE self));
107
- static VALUE strscan_aref _((VALUE self, VALUE idx));
108
- static VALUE strscan_pre_match _((VALUE self));
109
- static VALUE strscan_post_match _((VALUE self));
110
- static VALUE strscan_rest _((VALUE self));
111
- static VALUE strscan_rest_size _((VALUE self));
112
-
113
- static VALUE strscan_inspect _((VALUE self));
114
- static VALUE inspect1 _((struct strscanner *p));
115
- static VALUE inspect2 _((struct strscanner *p));
116
-
117
- /* =======================================================================
118
- Utils
119
- ======================================================================= */
120
-
121
- static VALUE
122
- infect(VALUE str, struct strscanner *p)
123
- {
124
- OBJ_INFECT(str, p->str);
125
- return str;
126
- }
127
-
128
- static VALUE
129
- extract_range(struct strscanner *p, long beg_i, long end_i)
130
- {
131
- if (beg_i > S_LEN(p)) return Qnil;
132
- if (end_i > S_LEN(p))
133
- end_i = S_LEN(p);
134
- return infect(rb_str_new(S_PBEG(p) + beg_i, end_i - beg_i), p);
135
- }
136
-
137
- static VALUE
138
- extract_beg_len(struct strscanner *p, long beg_i, long len)
139
- {
140
- if (beg_i > S_LEN(p)) return Qnil;
141
- if (beg_i + len > S_LEN(p))
142
- len = S_LEN(p) - beg_i;
143
- return infect(rb_str_new(S_PBEG(p) + beg_i, len), p);
144
- }
145
-
146
- /* =======================================================================
147
- Constructor
148
- ======================================================================= */
149
-
150
- static void
151
- strscan_mark(struct strscanner *p)
152
- {
153
- rb_gc_mark(p->str);
154
- }
155
-
156
- static void
157
- strscan_free(struct strscanner *p)
158
- {
159
- re_free_registers(&(p->regs));
160
- free(p);
161
- }
162
-
163
- static VALUE
164
- strscan_s_allocate(VALUE klass)
165
- {
166
- struct strscanner *p;
167
-
168
- p = ALLOC(struct strscanner);
169
- MEMZERO(p, struct strscanner, 1);
170
- CLEAR_MATCH_STATUS(p);
171
- MEMZERO(&(p->regs), struct re_registers, 1);
172
- p->str = Qnil;
173
- return Data_Wrap_Struct(klass, strscan_mark, strscan_free, p);
174
- }
175
-
176
- /*
177
- * call-seq: StringScanner.new(string, dup = false)
178
- *
179
- * Creates a new StringScanner object to scan over the given +string+.
180
- * +dup+ argument is obsolete and not used now.
181
- */
182
- static VALUE
183
- strscan_initialize(int argc, VALUE *argv, VALUE self)
184
- {
185
- struct strscanner *p;
186
- VALUE str, need_dup;
187
-
188
- Data_Get_Struct(self, struct strscanner, p);
189
- rb_scan_args(argc, argv, "11", &str, &need_dup);
190
- StringValue(str);
191
- p->str = str;
192
-
193
- return self;
194
- }
195
-
196
- static void
197
- check_strscan(VALUE obj)
198
- {
199
- if (TYPE(obj) != T_DATA || RDATA(obj)->dmark != (RUBY_DATA_FUNC)strscan_mark) {
200
- rb_raise(rb_eTypeError,
201
- "wrong argument type %s (expected StringScanner)",
202
- rb_obj_classname(obj));
203
- }
204
- }
205
-
206
- /*
207
- * call-seq:
208
- * dup
209
- * clone
210
- *
211
- * Duplicates a StringScanner object.
212
- */
213
- static VALUE
214
- strscan_init_copy(VALUE vself, VALUE vorig)
215
- {
216
- struct strscanner *self, *orig;
217
-
218
- Data_Get_Struct(vself, struct strscanner, self);
219
- check_strscan(vorig);
220
- Data_Get_Struct(vorig, struct strscanner, orig);
221
- if (self != orig) {
222
- self->flags = orig->flags;
223
- self->str = orig->str;
224
- self->prev = orig->prev;
225
- self->curr = orig->curr;
226
- re_copy_registers(&self->regs, &orig->regs);
227
- }
228
- return vself;
229
- }
230
-
231
- /* =======================================================================
232
- Instance Methods
233
- ======================================================================= */
234
-
235
- /*
236
- * call-seq: StringScanner.must_C_version
237
- *
238
- * This method is defined for backward compatibility.
239
- */
240
- static VALUE
241
- strscan_s_mustc(VALUE self)
242
- {
243
- return self;
244
- }
245
-
246
- /*
247
- * Reset the scan pointer (index 0) and clear matching data.
248
- */
249
- static VALUE
250
- strscan_reset(VALUE self)
251
- {
252
- struct strscanner *p;
253
-
254
- GET_SCANNER(self, p);
255
- p->curr = 0;
256
- CLEAR_MATCH_STATUS(p);
257
- return self;
258
- }
259
-
260
- /*
261
- * call-seq:
262
- * terminate
263
- * clear
264
- *
265
- * Set the scan pointer to the end of the string and clear matching data.
266
- */
267
- static VALUE
268
- strscan_terminate(VALUE self)
269
- {
270
- struct strscanner *p;
271
-
272
- GET_SCANNER(self, p);
273
- p->curr = S_LEN(p);
274
- CLEAR_MATCH_STATUS(p);
275
- return self;
276
- }
277
-
278
- /*
279
- * Equivalent to #terminate.
280
- * This method is obsolete; use #terminate instead.
281
- */
282
- static VALUE
283
- strscan_clear(VALUE self)
284
- {
285
- rb_warning("StringScanner#clear is obsolete; use #terminate instead");
286
- return strscan_terminate(self);
287
- }
288
-
289
- /*
290
- * Returns the string being scanned.
291
- */
292
- static VALUE
293
- strscan_get_string(VALUE self)
294
- {
295
- struct strscanner *p;
296
-
297
- GET_SCANNER(self, p);
298
- return p->str;
299
- }
300
-
301
- /*
302
- * call-seq: string=(str)
303
- *
304
- * Changes the string being scanned to +str+ and resets the scanner.
305
- * Returns +str+.
306
- */
307
- static VALUE
308
- strscan_set_string(VALUE self, VALUE str)
309
- {
310
- struct strscanner *p;
311
-
312
- Data_Get_Struct(self, struct strscanner, p);
313
- StringValue(str);
314
- p->str = rb_str_dup(str);
315
- rb_obj_freeze(p->str);
316
- p->curr = 0;
317
- CLEAR_MATCH_STATUS(p);
318
- return str;
319
- }
320
-
321
- /*
322
- * call-seq:
323
- * concat(str)
324
- * <<(str)
325
- *
326
- * Appends +str+ to the string being scanned.
327
- * This method does not affect scan pointer.
328
- *
329
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
330
- * s.scan(/Fri /)
331
- * s << " +1000 GMT"
332
- * s.string # -> "Fri Dec 12 1975 14:39 +1000 GMT"
333
- * s.scan(/Dec/) # -> "Dec"
334
- */
335
- static VALUE
336
- strscan_concat(VALUE self, VALUE str)
337
- {
338
- struct strscanner *p;
339
-
340
- GET_SCANNER(self, p);
341
- StringValue(str);
342
- rb_str_append(p->str, str);
343
- return self;
344
- }
345
-
346
- /*
347
- * Returns the position of the scan pointer. In the 'reset' position, this
348
- * value is zero. In the 'terminated' position (i.e. the string is exhausted),
349
- * this value is the length of the string.
350
- *
351
- * In short, it's a 0-based index into the string.
352
- *
353
- * s = StringScanner.new('test string')
354
- * s.pos # -> 0
355
- * s.scan_until /str/ # -> "test str"
356
- * s.pos # -> 8
357
- * s.terminate # -> #<StringScanner fin>
358
- * s.pos # -> 11
359
- */
360
- static VALUE
361
- strscan_get_pos(VALUE self)
362
- {
363
- struct strscanner *p;
364
-
365
- GET_SCANNER(self, p);
366
- return INT2FIX(p->curr);
367
- }
368
-
369
- /*
370
- * call-seq: pos=(n)
371
- *
372
- * Modify the scan pointer.
373
- *
374
- * s = StringScanner.new('test string')
375
- * s.pos = 7 # -> 7
376
- * s.rest # -> "ring"
377
- */
378
- static VALUE
379
- strscan_set_pos(VALUE self, VALUE v)
380
- {
381
- struct strscanner *p;
382
- long i;
383
-
384
- GET_SCANNER(self, p);
385
- i = NUM2INT(v);
386
- if (i < 0) i += S_LEN(p);
387
- if (i < 0) rb_raise(rb_eRangeError, "index out of range");
388
- if (i > S_LEN(p)) rb_raise(rb_eRangeError, "index out of range");
389
- p->curr = i;
390
- return INT2NUM(i);
391
- }
392
-
393
- static VALUE
394
- strscan_do_scan(VALUE self, VALUE regex, int succptr, int getstr, int headonly)
395
- {
396
- struct strscanner *p;
397
- int ret;
398
-
399
- Check_Type(regex, T_REGEXP);
400
- GET_SCANNER(self, p);
401
-
402
- CLEAR_MATCH_STATUS(p);
403
- if (S_RESTLEN(p) < 0) {
404
- return Qnil;
405
- }
406
- rb_kcode_set_option(regex);
407
- if (headonly) {
408
- ret = re_match(RREGEXP(regex)->ptr,
409
- CURPTR(p), S_RESTLEN(p),
410
- 0,
411
- &(p->regs));
412
- }
413
- else {
414
- ret = re_search(RREGEXP(regex)->ptr,
415
- CURPTR(p), S_RESTLEN(p),
416
- 0,
417
- S_RESTLEN(p),
418
- &(p->regs));
419
- }
420
- rb_kcode_reset_option();
421
-
422
- if (ret == -2) rb_raise(ScanError, "regexp buffer overflow");
423
- if (ret < 0) {
424
- /* not matched */
425
- return Qnil;
426
- }
427
-
428
- MATCHED(p);
429
- p->prev = p->curr;
430
- if (succptr) {
431
- p->curr += p->regs.end[0];
432
- }
433
- if (getstr) {
434
- return extract_beg_len(p, p->prev, p->regs.end[0]);
435
- }
436
- else {
437
- return INT2FIX(p->regs.end[0]);
438
- }
439
- }
440
-
441
- /*
442
- * call-seq: scan(pattern) => String
443
- *
444
- * Tries to match with +pattern+ at the current position. If there's a match,
445
- * the scanner advances the "scan pointer" and returns the matched string.
446
- * Otherwise, the scanner returns +nil+.
447
- *
448
- * s = StringScanner.new('test string')
449
- * p s.scan(/\w+/) # -> "test"
450
- * p s.scan(/\w+/) # -> nil
451
- * p s.scan(/\s+/) # -> " "
452
- * p s.scan(/\w+/) # -> "string"
453
- * p s.scan(/./) # -> nil
454
- *
455
- */
456
- static VALUE
457
- strscan_scan(VALUE self, VALUE re)
458
- {
459
- return strscan_do_scan(self, re, 1, 1, 1);
460
- }
461
-
462
- /*
463
- * call-seq: match?(pattern)
464
- *
465
- * Tests whether the given +pattern+ is matched from the current scan pointer.
466
- * Returns the length of the match, or +nil+. The scan pointer is not advanced.
467
- *
468
- * s = StringScanner.new('test string')
469
- * p s.match?(/\w+/) # -> 4
470
- * p s.match?(/\w+/) # -> 4
471
- * p s.match?(/\s+/) # -> nil
472
- */
473
- static VALUE
474
- strscan_match_p(VALUE self, VALUE re)
475
- {
476
- return strscan_do_scan(self, re, 0, 0, 1);
477
- }
478
-
479
- /*
480
- * call-seq: skip(pattern)
481
- *
482
- * Attempts to skip over the given +pattern+ beginning with the scan pointer.
483
- * If it matches, the scan pointer is advanced to the end of the match, and the
484
- * length of the match is returned. Otherwise, +nil+ is returned.
485
- *
486
- * It's similar to #scan, but without returning the matched string.
487
- *
488
- * s = StringScanner.new('test string')
489
- * p s.skip(/\w+/) # -> 4
490
- * p s.skip(/\w+/) # -> nil
491
- * p s.skip(/\s+/) # -> 1
492
- * p s.skip(/\w+/) # -> 6
493
- * p s.skip(/./) # -> nil
494
- *
495
- */
496
- static VALUE
497
- strscan_skip(VALUE self, VALUE re)
498
- {
499
- return strscan_do_scan(self, re, 1, 0, 1);
500
- }
501
-
502
- /*
503
- * call-seq: check(pattern)
504
- *
505
- * This returns the value that #scan would return, without advancing the scan
506
- * pointer. The match register is affected, though.
507
- *
508
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
509
- * s.check /Fri/ # -> "Fri"
510
- * s.pos # -> 0
511
- * s.matched # -> "Fri"
512
- * s.check /12/ # -> nil
513
- * s.matched # -> nil
514
- *
515
- * Mnemonic: it "checks" to see whether a #scan will return a value.
516
- */
517
- static VALUE
518
- strscan_check(VALUE self, VALUE re)
519
- {
520
- return strscan_do_scan(self, re, 0, 1, 1);
521
- }
522
-
523
- /*
524
- * call-seq: scan_full(pattern, return_string_p, advance_pointer_p)
525
- *
526
- * Tests whether the given +pattern+ is matched from the current scan pointer.
527
- * Returns the matched string if +return_string_p+ is true.
528
- * Advances the scan pointer if +advance_pointer_p+ is true.
529
- * The match register is affected.
530
- *
531
- * "full" means "#scan with full parameters".
532
- */
533
- static VALUE
534
- strscan_scan_full(VALUE self, VALUE re, VALUE s, VALUE f)
535
- {
536
- return strscan_do_scan(self, re, RTEST(s), RTEST(f), 1);
537
- }
538
-
539
-
540
- /*
541
- * call-seq: scan_until(pattern)
542
- *
543
- * Scans the string _until_ the +pattern+ is matched. Returns the substring up
544
- * to and including the end of the match, advancing the scan pointer to that
545
- * location. If there is no match, +nil+ is returned.
546
- *
547
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
548
- * s.scan_until(/1/) # -> "Fri Dec 1"
549
- * s.pre_match # -> "Fri Dec "
550
- * s.scan_until(/XYZ/) # -> nil
551
- */
552
- static VALUE
553
- strscan_scan_until(VALUE self, VALUE re)
554
- {
555
- return strscan_do_scan(self, re, 1, 1, 0);
556
- }
557
-
558
- /*
559
- * call-seq: exist?(pattern)
560
- *
561
- * Looks _ahead_ to see if the +pattern+ exists _anywhere_ in the string,
562
- * without advancing the scan pointer. This predicates whether a #scan_until
563
- * will return a value.
564
- *
565
- * s = StringScanner.new('test string')
566
- * s.exist? /s/ # -> 3
567
- * s.scan /test/ # -> "test"
568
- * s.exist? /s/ # -> 6
569
- * s.exist? /e/ # -> nil
570
- */
571
- static VALUE
572
- strscan_exist_p(VALUE self, VALUE re)
573
- {
574
- return strscan_do_scan(self, re, 0, 0, 0);
575
- }
576
-
577
- /*
578
- * call-seq: skip_until(pattern)
579
- *
580
- * Advances the scan pointer until +pattern+ is matched and consumed. Returns
581
- * the number of bytes advanced, or +nil+ if no match was found.
582
- *
583
- * Look ahead to match +pattern+, and advance the scan pointer to the _end_
584
- * of the match. Return the number of characters advanced, or +nil+ if the
585
- * match was unsuccessful.
586
- *
587
- * It's similar to #scan_until, but without returning the intervening string.
588
- *
589
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
590
- * s.skip_until /12/ # -> 10
591
- * s #
592
- */
593
- static VALUE
594
- strscan_skip_until(VALUE self, VALUE re)
595
- {
596
- return strscan_do_scan(self, re, 1, 0, 0);
597
- }
598
-
599
- /*
600
- * call-seq: check_until(pattern)
601
- *
602
- * This returns the value that #scan_until would return, without advancing the
603
- * scan pointer. The match register is affected, though.
604
- *
605
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
606
- * s.check_until /12/ # -> "Fri Dec 12"
607
- * s.pos # -> 0
608
- * s.matched # -> 12
609
- *
610
- * Mnemonic: it "checks" to see whether a #scan_until will return a value.
611
- */
612
- static VALUE
613
- strscan_check_until(VALUE self, VALUE re)
614
- {
615
- return strscan_do_scan(self, re, 0, 1, 0);
616
- }
617
-
618
- /*
619
- * call-seq: search_full(pattern, return_string_p, advance_pointer_p)
620
- *
621
- * Scans the string _until_ the +pattern+ is matched.
622
- * Returns the matched string if +return_string_p+ is true, otherwise
623
- * returns the number of bytes advanced.
624
- * Advances the scan pointer if +advance_pointer_p+, otherwise not.
625
- * This method does affect the match register.
626
- */
627
- static VALUE
628
- strscan_search_full(VALUE self, VALUE re, VALUE s, VALUE f)
629
- {
630
- return strscan_do_scan(self, re, RTEST(s), RTEST(f), 0);
631
- }
632
-
633
- /* DANGEROUS; need to synchronize with regex.c */
634
- static void
635
- adjust_registers_to_matched(struct strscanner *p)
636
- {
637
- if (p->regs.allocated == 0) {
638
- p->regs.beg = ALLOC_N(int, RE_NREGS);
639
- p->regs.end = ALLOC_N(int, RE_NREGS);
640
- p->regs.allocated = RE_NREGS;
641
- }
642
- p->regs.num_regs = 1;
643
- p->regs.beg[0] = 0;
644
- p->regs.end[0] = p->curr - p->prev;
645
- }
646
-
647
- /*
648
- * Scans one character and returns it.
649
- * This method is multi-byte character sensitive.
650
- * See also #get_byte.
651
- *
652
- * s = StringScanner.new('ab')
653
- * s.getch # => "a"
654
- * s.getch # => "b"
655
- * s.getch # => nil
656
- *
657
- * $KCODE = 'EUC'
658
- * s = StringScanner.new("\244\242")
659
- * s.getch # => "\244\242" # Japanese hira-kana "A" in EUC-JP
660
- * s.getch # => nil
661
- */
662
- static VALUE
663
- strscan_getch(VALUE self)
664
- {
665
- struct strscanner *p;
666
- long len;
667
-
668
- GET_SCANNER(self, p);
669
- CLEAR_MATCH_STATUS(p);
670
- if (EOS_P(p))
671
- return Qnil;
672
- len = mbclen(*CURPTR(p));
673
- if (p->curr + len > S_LEN(p)) {
674
- len = S_LEN(p) - p->curr;
675
- }
676
- p->prev = p->curr;
677
- p->curr += len;
678
- MATCHED(p);
679
- adjust_registers_to_matched(p);
680
- return extract_range(p, p->prev + p->regs.beg[0],
681
- p->prev + p->regs.end[0]);
682
- }
683
-
684
- /*
685
- * Scans one byte and returns it.
686
- * This method is NOT multi-byte character sensitive.
687
- * See also #getch.
688
- *
689
- * s = StringScanner.new('ab')
690
- * s.get_byte # => "a"
691
- * s.get_byte # => "b"
692
- * s.get_byte # => nil
693
- *
694
- * s = StringScanner.new("\244\242")
695
- * s.get_byte # => "\244"
696
- * s.get_byte # => "\242"
697
- * s.get_byte # => nil
698
- */
699
- static VALUE
700
- strscan_get_byte(VALUE self)
701
- {
702
- struct strscanner *p;
703
-
704
- GET_SCANNER(self, p);
705
- CLEAR_MATCH_STATUS(p);
706
- if (EOS_P(p)) {
707
- return Qnil;
708
- }
709
- p->prev = p->curr;
710
- p->curr++;
711
- MATCHED(p);
712
- adjust_registers_to_matched(p);
713
- return extract_range(p, p->prev + p->regs.beg[0],
714
- p->prev + p->regs.end[0]);
715
- }
716
-
717
- /*
718
- * Equivalent to #get_byte.
719
- * This method is obsolete; use #get_byte instead.
720
- */
721
- static VALUE
722
- strscan_getbyte(VALUE self)
723
- {
724
- rb_warning("StringScanner#getbyte is obsolete; use #get_byte instead");
725
- return strscan_get_byte(self);
726
- }
727
-
728
- /*
729
- * call-seq: peek(len)
730
- *
731
- * Extracts a string corresponding to <tt>string[pos,len]</tt>, without
732
- * advancing the scan pointer.
733
- *
734
- * s = StringScanner.new('test string')
735
- * s.peek(7) # => "test st"
736
- * s.peek(7) # => "test st"
737
- *
738
- */
739
- static VALUE
740
- strscan_peek(VALUE self, VALUE vlen)
741
- {
742
- struct strscanner *p;
743
- long len;
744
-
745
- GET_SCANNER(self, p);
746
- len = NUM2LONG(vlen);
747
- if (EOS_P(p)) {
748
- return infect(rb_str_new("", 0), p);
749
- }
750
- if (p->curr + len > S_LEN(p)) {
751
- len = S_LEN(p) - p->curr;
752
- }
753
- return extract_beg_len(p, p->curr, len);
754
- }
755
-
756
- /*
757
- * Equivalent to #peek.
758
- * This method is obsolete; use #peek instead.
759
- */
760
- static VALUE
761
- strscan_peep(VALUE self, VALUE vlen)
762
- {
763
- rb_warning("StringScanner#peep is obsolete; use #peek instead");
764
- return strscan_peek(self, vlen);
765
- }
766
-
767
- /*
768
- * Set the scan pointer to the previous position. Only one previous position is
769
- * remembered, and it changes with each scanning operation.
770
- *
771
- * s = StringScanner.new('test string')
772
- * s.scan(/\w+/) # => "test"
773
- * s.unscan
774
- * s.scan(/../) # => "te"
775
- * s.scan(/\d/) # => nil
776
- * s.unscan # ScanError: unscan failed: previous match had failed
777
- */
778
- static VALUE
779
- strscan_unscan(VALUE self)
780
- {
781
- struct strscanner *p;
782
-
783
- GET_SCANNER(self, p);
784
- if (! MATCHED_P(p)) {
785
- rb_raise(ScanError, "unscan failed: previous match had failed");
786
- }
787
- p->curr = p->prev;
788
- CLEAR_MATCH_STATUS(p);
789
- return self;
790
- }
791
-
792
- /*
793
- * Returns +true+ iff the scan pointer is at the beginning of the line.
794
- *
795
- * s = StringScanner.new("test\ntest\n")
796
- * s.bol? # => true
797
- * s.scan(/te/)
798
- * s.bol? # => false
799
- * s.scan(/st\n/)
800
- * s.bol? # => true
801
- * s.terminate
802
- * s.bol? # => true
803
- */
804
- static VALUE
805
- strscan_bol_p(VALUE self)
806
- {
807
- struct strscanner *p;
808
-
809
- GET_SCANNER(self, p);
810
- if (CURPTR(p) > S_PEND(p)) return Qnil;
811
- if (p->curr == 0) return Qtrue;
812
- return (*(CURPTR(p) - 1) == '\n') ? Qtrue : Qfalse;
813
- }
814
-
815
- /*
816
- * Returns +true+ if the scan pointer is at the end of the string.
817
- *
818
- * s = StringScanner.new('test string')
819
- * p s.eos? # => false
820
- * s.scan(/test/)
821
- * p s.eos? # => false
822
- * s.terminate
823
- * p s.eos? # => true
824
- */
825
- static VALUE
826
- strscan_eos_p(VALUE self)
827
- {
828
- struct strscanner *p;
829
-
830
- GET_SCANNER(self, p);
831
- return EOS_P(p) ? Qtrue : Qfalse;
832
- }
833
-
834
- /*
835
- * Equivalent to #eos?.
836
- * This method is obsolete, use #eos? instead.
837
- */
838
- static VALUE
839
- strscan_empty_p(VALUE self)
840
- {
841
- rb_warning("StringScanner#empty? is obsolete; use #eos? instead");
842
- return strscan_eos_p(self);
843
- }
844
-
845
- /*
846
- * Returns true iff there is more data in the string. See #eos?.
847
- * This method is obsolete; use #eos? instead.
848
- *
849
- * s = StringScanner.new('test string')
850
- * s.eos? # These two
851
- * s.rest? # are opposites.
852
- */
853
- static VALUE
854
- strscan_rest_p(VALUE self)
855
- {
856
- struct strscanner *p;
857
-
858
- GET_SCANNER(self, p);
859
- return EOS_P(p) ? Qfalse : Qtrue;
860
- }
861
-
862
- /*
863
- * Returns +true+ iff the last match was successful.
864
- *
865
- * s = StringScanner.new('test string')
866
- * s.match?(/\w+/) # => 4
867
- * s.matched? # => true
868
- * s.match?(/\d+/) # => nil
869
- * s.matched? # => false
870
- */
871
- static VALUE
872
- strscan_matched_p(VALUE self)
873
- {
874
- struct strscanner *p;
875
-
876
- GET_SCANNER(self, p);
877
- return MATCHED_P(p) ? Qtrue : Qfalse;
878
- }
879
-
880
- /*
881
- * Returns the last matched string.
882
- *
883
- * s = StringScanner.new('test string')
884
- * s.match?(/\w+/) # -> 4
885
- * s.matched # -> "test"
886
- */
887
- static VALUE
888
- strscan_matched(VALUE self)
889
- {
890
- struct strscanner *p;
891
-
892
- GET_SCANNER(self, p);
893
- if (! MATCHED_P(p)) return Qnil;
894
-
895
- return extract_range(p, p->prev + p->regs.beg[0],
896
- p->prev + p->regs.end[0]);
897
- }
898
-
899
- /*
900
- * Returns the size of the most recent match (see #matched), or +nil+ if there
901
- * was no recent match.
902
- *
903
- * s = StringScanner.new('test string')
904
- * s.check /\w+/ # -> "test"
905
- * s.matched_size # -> 4
906
- * s.check /\d+/ # -> nil
907
- * s.matched_size # -> nil
908
- */
909
- static VALUE
910
- strscan_matched_size(VALUE self)
911
- {
912
- struct strscanner *p;
913
-
914
- GET_SCANNER(self, p);
915
- if (! MATCHED_P(p)) return Qnil;
916
-
917
- return INT2NUM(p->regs.end[0] - p->regs.beg[0]);
918
- }
919
-
920
- /*
921
- * Equivalent to #matched_size.
922
- * This method is obsolete; use #matched_size instead.
923
- */
924
- static VALUE
925
- strscan_matchedsize(VALUE self)
926
- {
927
- rb_warning("StringScanner#matchedsize is obsolete; use #matched_size instead");
928
- return strscan_matched_size(self);
929
- }
930
-
931
- /*
932
- * call-seq: [](n)
933
- *
934
- * Return the n-th subgroup in the most recent match.
935
- *
936
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
937
- * s.scan(/(\w+) (\w+) (\d+) /) # -> "Fri Dec 12 "
938
- * s[0] # -> "Fri Dec 12 "
939
- * s[1] # -> "Fri"
940
- * s[2] # -> "Dec"
941
- * s[3] # -> "12"
942
- * s.post_match # -> "1975 14:39"
943
- * s.pre_match # -> ""
944
- */
945
- static VALUE
946
- strscan_aref(VALUE self, VALUE idx)
947
- {
948
- struct strscanner *p;
949
- long i;
950
-
951
- GET_SCANNER(self, p);
952
- if (! MATCHED_P(p)) return Qnil;
953
-
954
- i = NUM2LONG(idx);
955
- if (i < 0)
956
- i += p->regs.num_regs;
957
- if (i < 0) return Qnil;
958
- if (i >= p->regs.num_regs) return Qnil;
959
- if (p->regs.beg[i] == -1) return Qnil;
960
-
961
- return extract_range(p, p->prev + p->regs.beg[i],
962
- p->prev + p->regs.end[i]);
963
- }
964
-
965
- /*
966
- * Return the <i><b>pre</b>-match</i> (in the regular expression sense) of the last scan.
967
- *
968
- * s = StringScanner.new('test string')
969
- * s.scan(/\w+/) # -> "test"
970
- * s.scan(/\s+/) # -> " "
971
- * s.pre_match # -> "test"
972
- * s.post_match # -> "string"
973
- */
974
- static VALUE
975
- strscan_pre_match(VALUE self)
976
- {
977
- struct strscanner *p;
978
-
979
- GET_SCANNER(self, p);
980
- if (! MATCHED_P(p)) return Qnil;
981
-
982
- return extract_range(p, 0, p->prev + p->regs.beg[0]);
983
- }
984
-
985
- /*
986
- * Return the <i><b>post</b>-match</i> (in the regular expression sense) of the last scan.
987
- *
988
- * s = StringScanner.new('test string')
989
- * s.scan(/\w+/) # -> "test"
990
- * s.scan(/\s+/) # -> " "
991
- * s.pre_match # -> "test"
992
- * s.post_match # -> "string"
993
- */
994
- static VALUE
995
- strscan_post_match(VALUE self)
996
- {
997
- struct strscanner *p;
998
-
999
- GET_SCANNER(self, p);
1000
- if (! MATCHED_P(p)) return Qnil;
1001
-
1002
- return extract_range(p, p->prev + p->regs.end[0], S_LEN(p));
1003
- }
1004
-
1005
- /*
1006
- * Returns the "rest" of the string (i.e. everything after the scan pointer).
1007
- * If there is no more data (eos? = true), it returns <tt>""</tt>.
1008
- */
1009
- static VALUE
1010
- strscan_rest(VALUE self)
1011
- {
1012
- struct strscanner *p;
1013
-
1014
- GET_SCANNER(self, p);
1015
- if (EOS_P(p)) {
1016
- return infect(rb_str_new("", 0), p);
1017
- }
1018
- return extract_range(p, p->curr, S_LEN(p));
1019
- }
1020
-
1021
- /*
1022
- * <tt>s.rest_size</tt> is equivalent to <tt>s.rest.size</tt>.
1023
- */
1024
- static VALUE
1025
- strscan_rest_size(VALUE self)
1026
- {
1027
- struct strscanner *p;
1028
- long i;
1029
-
1030
- GET_SCANNER(self, p);
1031
- if (EOS_P(p)) {
1032
- return INT2FIX(0);
1033
- }
1034
-
1035
- i = S_LEN(p) - p->curr;
1036
- return INT2FIX(i);
1037
- }
1038
-
1039
- /*
1040
- * <tt>s.restsize</tt> is equivalent to <tt>s.rest_size</tt>.
1041
- * This method is obsolete; use #rest_size instead.
1042
- */
1043
- static VALUE
1044
- strscan_restsize(VALUE self)
1045
- {
1046
- rb_warning("StringScanner#restsize is obsolete; use #rest_size instead");
1047
- return strscan_rest_size(self);
1048
- }
1049
-
1050
- #define INSPECT_LENGTH 5
1051
- #define BUFSIZE 256
1052
-
1053
- /*
1054
- * Returns a string that represents the StringScanner object, showing:
1055
- * - the current position
1056
- * - the size of the string
1057
- * - the characters surrounding the scan pointer
1058
- *
1059
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
1060
- * s.inspect # -> '#<StringScanner 0/21 @ "Fri D...">'
1061
- * s.scan_until /12/ # -> "Fri Dec 12"
1062
- * s.inspect # -> '#<StringScanner 10/21 "...ec 12" @ " 1975...">'
1063
- */
1064
- static VALUE
1065
- strscan_inspect(VALUE self)
1066
- {
1067
- struct strscanner *p;
1068
- char buf[BUFSIZE];
1069
- long len;
1070
- VALUE a, b;
1071
-
1072
- Data_Get_Struct(self, struct strscanner, p);
1073
- if (NIL_P(p->str)) {
1074
- len = snprintf(buf, BUFSIZE, "#<%s (uninitialized)>",
1075
- rb_class2name(CLASS_OF(self)));
1076
- return infect(rb_str_new(buf, len), p);
1077
- }
1078
- if (EOS_P(p)) {
1079
- len = snprintf(buf, BUFSIZE, "#<%s fin>",
1080
- rb_class2name(CLASS_OF(self)));
1081
- return infect(rb_str_new(buf, len), p);
1082
- }
1083
- if (p->curr == 0) {
1084
- b = inspect2(p);
1085
- len = snprintf(buf, BUFSIZE, "#<%s %ld/%ld @ %s>",
1086
- rb_class2name(CLASS_OF(self)),
1087
- p->curr, S_LEN(p),
1088
- RSTRING(b)->ptr);
1089
- return infect(rb_str_new(buf, len), p);
1090
- }
1091
- a = inspect1(p);
1092
- b = inspect2(p);
1093
- len = snprintf(buf, BUFSIZE, "#<%s %ld/%ld %s @ %s>",
1094
- rb_class2name(CLASS_OF(self)),
1095
- p->curr, S_LEN(p),
1096
- RSTRING(a)->ptr,
1097
- RSTRING(b)->ptr);
1098
- return infect(rb_str_new(buf, len), p);
1099
- }
1100
-
1101
- static VALUE
1102
- inspect1(struct strscanner *p)
1103
- {
1104
- char buf[BUFSIZE];
1105
- char *bp = buf;
1106
- long len;
1107
-
1108
- if (p->curr == 0) return rb_str_new2("");
1109
- if (p->curr > INSPECT_LENGTH) {
1110
- strcpy(bp, "..."); bp += 3;
1111
- len = INSPECT_LENGTH;
1112
- }
1113
- else {
1114
- len = p->curr;
1115
- }
1116
- memcpy(bp, CURPTR(p) - len, len); bp += len;
1117
- return rb_str_dump(rb_str_new(buf, bp - buf));
1118
- }
1119
-
1120
- static VALUE
1121
- inspect2(struct strscanner *p)
1122
- {
1123
- char buf[BUFSIZE];
1124
- char *bp = buf;
1125
- long len;
1126
-
1127
- if (EOS_P(p)) return rb_str_new2("");
1128
- len = S_LEN(p) - p->curr;
1129
- if (len > INSPECT_LENGTH) {
1130
- len = INSPECT_LENGTH;
1131
- memcpy(bp, CURPTR(p), len); bp += len;
1132
- strcpy(bp, "..."); bp += 3;
1133
- }
1134
- else {
1135
- memcpy(bp, CURPTR(p), len); bp += len;
1136
- }
1137
- return rb_str_dump(rb_str_new(buf, bp - buf));
1138
- }
1139
-
1140
- /* =======================================================================
1141
- Ruby Interface
1142
- ======================================================================= */
1143
-
1144
- /*
1145
- * Document-class: StringScanner
1146
- *
1147
- * StringScanner provides for lexical scanning operations on a String. Here is
1148
- * an example of its usage:
1149
- *
1150
- * s = StringScanner.new('This is an example string')
1151
- * s.eos? # -> false
1152
- *
1153
- * p s.scan(/\w+/) # -> "This"
1154
- * p s.scan(/\w+/) # -> nil
1155
- * p s.scan(/\s+/) # -> " "
1156
- * p s.scan(/\s+/) # -> nil
1157
- * p s.scan(/\w+/) # -> "is"
1158
- * s.eos? # -> false
1159
- *
1160
- * p s.scan(/\s+/) # -> " "
1161
- * p s.scan(/\w+/) # -> "an"
1162
- * p s.scan(/\s+/) # -> " "
1163
- * p s.scan(/\w+/) # -> "example"
1164
- * p s.scan(/\s+/) # -> " "
1165
- * p s.scan(/\w+/) # -> "string"
1166
- * s.eos? # -> true
1167
- *
1168
- * p s.scan(/\s+/) # -> nil
1169
- * p s.scan(/\w+/) # -> nil
1170
- *
1171
- * Scanning a string means remembering the position of a <i>scan pointer</i>,
1172
- * which is just an index. The point of scanning is to move forward a bit at
1173
- * a time, so matches are sought after the scan pointer; usually immediately
1174
- * after it.
1175
- *
1176
- * Given the string "test string", here are the pertinent scan pointer
1177
- * positions:
1178
- *
1179
- * t e s t s t r i n g
1180
- * 0 1 2 ... 1
1181
- * 0
1182
- *
1183
- * When you #scan for a pattern (a regular expression), the match must occur
1184
- * at the character after the scan pointer. If you use #scan_until, then the
1185
- * match can occur anywhere after the scan pointer. In both cases, the scan
1186
- * pointer moves <i>just beyond</i> the last character of the match, ready to
1187
- * scan again from the next character onwards. This is demonstrated by the
1188
- * example above.
1189
- *
1190
- * == Method Categories
1191
- *
1192
- * There are other methods besides the plain scanners. You can look ahead in
1193
- * the string without actually scanning. You can access the most recent match.
1194
- * You can modify the string being scanned, reset or terminate the scanner,
1195
- * find out or change the position of the scan pointer, skip ahead, and so on.
1196
- *
1197
- * === Advancing the Scan Pointer
1198
- *
1199
- * - #getch
1200
- * - #get_byte
1201
- * - #scan
1202
- * - #scan_until
1203
- * - #skip
1204
- * - #skip_until
1205
- *
1206
- * === Looking Ahead
1207
- *
1208
- * - #check
1209
- * - #check_until
1210
- * - #exist?
1211
- * - #match?
1212
- * - #peek
1213
- *
1214
- * === Finding Where we Are
1215
- *
1216
- * - #beginning_of_line? (#bol?)
1217
- * - #eos?
1218
- * - #rest?
1219
- * - #rest_size
1220
- * - #pos
1221
- *
1222
- * === Setting Where we Are
1223
- *
1224
- * - #reset
1225
- * - #terminate
1226
- * - #pos=
1227
- *
1228
- * === Match Data
1229
- *
1230
- * - #matched
1231
- * - #matched?
1232
- * - #matched_size
1233
- * - []
1234
- * - #pre_match
1235
- * - #post_match
1236
- *
1237
- * === Miscellaneous
1238
- *
1239
- * - <<
1240
- * - #concat
1241
- * - #string
1242
- * - #string=
1243
- * - #unscan
1244
- *
1245
- * There are aliases to several of the methods.
1246
- */
1247
- void
1248
- Init_strscan(void)
1249
- {
1250
- ID id_scanerr = rb_intern("ScanError");
1251
- VALUE tmp;
1252
-
1253
- StringScanner = rb_define_class("StringScanner", rb_cObject);
1254
- ScanError = rb_define_class_under(StringScanner, "Error", rb_eStandardError);
1255
- if (!rb_const_defined(rb_cObject, id_scanerr)) {
1256
- rb_const_set(rb_cObject, id_scanerr, ScanError);
1257
- }
1258
- tmp = rb_str_new2(STRSCAN_VERSION);
1259
- rb_obj_freeze(tmp);
1260
- rb_const_set(StringScanner, rb_intern("Version"), tmp);
1261
- tmp = rb_str_new2("$Id: strscan.c 11708 2007-02-12 23:01:19Z shyouhei $");
1262
- rb_obj_freeze(tmp);
1263
- rb_const_set(StringScanner, rb_intern("Id"), tmp);
1264
-
1265
- rb_define_alloc_func(StringScanner, strscan_s_allocate);
1266
- rb_define_private_method(StringScanner, "initialize", strscan_initialize, -1);
1267
- rb_define_private_method(StringScanner, "initialize_copy", strscan_init_copy, 1);
1268
- rb_define_singleton_method(StringScanner, "must_C_version", strscan_s_mustc, 0);
1269
- rb_define_method(StringScanner, "reset", strscan_reset, 0);
1270
- rb_define_method(StringScanner, "terminate", strscan_terminate, 0);
1271
- rb_define_method(StringScanner, "clear", strscan_clear, 0);
1272
- rb_define_method(StringScanner, "string", strscan_get_string, 0);
1273
- rb_define_method(StringScanner, "string=", strscan_set_string, 1);
1274
- rb_define_method(StringScanner, "concat", strscan_concat, 1);
1275
- rb_define_method(StringScanner, "<<", strscan_concat, 1);
1276
- rb_define_method(StringScanner, "pos", strscan_get_pos, 0);
1277
- rb_define_method(StringScanner, "pos=", strscan_set_pos, 1);
1278
- rb_define_method(StringScanner, "pointer", strscan_get_pos, 0);
1279
- rb_define_method(StringScanner, "pointer=", strscan_set_pos, 1);
1280
-
1281
- rb_define_method(StringScanner, "scan", strscan_scan, 1);
1282
- rb_define_method(StringScanner, "skip", strscan_skip, 1);
1283
- rb_define_method(StringScanner, "match?", strscan_match_p, 1);
1284
- rb_define_method(StringScanner, "check", strscan_check, 1);
1285
- rb_define_method(StringScanner, "scan_full", strscan_scan_full, 3);
1286
-
1287
- rb_define_method(StringScanner, "scan_until", strscan_scan_until, 1);
1288
- rb_define_method(StringScanner, "skip_until", strscan_skip_until, 1);
1289
- rb_define_method(StringScanner, "exist?", strscan_exist_p, 1);
1290
- rb_define_method(StringScanner, "check_until", strscan_check_until, 1);
1291
- rb_define_method(StringScanner, "search_full", strscan_search_full, 3);
1292
-
1293
- rb_define_method(StringScanner, "getch", strscan_getch, 0);
1294
- rb_define_method(StringScanner, "get_byte", strscan_get_byte, 0);
1295
- rb_define_method(StringScanner, "getbyte", strscan_getbyte, 0);
1296
- rb_define_method(StringScanner, "peek", strscan_peek, 1);
1297
- rb_define_method(StringScanner, "peep", strscan_peep, 1);
1298
-
1299
- rb_define_method(StringScanner, "unscan", strscan_unscan, 0);
1300
-
1301
- rb_define_method(StringScanner, "beginning_of_line?", strscan_bol_p, 0);
1302
- rb_alias(StringScanner, rb_intern("bol?"), rb_intern("beginning_of_line?"));
1303
- rb_define_method(StringScanner, "eos?", strscan_eos_p, 0);
1304
- rb_define_method(StringScanner, "empty?", strscan_empty_p, 0);
1305
- rb_define_method(StringScanner, "rest?", strscan_rest_p, 0);
1306
-
1307
- rb_define_method(StringScanner, "matched?", strscan_matched_p, 0);
1308
- rb_define_method(StringScanner, "matched", strscan_matched, 0);
1309
- rb_define_method(StringScanner, "matched_size", strscan_matched_size, 0);
1310
- rb_define_method(StringScanner, "matchedsize", strscan_matchedsize, 0);
1311
- rb_define_method(StringScanner, "[]", strscan_aref, 1);
1312
- rb_define_method(StringScanner, "pre_match", strscan_pre_match, 0);
1313
- rb_define_method(StringScanner, "post_match", strscan_post_match, 0);
1314
-
1315
- rb_define_method(StringScanner, "rest", strscan_rest, 0);
1316
- rb_define_method(StringScanner, "rest_size", strscan_rest_size, 0);
1317
- rb_define_method(StringScanner, "restsize", strscan_restsize, 0);
1318
-
1319
- rb_define_method(StringScanner, "inspect", strscan_inspect, 0);
1320
- }