Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
string.c
Go to the documentation of this file.
1 #include "mruby.h"
2 #include "mruby/string.h"
3 #include <ctype.h>
4 #include <string.h>
5 
6 static mrb_value
7 mrb_str_getbyte(mrb_state *mrb, mrb_value str)
8 {
9  mrb_int pos;
10  mrb_get_args(mrb, "i", &pos);
11 
12  if (pos < 0)
13  pos += RSTRING_LEN(str);
14  if (pos < 0 || RSTRING_LEN(str) <= pos)
15  return mrb_nil_value();
16 
17  return mrb_fixnum_value((unsigned char)RSTRING_PTR(str)[pos]);
18 }
19 
20 /*
21  * call-seq:
22  * str.swapcase! -> str or nil
23  *
24  * Equivalent to <code>String#swapcase</code>, but modifies the receiver in
25  * place, returning <i>str</i>, or <code>nil</code> if no changes were made.
26  * Note: case conversion is effective only in ASCII region.
27  */
28 static mrb_value
29 mrb_str_swapcase_bang(mrb_state *mrb, mrb_value str)
30 {
31  char *p, *pend;
32  int modify = 0;
33  struct RString *s = mrb_str_ptr(str);
34 
35  mrb_str_modify(mrb, s);
36  p = s->ptr;
37  pend = s->ptr + s->len;
38  while (p < pend) {
39  if (ISUPPER(*p)) {
40  *p = TOLOWER(*p);
41  modify = 1;
42  }
43  else if (ISLOWER(*p)) {
44  *p = TOUPPER(*p);
45  modify = 1;
46  }
47  p++;
48  }
49 
50  if (modify) return str;
51  return mrb_nil_value();
52 }
53 
54 /*
55  * call-seq:
56  * str.swapcase -> new_str
57  *
58  * Returns a copy of <i>str</i> with uppercase alphabetic characters converted
59  * to lowercase and lowercase characters converted to uppercase.
60  * Note: case conversion is effective only in ASCII region.
61  *
62  * "Hello".swapcase #=> "hELLO"
63  * "cYbEr_PuNk11".swapcase #=> "CyBeR_pUnK11"
64  */
65 static mrb_value
66 mrb_str_swapcase(mrb_state *mrb, mrb_value self)
67 {
68  mrb_value str;
69 
70  str = mrb_str_dup(mrb, self);
71  mrb_str_swapcase_bang(mrb, str);
72  return str;
73 }
74 
75 /*
76  * call-seq:
77  * str << integer -> str
78  * str.concat(integer) -> str
79  * str << obj -> str
80  * str.concat(obj) -> str
81  *
82  * Append---Concatenates the given object to <i>str</i>. If the object is a
83  * <code>Integer</code>, it is considered as a codepoint, and is converted
84  * to a character before concatenation.
85  *
86  * a = "hello "
87  * a << "world" #=> "hello world"
88  * a.concat(33) #=> "hello world!"
89  */
90 static mrb_value
91 mrb_str_concat2(mrb_state *mrb, mrb_value self)
92 {
93  mrb_value str;
94  mrb_get_args(mrb, "S", &str);
95  mrb_str_concat(mrb, self, str);
96  return self;
97 }
98 
99 /*
100  * call-seq:
101  * str.start_with?([prefixes]+) -> true or false
102  *
103  * Returns true if +str+ starts with one of the +prefixes+ given.
104  *
105  * "hello".start_with?("hell") #=> true
106  *
107  * # returns true if one of the prefixes matches.
108  * "hello".start_with?("heaven", "hell") #=> true
109  * "hello".start_with?("heaven", "paradise") #=> false
110  * "h".start_with?("heaven", "hell") #=> false
111  */
112 static mrb_value
113 mrb_str_start_with(mrb_state *mrb, mrb_value self)
114 {
115  mrb_value *argv, sub;
116  int argc, i;
117  mrb_get_args(mrb, "*", &argv, &argc);
118 
119  for (i = 0; i < argc; i++) {
120  size_t len_l, len_r;
121  int ai = mrb_gc_arena_save(mrb);
122  sub = mrb_string_type(mrb, argv[i]);
123  mrb_gc_arena_restore(mrb, ai);
124  len_l = RSTRING_LEN(self);
125  len_r = RSTRING_LEN(sub);
126  if (len_l >= len_r) {
127  if (memcmp(RSTRING_PTR(self), RSTRING_PTR(sub), len_r) == 0) {
128  return mrb_true_value();
129  }
130  }
131  }
132  return mrb_false_value();
133 }
134 
135 /*
136  * call-seq:
137  * str.end_with?([suffixes]+) -> true or false
138  *
139  * Returns true if +str+ ends with one of the +suffixes+ given.
140  */
141 static mrb_value
142 mrb_str_end_with(mrb_state *mrb, mrb_value self)
143 {
144  mrb_value *argv, sub;
145  int argc, i;
146  mrb_get_args(mrb, "*", &argv, &argc);
147 
148  for (i = 0; i < argc; i++) {
149  size_t len_l, len_r;
150  int ai = mrb_gc_arena_save(mrb);
151  sub = mrb_string_type(mrb, argv[i]);
152  mrb_gc_arena_restore(mrb, ai);
153  len_l = RSTRING_LEN(self);
154  len_r = RSTRING_LEN(sub);
155  if (len_l >= len_r) {
156  if (memcmp(RSTRING_PTR(self) + (len_l - len_r),
157  RSTRING_PTR(sub),
158  len_r) == 0) {
159  return mrb_true_value();
160  }
161  }
162  }
163  return mrb_false_value();
164 }
165 
166 void
168 {
169  struct RClass * s = mrb->string_class;
170 
171  mrb_define_method(mrb, s, "dump", mrb_str_dump, MRB_ARGS_NONE());
172  mrb_define_method(mrb, s, "getbyte", mrb_str_getbyte, MRB_ARGS_REQ(1));
173  mrb_define_method(mrb, s, "swapcase!", mrb_str_swapcase_bang, MRB_ARGS_NONE());
174  mrb_define_method(mrb, s, "swapcase", mrb_str_swapcase, MRB_ARGS_NONE());
175  mrb_define_method(mrb, s, "concat", mrb_str_concat2, MRB_ARGS_REQ(1));
176  mrb_define_method(mrb, s, "<<", mrb_str_concat2, MRB_ARGS_REQ(1));
177  mrb_define_method(mrb, s, "start_with?", mrb_str_start_with, MRB_ARGS_REST());
178  mrb_define_method(mrb, s, "end_with?", mrb_str_end_with, MRB_ARGS_REST());
179 }
180 
181 void
183 {
184 }