Om
code_point_string_back_source.cpp
Go to the documentation of this file.
1 
15 #ifndef Om_Source_CodePointStringBackSource_
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(CodePointStringBackSourceTest)
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  CodePointStringBackSource<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  "\xE2\x98\xB9",
54  *theSource
55  );
56  theSource.Pop();
57 
58  BOOST_CHECK_EQUAL(
59  false,
60  !theSource
61  );
62  BOOST_CHECK_EQUAL(
63  "k",
64  *theSource
65  );
66  theSource.Pop();
67 
68  BOOST_CHECK_EQUAL(
69  false,
70  !theSource
71  );
72  BOOST_CHECK_EQUAL(
73  "r",
74  *theSource
75  );
76  theSource.Pop();
77 
78  BOOST_CHECK_EQUAL(
79  false,
80  !theSource
81  );
82  BOOST_CHECK_EQUAL(
83  "\xCC\x88",
84  *theSource
85  );
86  theSource.Pop();
87 
88  BOOST_CHECK_EQUAL(
89  false,
90  !theSource
91  );
92  BOOST_CHECK_EQUAL(
93  "o",
94  *theSource
95  );
96  theSource.Pop();
97 
98  BOOST_CHECK_EQUAL(
99  false,
100  !theSource
101  );
102  BOOST_CHECK_EQUAL(
103  "P",
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  CodePointStringBackSource<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  "!",
131  *theSource
132  );
133  theSource.Pop();
134 
135  BOOST_CHECK_EQUAL(
136  false,
137  !theSource
138  );
139  BOOST_CHECK_EQUAL(
140  "\xEF\xBF\xBD",
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  CodePointStringBackSource<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  "!",
168  *theSource
169  );
170  theSource.Pop();
171 
172  BOOST_CHECK_EQUAL(
173  false,
174  !theSource
175  );
176  BOOST_CHECK_EQUAL(
177  "\xEF\xBF\xBD",
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  CodePointStringBackSource<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  "!",
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  "\xE2\x98\xB9",
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  CodePointStringBackSource<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  "!",
253  *theSource
254  );
255  theSource.Pop();
256 
257  BOOST_CHECK_EQUAL(
258  false,
259  !theSource
260  );
261  BOOST_CHECK_EQUAL(
262  "\xEF\xBF\xBD",
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  CodePointStringBackSource<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::CodePointStringBackSource
318 
319  #define Template_ \
320  template <typename ThisStringIterator>
321 
322  #define Type_ \
323  Om::Source::CodePointStringBackSource<ThisStringIterator>
324 
325 // MARK: public (non-static)
326 
327 Template_
328 inline Type_::CodePointStringBackSource(
329  ThisStringIterator theStringStart,
330  ThisStringIterator const theStringEnd
331 ):
332 thisStringIterator(theStringStart),
333 thisCodePointIterator(theStringEnd),
334 thisCodePointEnd(theStringEnd),
335 thisCodePoint() {
336  this->Update();
337 }
338 
339 Template_
340 inline Type_ & Type_::operator =(CodePointStringBackSource theCodePointStringBackSource) {
341  this->Swap(theCodePointStringBackSource);
342  return *this;
343 }
344 
345 Template_
346 inline bool Type_::operator !() const {
347  return this->thisCodePointEnd == this->thisCodePointIterator;
348 }
349 
350 Template_
351 inline std::string & Type_::operator *() const {
352  assert(this->thisCodePointEnd != this->thisCodePointIterator);
353  return this->thisCodePoint;
354 }
355 
356 Template_
357 inline bool Type_::Equals(CodePointStringBackSource const & theCodePointStringBackSource) const {
358  return this->thisCodePointIterator == theCodePointStringBackSource.thisCodePointIterator;
359 }
360 
361 Template_
362 inline void Type_::Pop() {
363  assert(this->thisCodePointEnd != this->thisCodePointIterator);
364  this->thisCodePointEnd = this->thisCodePointIterator;
365  this->thisCodePoint.clear();
366  this->Update();
367 }
368 
369 Template_
370 inline void Type_::Swap(CodePointStringBackSource & theCodePointStringBackSource) {
371  boost::swap(
372  this->thisStringIterator,
373  theCodePointStringBackSource.thisStringIterator
374  );
375  boost::swap(
376  this->thisCodePointIterator,
377  theCodePointStringBackSource.thisCodePointIterator
378  );
379  boost::swap(
380  this->thisCodePointEnd,
381  theCodePointStringBackSource.thisCodePointEnd
382  );
383  boost::swap(
384  this->thisCodePoint,
385  theCodePointStringBackSource.thisCodePoint
386  );
387 }
388 
389 // MARK: private (non-static)
390 
391 Template_
392 inline void Type_::Update() {
393  assert(this->thisCodePointEnd == this->thisCodePointIterator);
394  assert(
395  this->thisCodePoint.empty()
396  );
397  if (this->thisStringIterator == this->thisCodePointIterator) {
398  return;
399  }
400  for (
401  int theTrailCount = 0;
402  ;
403  ++theTrailCount
404  ) {
405  assert(this->thisStringIterator != this->thisCodePointIterator);
406  char const theCodeUnit = *--this->thisCodePointIterator;
407  if (
408  Utf8::is_lead(theCodeUnit)
409  ) {
410  int const theCorrectTrailCount = Utf8::trail_length(theCodeUnit);
411  if (theCorrectTrailCount == theTrailCount) {
412  this->thisCodePoint.assign(
413  this->thisCodePointIterator,
414  this->thisCodePointEnd
415  );
416  return;
417  }
418  if (theCorrectTrailCount < theTrailCount) {
419  this->thisCodePointIterator += (theCorrectTrailCount + 1);
420  }
421  break;
422  }
423  if (this->thisStringIterator == this->thisCodePointIterator) {
424  break;
425  }
426  }
427  this->thisCodePoint = "\xEF\xBF\xBD" /* Replacement character */;
428 }
429 
430  #undef Type_
431  #undef Template_
432 
433 // MARK: - Om::Source::
434 
435  #define Template_ \
436  template <typename TheStringIterator>
437 
438  #define Type_ \
439  Om::Source::CodePointStringBackSource<TheStringIterator>
440 
441 Template_
442 inline bool Om::Source::operator ==(
443  Type_ const & theFirst,
444  Type_ const & theSecond
445 ) {
446  return theFirst.Equals(theSecond);
447 }
448 
449 Template_
450 inline bool Om::Source::operator !=(
451  Type_ const & theFirst,
452  Type_ const & theSecond
453 ) {
454  return !theFirst.Equals(theSecond);
455 }
456 
457 // MARK: - boost::
458 
459 Template_
460 inline void boost::swap(
461  Type_ & theFirst,
462  Type_ & theSecond
463 ) {
464  theFirst.Swap(theSecond);
465 }
466 
467  #undef Type_
468  #undef Template_
469 
470 #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.