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