]> Dogcows Code - chaz/yoink/blob - src/moof/string.cc
mesh and other random adjustments
[chaz/yoink] / src / moof / string.cc
1
2 /*] Copyright (c) 2009-2010, Charles McGarvey [**************************
3 **] All rights reserved.
4 *
5 * vi:ts=4 sw=4 tw=75
6 *
7 * Distributable under the terms and conditions of the 2-clause BSD license;
8 * see the file COPYING for a complete text of the license.
9 *
10 **************************************************************************/
11
12 #include <stdexcept>
13
14 #include <boost/shared_array.hpp>
15
16 #include "ConvertUTF.h"
17 #include "script.hh"
18 #include "string.hh"
19
20
21 namespace moof {
22
23
24 wstring multi_to_wide(const string& multi)
25 {
26 typedef boost::shared_array<wchar_t> buffer;
27
28 if (sizeof(wchar_t) == 2)
29 {
30 size_t length = multi.length();
31 buffer wide(new wchar_t[length + 1]);
32 const UTF8* src1 = (const UTF8*)multi.c_str();
33 const UTF8* src2 = src1 + length;
34 UTF16* dst1 = (UTF16*)wide.get();
35 UTF16* dst2 = dst1 + length+1;
36
37 if (ConvertUTF8toUTF16(&src1, src2,
38 &dst1, dst2, lenientConversion) != conversionOK)
39 {
40 throw std::runtime_error("bad string conversion");
41 }
42
43 *dst1 = 0;
44 wstring str(wide.get());
45 return str;
46 }
47 else if (sizeof(wchar_t) == 4)
48 {
49 size_t length = multi.length();
50 buffer wide(new wchar_t[length + 1]);
51 const UTF8* src1 = (const UTF8*)multi.c_str();
52 const UTF8* src2 = src1 + length;
53 UTF32* dst1 = (UTF32*)wide.get();
54 UTF32* dst2 = dst1 + length+1;
55
56 if (ConvertUTF8toUTF32(&src1, src2,
57 &dst1, dst2, lenientConversion) != conversionOK)
58 {
59 throw std::runtime_error("bad string conversion");
60 }
61
62 *dst1 = 0;
63 wstring str(wide.get());
64 return str;
65 }
66 else
67 {
68 throw std::runtime_error("unknown size of wide characters");
69 }
70 }
71
72 string wide_to_multi(const wstring& wide)
73 {
74 typedef boost::shared_array<char> buffer;
75
76 if (sizeof(wchar_t) == 2)
77 {
78 size_t length = wide.length();
79 size_t multi_length = 3 * length + 1;
80 buffer multi(new char[multi_length]);
81 const UTF16* src1 = (const UTF16*)wide.c_str();
82 const UTF16* src2 = src1 + length;
83 UTF8* dst1 = (UTF8*)multi.get();
84 UTF8* dst2 = dst1 + multi_length;
85
86 if (ConvertUTF16toUTF8(&src1, src2,
87 &dst1, dst2, lenientConversion) != conversionOK)
88 {
89 throw std::runtime_error("bad string conversion");
90 }
91
92 *dst1 = 0;
93 string str(multi.get());
94 return str;
95 }
96 else if (sizeof(wchar_t) == 4)
97 {
98 size_t length = wide.length();
99 size_t multi_length = 4 * length + 1;
100 buffer multi(new char[multi_length]);
101 const UTF32* src1 = (const UTF32*)wide.c_str();
102 const UTF32* src2 = src1 + length;
103 UTF8* dst1 = (UTF8*)multi.get();
104 UTF8* dst2 = dst1 + multi_length;
105
106 if (ConvertUTF32toUTF8(&src1, src2,
107 &dst1, dst2, lenientConversion) != conversionOK)
108 {
109 throw std::runtime_error("bad string conversion");
110 }
111
112 *dst1 = 0;
113 string str(multi.get());
114 return str;
115 }
116 else
117 {
118 throw std::runtime_error("unknown size of wide characters");
119 }
120 }
121
122
123 static script& regex_script()
124 {
125 static script script;
126 static bool init = true;
127 if (init)
128 {
129 script.import_string_library();
130 script.globals().push_field("string").push_field("match");
131 script.globals().set_field("match");
132 script.top().push_field("gmatch");
133 script.globals().set_field("gmatch");
134 script.top().push_field("gsub");
135 script.globals().set_field("gsub");
136 script.push_nil();
137 script.globals().set_field("string");
138 script.pop();
139 init = false;
140 }
141 return script;
142 }
143
144
145 regex::regex(const string& pattern)
146 {
147 regex::pattern(pattern);
148 }
149
150 regex::regex(const string& pattern, const string& source)
151 {
152 regex::pattern(pattern);
153 match(source);
154 }
155
156 regex::~regex()
157 {
158 script& script = regex_script();
159
160 script.push_pointer(this);
161 script.push_nil();
162 script.globals().set_field();
163 script.push_pointer(this);
164 script.push_nil();
165 script.registry().set_field();
166 }
167
168
169 string regex::pattern() const
170 {
171 script& script = regex_script();
172 script.push_pointer(this);
173 script::slot saved = script.registry().push_field();
174
175 string pattern;
176 saved.get(pattern);
177
178 saved.pop();
179 return pattern;
180 }
181
182 void regex::pattern(const string& pattern)
183 {
184 script& script = regex_script();
185 script.push_pointer(this);
186 script.push(pattern);
187 script.registry().set_field();
188 }
189
190
191 void regex::match(const string& source)
192 {
193 script& script = regex_script();
194 script.push_pointer(this);
195
196 script.globals().push_field("gmatch");
197 script.push(source);
198 script.push_pointer(this);
199 script.registry().push_field();
200 script.call(2, 1);
201
202 script.globals().set_field();
203 }
204
205 bool regex::get(string& match)
206 {
207 script& script = regex_script();
208 script.push_pointer(this);
209 script::slot value = script.globals().push_field();
210 if (!value.is_function())
211 {
212 script.clear_stack();
213 return false;
214 }
215
216 script.call(0, 1);
217 bool result = value.get(match);
218 script.pop();
219 return result;
220 }
221
222 bool regex::get(std::vector<string>& captures)
223 {
224 script& script = regex_script();
225 script.push_pointer(this);
226 script::slot value = script.globals().push_field();
227 if (!value.is_function())
228 {
229 script.clear_stack();
230 return false;
231 }
232
233 script.call();
234 captures.clear();
235
236 while (value.is_string())
237 {
238 captures.resize(captures.size() + 1);
239 value.get(captures.back());
240 ++value.index;
241 }
242
243 script.clear_stack();
244 return 0 < captures.size();
245 }
246
247
248 bool regex::match(string& match,
249 const string& pattern,
250 const string& source,
251 int position)
252 {
253 script& script = regex_script();
254
255 script::slot value = script.globals().push_field("match");
256 script.push(source);
257 script.push(pattern);
258 ++position; // Lua indices count from one.
259 script.push(position);
260 script.call(3, 1);
261
262 bool result = value.get(match);
263 script.clear_stack();
264 return result;
265 }
266
267 bool regex::match(std::vector<string>& captures,
268 const string& pattern,
269 const string& source,
270 int position)
271 {
272 script& script = regex_script();
273
274 script::slot value = script.globals().push_field("match");
275 script.push(source);
276 script.push(pattern);
277 ++position; // Lua indices count from one.
278 script.push(position);
279 script.call(3);
280
281 captures.clear();
282
283 while (value.is_string())
284 {
285 captures.resize(captures.size() + 1);
286 value.get(captures.back());
287 ++value.index;
288 }
289
290 script.clear_stack();
291 return 0 < captures.size();
292 }
293
294
295 int regex::sub(string& substitution,
296 const string& pattern,
297 const string& source,
298 const string& replacement)
299 {
300 script& script = regex_script();
301
302 script::slot value = script.globals().push_field("gsub");
303 script.push(source);
304 script.push(pattern);
305 script.push(replacement);
306 script.call(3, 2);
307
308 value.get(substitution);
309
310 ++value.index;
311 int count = 0;
312 value.get(count);
313
314 script.clear_stack();
315 return count;
316 }
317
318
319 } // namespace moof
320
This page took 0.04402 seconds and 5 git commands to generate.