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