Om
code_point_string_front_source.cpp
Go to the documentation of this file.
1 
15 #ifndef Om_Source_CodePointStringFrontSource_
16 
18 
19  #ifdef Om_Macro_Test_
20 
21  #ifndef Om_Macro_Precompilation_
22 
23  #include "boost/test/unit_test.hpp"
24 
25  #endif
26 
27 namespace Om {
28 
29  namespace Source {
30 
31  BOOST_AUTO_TEST_SUITE(CodePointStringFrontSourceTest)
32 
33  BOOST_AUTO_TEST_CASE(ValidTest) {
34  std::string theString(
35  "P" /* ASCII character */
36  "o"
37  "\xCC\x88" /* Combining multi-byte character */
38  "r" /* ASCII character */
39  "k" /* ASCII character */
40  "\xE2\x98\xB9" /* Non-combining multi-byte character */
41  );
42 
43  CodePointStringFrontSource<std::string::const_iterator> theSource(
44  theString.begin(),
45  theString.end()
46  );
47 
48  BOOST_CHECK_EQUAL(
49  false,
50  !theSource
51  );
52  BOOST_CHECK_EQUAL(
53  "P",
54  *theSource
55  );
56  theSource.Pop();
57 
58  BOOST_CHECK_EQUAL(
59  false,
60  !theSource
61  );
62  BOOST_CHECK_EQUAL(
63  "o",
64  *theSource
65  );
66  theSource.Pop();
67 
68  BOOST_CHECK_EQUAL(
69  false,
70  !theSource
71  );
72  BOOST_CHECK_EQUAL(
73  "\xCC\x88",
74  *theSource
75  );
76  theSource.Pop();
77 
78  BOOST_CHECK_EQUAL(
79  false,
80  !theSource
81  );
82  BOOST_CHECK_EQUAL(
83  "r",
84  *theSource
85  );
86  theSource.Pop();
87 
88  BOOST_CHECK_EQUAL(
89  false,
90  !theSource
91  );
92  BOOST_CHECK_EQUAL(
93  "k",
94  *theSource
95  );
96  theSource.Pop();
97 
98  BOOST_CHECK_EQUAL(
99  false,
100  !theSource
101  );
102  BOOST_CHECK_EQUAL(
103  "\xE2\x98\xB9",
104  *theSource
105  );
106  theSource.Pop();
107 
108  BOOST_CHECK_EQUAL(
109  true,
110  !theSource
111  );
112  }
113 
114  BOOST_AUTO_TEST_CASE(InvalidNoTrailingTest) {
115  std::string theString(
116  "\xE2"
117  "!"
118  );
119 
120  CodePointStringFrontSource<std::string::const_iterator> theSource(
121  theString.begin(),
122  theString.end()
123  );
124 
125  BOOST_CHECK_EQUAL(
126  false,
127  !theSource
128  );
129  BOOST_CHECK_EQUAL(
130  "\xEF\xBF\xBD",
131  *theSource
132  );
133  theSource.Pop();
134 
135  BOOST_CHECK_EQUAL(
136  false,
137  !theSource
138  );
139  BOOST_CHECK_EQUAL(
140  "!",
141  *theSource
142  );
143  theSource.Pop();
144 
145  BOOST_CHECK_EQUAL(
146  true,
147  !theSource
148  );
149  }
150 
151  BOOST_AUTO_TEST_CASE(InvalidInsufficientTrailingTest) {
152  std::string theString(
153  "\xE2\x98"
154  "!"
155  );
156 
157  CodePointStringFrontSource<std::string::const_iterator> theSource(
158  theString.begin(),
159  theString.end()
160  );
161 
162  BOOST_CHECK_EQUAL(
163  false,
164  !theSource
165  );
166  BOOST_CHECK_EQUAL(
167  "\xEF\xBF\xBD",
168  *theSource
169  );
170  theSource.Pop();
171 
172  BOOST_CHECK_EQUAL(
173  false,
174  !theSource
175  );
176  BOOST_CHECK_EQUAL(
177  "!",
178  *theSource
179  );
180  theSource.Pop();
181 
182  BOOST_CHECK_EQUAL(
183  true,
184  !theSource
185  );
186  }
187 
188  BOOST_AUTO_TEST_CASE(InvalidExtraTrailingTest) {
189  std::string theString(
190  "\xE2\x98\xB9" /* Valid */
191  "\xB9" /* Invalid */
192  "!"
193  );
194 
195  CodePointStringFrontSource<std::string::const_iterator> theSource(
196  theString.begin(),
197  theString.end()
198  );
199 
200  BOOST_CHECK_EQUAL(
201  false,
202  !theSource
203  );
204  BOOST_CHECK_EQUAL(
205  "\xE2\x98\xB9",
206  *theSource
207  );
208  theSource.Pop();
209 
210  BOOST_CHECK_EQUAL(
211  false,
212  !theSource
213  );
214  BOOST_CHECK_EQUAL(
215  "\xEF\xBF\xBD",
216  *theSource
217  );
218  theSource.Pop();
219 
220  BOOST_CHECK_EQUAL(
221  false,
222  !theSource
223  );
224  BOOST_CHECK_EQUAL(
225  "!",
226  *theSource
227  );
228  theSource.Pop();
229 
230  BOOST_CHECK_EQUAL(
231  true,
232  !theSource
233  );
234  }
235 
236  BOOST_AUTO_TEST_CASE(InvalidMissingLeadingTest) {
237  std::string theString(
238  "\xB9" /* Invalid */
239  "!"
240  );
241 
242  CodePointStringFrontSource<std::string::const_iterator> theSource(
243  theString.begin(),
244  theString.end()
245  );
246 
247  BOOST_CHECK_EQUAL(
248  false,
249  !theSource
250  );
251  BOOST_CHECK_EQUAL(
252  "\xEF\xBF\xBD",
253  *theSource
254  );
255  theSource.Pop();
256 
257  BOOST_CHECK_EQUAL(
258  false,
259  !theSource
260  );
261  BOOST_CHECK_EQUAL(
262  "!",
263  *theSource
264  );
265  theSource.Pop();
266 
267  BOOST_CHECK_EQUAL(
268  true,
269  !theSource
270  );
271  }
272 
273  BOOST_AUTO_TEST_CASE(InvalidEarlyTerminationTest) {
274  std::string theString(
275  "\xE2\x98" /* Invalid */
276  );
277 
278  CodePointStringFrontSource<std::string::const_iterator> theSource(
279  theString.begin(),
280  theString.end()
281  );
282 
283  BOOST_CHECK_EQUAL(
284  false,
285  !theSource
286  );
287  BOOST_CHECK_EQUAL(
288  "\xEF\xBF\xBD",
289  *theSource
290  );
291  theSource.Pop();
292 
293  BOOST_CHECK_EQUAL(
294  true,
295  !theSource
296  );
297  }
298 
299  BOOST_AUTO_TEST_SUITE_END()
300 
301  }
302 
303 }
304 
305  #endif
306 
307 #else
308 
309  #include "om/utf8.hpp"
310 
311  #ifndef Om_Macro_Precompilation_
312 
313  #include "boost/swap.hpp"
314 
315  #endif
316 
317 // MARK: - Om::Source::CodePointStringFrontSource
318 
319  #define Template_ \
320  template <typename ThisStringIterator>
321 
322  #define Type_ \
323  Om::Source::CodePointStringFrontSource<ThisStringIterator>
324 
325 // MARK: public (non-static)
326 
327 Template_
328 inline Type_::CodePointStringFrontSource(
329  ThisStringIterator theStringStart,
330  ThisStringIterator const theStringEnd
331 ):
332 thisStringIterator(theStringStart),
333 thisStringEnd(theStringEnd),
334 thisCodePoint() {
335  this->Update();
336 }
337 
338 Template_
339 inline Type_ & Type_::operator =(CodePointStringFrontSource theCodePointStringFrontSource) {
340  this->Swap(theCodePointStringFrontSource);
341  return *this;
342 }
343 
344 Template_
345 inline bool Type_::operator !() const {
346  return this->thisCodePoint.empty();
347 }
348 
349 Template_
350 inline std::string & Type_::operator *() const {
351  return this->thisCodePoint;
352 }
353 
354 Template_
355 inline bool Type_::Equals(CodePointStringFrontSource const & theCodePointStringFrontSource) const {
356  return this->thisStringIterator == theCodePointStringFrontSource.thisStringIterator;
357 }
358 
359 Template_
360 inline void Type_::Pop() {
361  this->thisCodePoint.clear();
362  this->Update();
363 }
364 
365 Template_
366 inline void Type_::Swap(CodePointStringFrontSource & theCodePointStringFrontSource) {
367  boost::swap(
368  this->thisStringIterator,
369  theCodePointStringFrontSource.thisStringIterator
370  );
371  boost::swap(
372  this->thisStringEnd,
373  theCodePointStringFrontSource.thisStringEnd
374  );
375  boost::swap(
376  this->thisCodePoint,
377  theCodePointStringFrontSource.thisCodePoint
378  );
379 }
380 
381 // MARK: private (non-static)
382 
383 Template_
384 inline void Type_::Update() {
385  assert(
386  this->thisCodePoint.empty()
387  );
388  if (this->thisStringEnd == this->thisStringIterator) {
389  return;
390  }
391  char theCodeUnit = *this->thisStringIterator;
392  ++this->thisStringIterator;
393  if (
394  Utf8::is_lead(theCodeUnit)
395  ) {
396  this->thisCodePoint.push_back(theCodeUnit);
397  for (
398  int theTrailCount = Utf8::trail_length(theCodeUnit);
399  ;
400  --theTrailCount
401  ) {
402  if (!theTrailCount) {
403  return;
404  }
405  if (
406  this->thisStringEnd == this->thisStringIterator ||
407  !Utf8::is_trail(theCodeUnit = *this->thisStringIterator)
408  ) {
409  break;
410  }
411  this->thisCodePoint.push_back(theCodeUnit);
412  ++this->thisStringIterator;
413  }
414  }
415  this->thisCodePoint = "\xEF\xBF\xBD" /* Replacement character */;
416 }
417 
418  #undef Type_
419  #undef Template_
420 
421 // MARK: - Om::Source::
422 
423  #define Template_ \
424  template <typename TheStringIterator>
425 
426  #define Type_ \
427  Om::Source::CodePointStringFrontSource<TheStringIterator>
428 
429 Template_
430 inline bool Om::Source::operator ==(
431  Type_ const & theFirst,
432  Type_ const & theSecond
433 ) {
434  return theFirst.Equals(theSecond);
435 }
436 
437 Template_
438 inline bool Om::Source::operator !=(
439  Type_ const & theFirst,
440  Type_ const & theSecond
441 ) {
442  return !theFirst.Equals(theSecond);
443 }
444 
445 // MARK: - boost::
446 
447 Template_
448 inline void boost::swap(
449  Type_ & theFirst,
450  Type_ & theSecond
451 ) {
452  theFirst.Swap(theSecond);
453 }
454 
455  #undef Type_
456  #undef Template_
457 
458 #endif
bool operator==(CodePointSource< TheCodeUnitIterator > const &, CodePointSource< TheCodeUnitIterator > const &)
bool operator!=(CodePointSource< TheCodeUnitIterator > const &, CodePointSource< TheCodeUnitIterator > const &)
The Om library.
Definition: code_point.hpp:26
void swap(Om::Language::Expression &, Om::Language::Expression &)
Om header file.