1//
2// StringTest.cpp
3//
4// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
5// and Contributors.
6//
7// SPDX-License-Identifier: BSL-1.0
8//
9
10
11#include "StringTest.h"
12#include "Poco/CppUnit/TestCaller.h"
13#include "Poco/CppUnit/TestSuite.h"
14#include "Poco/String.h"
15#include "Poco/JSONString.h"
16#include "Poco/Format.h"
17#include "Poco/MemoryStream.h"
18#include "Poco/Stopwatch.h"
19#include "Poco/FPEnvironment.h"
20#include "Poco/Exception.h"
21#include <iostream>
22#include <sstream>
23#include <iomanip>
24#include <cstdio>
25#include <climits>
26#include <map>
27#include <set>
28
29
30using Poco::trimLeft;
31using Poco::trimLeftInPlace;
32using Poco::trimRight;
33using Poco::trimRightInPlace;
34using Poco::trim;
35using Poco::trimInPlace;
36using Poco::toUpper;
37using Poco::toUpperInPlace;
38using Poco::toLower;
39using Poco::toLowerInPlace;
40using Poco::icompare;
41using Poco::istring;
42using Poco::isubstr;
43using Poco::translate;
44using Poco::translateInPlace;
45using Poco::replace;
46using Poco::replaceInPlace;
47using Poco::remove;
48using Poco::removeInPlace;
49using Poco::cat;
50using Poco::startsWith;
51using Poco::endsWith;
52using Poco::strToInt;
53using Poco::strToFloat;
54using Poco::strToDouble;
55using Poco::intToStr;
56using Poco::uIntToStr;
57using Poco::floatToStr;
58using Poco::doubleToStr;
59using Poco::thousandSeparator;
60using Poco::decimalSeparator;
61using Poco::format;
62using Poco::toJSON;
63using Poco::CILess;
64using Poco::MemoryInputStream;
65using Poco::Stopwatch;
66using Poco::RangeException;
67using Poco::isIntOverflow;
68using Poco::isSafeIntCast;
69using Poco::safeIntCast;
70using Poco::FPEnvironment;
71
72
73StringTest::StringTest(const std::string& rName): CppUnit::TestCase(rName)
74{
75}
76
77
78StringTest::~StringTest()
79{
80}
81
82
83void StringTest::testTrimLeft()
84{
85 {
86 std::string s = "abc";
87 assertTrue (trimLeft(s) == "abc");
88 }
89 std::string s = " abc ";
90 assertTrue (trimLeft(s) == "abc ");
91 {
92 std::string s = " ab c ";
93 assertTrue (trimLeft(s) == "ab c ");
94 }
95}
96
97
98void StringTest::testTrimLeftInPlace()
99{
100 {
101 std::string s = "abc";
102 assertTrue (trimLeftInPlace(s) == "abc");
103 }
104 {
105 std::string s = " abc ";
106 assertTrue (trimLeftInPlace(s) == "abc ");
107 }
108 {
109 std::string s = " ab c ";
110 assertTrue (trimLeftInPlace(s) == "ab c ");
111 }
112}
113
114
115void StringTest::testTrimRight()
116{
117 {
118 std::string s = "abc";
119 assertTrue (trimRight(s) == "abc");
120 }
121 {
122 std::string s = " abc ";
123 assertTrue (trimRight(s) == " abc");
124 }
125 {
126 std::string s = " ab c ";
127 assertTrue (trimRight(s) == " ab c");
128 }
129}
130
131
132void StringTest::testTrimRightInPlace()
133{
134 {
135 std::string s = "abc";
136 assertTrue (trimRightInPlace(s) == "abc");
137 }
138 {
139 std::string s = " abc ";
140 assertTrue (trimRightInPlace(s) == " abc");
141 }
142 {
143 std::string s = " ab c ";
144 assertTrue (trimRightInPlace(s) == " ab c");
145 }
146}
147
148
149void StringTest::testTrim()
150{
151 {
152 std::string s = "abc";
153 assertTrue (trim(s) == "abc");
154 }
155 {
156 std::string s = "abc ";
157 assertTrue (trim(s) == "abc");
158 }
159 {
160 std::string s = " ab c ";
161 assertTrue (trim(s) == "ab c");
162 }
163}
164
165
166void StringTest::testTrimInPlace()
167{
168 {
169 std::string s = "abc";
170 assertTrue (trimInPlace(s) == "abc");
171 }
172 {
173 std::string s = " abc ";
174 assertTrue (trimInPlace(s) == "abc");
175 }
176 {
177 std::string s = " ab c ";
178 assertTrue (trimInPlace(s) == "ab c");
179 }
180}
181
182
183void StringTest::testToUpper()
184{
185 {
186 std::string s = "abc";
187 assertTrue (toUpper(s) == "ABC");
188 }
189 {
190 std::string s = "Abc";
191 assertTrue (toUpper(s) == "ABC");
192 }
193 {
194 std::string s = "abc";
195 assertTrue (toUpperInPlace(s) == "ABC");
196 }
197 {
198 std::string s = "Abc";
199 assertTrue (toUpperInPlace(s) == "ABC");
200 }
201}
202
203
204void StringTest::testToLower()
205{
206 {
207 std::string s = "ABC";
208 assertTrue (toLower(s) == "abc");
209 }
210 {
211 std::string s = "aBC";
212 assertTrue (toLower(s) == "abc");
213 }
214 {
215 std::string s = "ABC";
216 assertTrue (toLowerInPlace(s) == "abc");
217 }
218 {
219 std::string s = "aBC";
220 assertTrue (toLowerInPlace(s) == "abc");
221 }
222}
223
224
225void StringTest::testIstring()
226{
227 istring is1 = "AbC";
228 istring is2 = "aBc";
229 assertTrue (is1 == is2);
230
231 const char c1[] = { 'G', 0, (char) 0xFC, 'n', 't', 'e', 'r', '\0' };
232 const char c2[] = { 'g', 0, (char) 0xDC, 'N', 'T', 'E', 'R', '\0' };
233 is1 = c1;
234 is2 = c2;
235 assertTrue (is1 == is2);
236 is1[0] = 'f';
237 assertTrue (is1 < is2);
238 is1[0] = 'F';
239 assertTrue (is1 < is2);
240 is1[0] = 'H';
241 assertTrue (is1 > is2);
242 is1[0] = 'h';
243 assertTrue (is1 > is2);
244
245 is1 = "aAaBbBcCc";
246 is2 = "bbb";
247 assertTrue (isubstr(is1, is2) == 3);
248 is2 = "bC";
249 assertTrue (isubstr(is1, is2) == 5);
250 is2 = "xxx";
251 assertTrue (isubstr(is1, is2) == istring::npos);
252}
253
254
255void StringTest::testIcompare()
256{
257 std::string s1 = "AAA";
258 std::string s2 = "aaa";
259 std::string s3 = "bbb";
260 std::string s4 = "cCcCc";
261 std::string s5;
262 assertTrue (icompare(s1, s2) == 0);
263 assertTrue (icompare(s1, s3) < 0);
264 assertTrue (icompare(s1, s4) < 0);
265 assertTrue (icompare(s3, s1) > 0);
266 assertTrue (icompare(s4, s2) > 0);
267 assertTrue (icompare(s2, s4) < 0);
268 assertTrue (icompare(s1, s5) > 0);
269 assertTrue (icompare(s5, s4) < 0);
270
271 std::string ss1 = "xxAAAzz";
272 std::string ss2 = "YaaaX";
273 std::string ss3 = "YbbbX";
274 assertTrue (icompare(ss1, 2, 3, ss2, 1, 3) == 0);
275 assertTrue (icompare(ss1, 2, 3, ss3, 1, 3) < 0);
276 assertTrue (icompare(ss1, 2, 3, ss2, 1) == 0);
277 assertTrue (icompare(ss1, 2, 3, ss3, 1) < 0);
278 assertTrue (icompare(ss1, 2, 2, ss2, 1, 3) < 0);
279 assertTrue (icompare(ss1, 2, 2, ss2, 1, 2) == 0);
280 assertTrue (icompare(ss3, 1, 3, ss1, 2, 3) > 0);
281
282 assertTrue (icompare(s1, s2.c_str()) == 0);
283 assertTrue (icompare(s1, s3.c_str()) < 0);
284 assertTrue (icompare(s1, s4.c_str()) < 0);
285 assertTrue (icompare(s3, s1.c_str()) > 0);
286 assertTrue (icompare(s4, s2.c_str()) > 0);
287 assertTrue (icompare(s2, s4.c_str()) < 0);
288 assertTrue (icompare(s1, s5.c_str()) > 0);
289 assertTrue (icompare(s5, s4.c_str()) < 0);
290
291 assertTrue (icompare(ss1, 2, 3, "aaa") == 0);
292 assertTrue (icompare(ss1, 2, 2, "aaa") < 0);
293 assertTrue (icompare(ss1, 2, 3, "AAA") == 0);
294 assertTrue (icompare(ss1, 2, 2, "bb") < 0);
295
296 assertTrue (icompare(ss1, 2, "aaa") > 0);
297}
298
299
300void StringTest::testCILessThan()
301{
302 typedef std::map<std::string, int, CILess> CIMapType;
303 CIMapType ciMap;
304
305 ciMap["z"] = 1;
306 ciMap["b"] = 2;
307 ciMap["A"] = 3;
308 ciMap["Z"] = 4;
309
310 assertTrue (ciMap.size() == 3);
311 CIMapType::iterator it = ciMap.begin();
312 assertTrue (it->first == "A"); ++it;
313 assertTrue (it->first == "b"); ++it;
314 assertTrue (it->first == "z");
315 assertTrue (it->second == 4);
316
317 typedef std::set<std::string, CILess> CISetType;
318
319 CISetType ciSet;
320 ciSet.insert("z");
321 ciSet.insert("b");
322 ciSet.insert("A");
323 ciSet.insert("Z");
324
325 assertTrue (ciSet.size() == 3);
326 CISetType::iterator sIt = ciSet.begin();
327 assertTrue (*sIt == "A"); ++sIt;
328 assertTrue (*sIt == "b"); ++sIt;
329 assertTrue (*sIt == "z");
330}
331
332
333void StringTest::testTranslate()
334{
335 std::string s = "aabbccdd";
336 assertTrue (translate(s, "abc", "ABC") == "AABBCCdd");
337 assertTrue (translate(s, "abc", "AB") == "AABBdd");
338 assertTrue (translate(s, "abc", "") == "dd");
339 assertTrue (translate(s, "cba", "CB") == "BBCCdd");
340 assertTrue (translate(s, "", "CB") == "aabbccdd");
341}
342
343
344void StringTest::testTranslateInPlace()
345{
346 std::string s = "aabbccdd";
347 translateInPlace(s, "abc", "ABC");
348 assertTrue (s == "AABBCCdd");
349}
350
351
352void StringTest::testReplace()
353{
354 std::string s("aabbccdd");
355
356 assertTrue (replace(s, std::string("aa"), std::string("xx")) == "xxbbccdd");
357 assertTrue (replace(s, std::string("bb"), std::string("xx")) == "aaxxccdd");
358 assertTrue (replace(s, std::string("dd"), std::string("xx")) == "aabbccxx");
359 assertTrue (replace(s, std::string("bbcc"), std::string("xx")) == "aaxxdd");
360 assertTrue (replace(s, std::string("b"), std::string("xx")) == "aaxxxxccdd");
361 assertTrue (replace(s, std::string("bb"), std::string("")) == "aaccdd");
362 assertTrue (replace(s, std::string("b"), std::string("")) == "aaccdd");
363 assertTrue (replace(s, std::string("ee"), std::string("xx")) == "aabbccdd");
364 assertTrue (replace(s, std::string("dd"), std::string("")) == "aabbcc");
365
366 assertTrue (replace(s, "aa", "xx") == "xxbbccdd");
367 assertTrue (replace(s, "bb", "xx") == "aaxxccdd");
368 assertTrue (replace(s, "dd", "xx") == "aabbccxx");
369 assertTrue (replace(s, "bbcc", "xx") == "aaxxdd");
370 assertTrue (replace(s, "bb", "") == "aaccdd");
371 assertTrue (replace(s, "b", "") == "aaccdd");
372 assertTrue (replace(s, "ee", "xx") == "aabbccdd");
373 assertTrue (replace(s, "dd", "") == "aabbcc");
374
375 s = "aabbaabb";
376 assertTrue (replace(s, std::string("aa"), std::string("")) == "bbbb");
377 assertTrue (replace(s, std::string("a"), std::string("")) == "bbbb");
378 assertTrue (replace(s, std::string("a"), std::string("x")) == "xxbbxxbb");
379 assertTrue (replace(s, std::string("a"), std::string("xx")) == "xxxxbbxxxxbb");
380 assertTrue (replace(s, std::string("aa"), std::string("xxx")) == "xxxbbxxxbb");
381
382 assertTrue (replace(s, std::string("aa"), std::string("xx"), 2) == "aabbxxbb");
383
384 assertTrue (replace(s, "aa", "") == "bbbb");
385 assertTrue (replace(s, "a", "") == "bbbb");
386 assertTrue (replace(s, "a", "x") == "xxbbxxbb");
387 assertTrue (replace(s, "a", "xx") == "xxxxbbxxxxbb");
388 assertTrue (replace(s, "aa", "xxx") == "xxxbbxxxbb");
389
390 assertTrue (replace(s, "aa", "xx", 2) == "aabbxxbb");
391 assertTrue (replace(s, 'a', 'x', 2) == "aabbxxbb");
392 assertTrue (remove(s, 'a', 2) == "aabbbb");
393 assertTrue (remove(s, 'a') == "bbbb");
394 assertTrue (remove(s, 'b', 2) == "aaaa");
395}
396
397
398void StringTest::testReplaceInPlace()
399{
400 std::string s("aabbccdd");
401
402 replaceInPlace(s, std::string("aa"), std::string("xx"));
403 assertTrue (s == "xxbbccdd");
404
405 s = "aabbccdd";
406 replaceInPlace(s, 'a', 'x');
407 assertTrue (s == "xxbbccdd");
408 replaceInPlace(s, 'x');
409 assertTrue (s == "bbccdd");
410 removeInPlace(s, 'b', 1);
411 assertTrue (s == "bccdd");
412 removeInPlace(s, 'd');
413 assertTrue (s == "bcc");
414}
415
416
417void StringTest::testCat()
418{
419 std::string s1("one");
420 std::string s2("two");
421 std::string s3("three");
422 std::string s4("four");
423 std::string s5("five");
424 std::string s6("six");
425
426 assertTrue (cat(s1, s2) == "onetwo");
427 assertTrue (cat(s1, s2, s3) == "onetwothree");
428 assertTrue (cat(s1, s2, s3, s4) == "onetwothreefour");
429 assertTrue (cat(s1, s2, s3, s4, s5) == "onetwothreefourfive");
430 assertTrue (cat(s1, s2, s3, s4, s5, s6) == "onetwothreefourfivesix");
431
432 std::vector<std::string> vec;
433 assertTrue (cat(std::string(), vec.begin(), vec.end()) == "");
434 assertTrue (cat(std::string(","), vec.begin(), vec.end()) == "");
435 vec.push_back(s1);
436 assertTrue (cat(std::string(","), vec.begin(), vec.end()) == "one");
437 vec.push_back(s2);
438 assertTrue (cat(std::string(","), vec.begin(), vec.end()) == "one,two");
439 vec.push_back(s3);
440 assertTrue (cat(std::string(","), vec.begin(), vec.end()) == "one,two,three");
441}
442
443
444void StringTest::testStartsWith()
445{
446 std::string s1("o");
447
448 assertTrue (startsWith(s1, std::string("o")));
449 assertTrue (startsWith(s1, std::string("")));
450
451 assertTrue (!startsWith(s1, std::string("O")));
452 assertTrue (!startsWith(s1, std::string("1")));
453
454 std::string s2("");
455
456 assertTrue (startsWith(s2, std::string("")));
457
458 assertTrue (!startsWith(s2, std::string("o")));
459
460 std::string s3("oO");
461
462 assertTrue (startsWith(s3, std::string("o")));
463
464 assertTrue (!startsWith(s3, std::string(" o")));
465}
466
467
468void StringTest::testEndsWith()
469{
470 std::string s1("o");
471
472 assertTrue (endsWith(s1, std::string("o")));
473 assertTrue (endsWith(s1, std::string("")));
474
475 assertTrue (!endsWith(s1, std::string("O")));
476 assertTrue (!endsWith(s1, std::string("1")));
477
478
479 std::string s2("");
480
481 assertTrue (endsWith(s2, std::string("")));
482
483 assertTrue (!endsWith(s2, std::string("o")));
484
485 std::string s3("Oo");
486
487 assertTrue (endsWith(s3, std::string("o")));
488
489 assertTrue (!endsWith(s3, std::string("o ")));
490}
491
492
493void StringTest::testStringToInt()
494{
495//gcc on Mac emits warnings that cannot be suppressed
496#ifndef POCO_OS_FAMILY_BSD
497 stringToInt<Poco::Int8>();
498 stringToInt<Poco::UInt8>();
499 stringToInt<Poco::Int16>();
500 stringToInt<Poco::UInt16>();
501#endif
502 stringToInt<Poco::Int32>();
503 stringToInt<Poco::UInt32>();
504#if defined(POCO_HAVE_INT64)
505 stringToInt<Poco::Int64>();
506 stringToInt<Poco::UInt64>();
507#endif
508}
509
510
511void StringTest::testStringToFloat()
512{
513 float result;
514 std::string sep(".,");
515
516 for (int i = 0; i < 2; ++i)
517 {
518 char ds = sep[i];
519 for (int j = 0; j < 2; ++j)
520 {
521 char ts = sep[j];
522 if (ts == ds) continue;
523
524 assertTrue (strToFloat("1", result, ds, ts));
525 assertEqualDelta(1.0, result, 0.01);
526 assertTrue (strToFloat(format("%c1", ds), result, ds, ts));
527 assertEqualDelta(.1, result, 0.01);
528 assertTrue (strToFloat(format("1%c", ds), result, ds, ts));
529 assertEqualDelta(1., result, 0.01);
530 assertTrue (strToFloat("0", result, ds, ts));
531 assertEqualDelta(0.0, result, 0.01);
532 assertTrue (strToFloat(format("0%c", ds), result, ds, ts));
533 assertEqualDelta(0.0, result, 0.01);
534 assertTrue (strToFloat(format("%c0", ds), result, ds, ts));
535 assertEqualDelta(0.0, result, 0.01);
536 assertTrue (strToFloat(format("0%c0", ds), result, ds, ts));
537 assertEqualDelta(0.0, result, 0.01);
538 assertTrue (strToFloat(format("0%c0", ds), result, ds, ts));
539 assertEqualDelta(0., result, 0.01);
540 assertTrue (strToFloat(format("0%c0", ds), result, ds, ts));
541 assertEqualDelta(.0, result, 0.01);
542 assertTrue (strToFloat(format("12%c34", ds), result, ds, ts));
543 assertEqualDelta(12.34, result, 0.01);
544 assertTrue (strToFloat(format("12%c34", ds), result, ds, ts));
545 assertEqualDelta(12.34, result, 0.01);
546 assertTrue (strToFloat(format("-12%c34", ds), result, ds, ts));
547 assertEqualDelta(-12.34, result, 0.01);
548 assertTrue (strToFloat(format("%c34", ds), result, ds, ts));
549 assertEqualDelta(.34, result, 0.01);
550 assertTrue (strToFloat(format("-%c34", ds), result, ds, ts));
551 assertEqualDelta(-.34, result, 0.01);
552 assertTrue (strToFloat(format("12%c", ds), result, ds, ts));
553 assertEqualDelta(12., result, 0.01);
554 assertTrue (strToFloat(format("-12%c", ds), result, ds, ts));
555 assertEqualDelta(-12., result, 0.01);
556 assertTrue (strToFloat("12", result, ds, ts));
557 assertEqualDelta(12, result, 0.01);
558 assertTrue (strToFloat("-12", result, ds, ts));
559 assertEqualDelta(-12, result, 0.01);
560 assertTrue (strToFloat(format("12%c34", ds), result, ds, ts));
561 assertEqualDelta(12.34, result, 0.01);
562
563 assertTrue (strToFloat(format("1%c234%c34", ts, ds), result, ds, ts));
564 assertEqualDelta(1234.34, result, 0.01);
565 assertTrue (strToFloat(format("12%c345%c34", ts, ds), result, ds, ts));
566 assertEqualDelta(12345.34, result, 0.01);
567 assertTrue (strToFloat(format("123%c456%c34", ts, ds), result, ds, ts));
568 assertEqualDelta(123456.34, result, 0.01);
569 assertTrue (strToFloat(format("1%c234%c567%c34", ts, ts, ds), result, ds, ts));
570
571 if ((std::numeric_limits<double>::max() / 10) < 1.23456e10)
572 fail ("test value larger than max value for this platform");
573 else
574 {
575 float d = 12e34f;
576 assertTrue (strToFloat(format("12e34", ds), result, ds, ts));
577 assertEqualDelta(d, result, 0.01e34);
578
579 d = 1.234e30f;
580 assertTrue (strToFloat(format("1%c234e30", ds), result, ds, ts));
581 assertEqualDelta(d, result, 0.01);
582 assertTrue (strToFloat(format("1%c234E+30", ds), result, ds, ts));
583 assertEqualDelta(d, result, 0.01);
584 }
585
586 float d = 12.34e-10f;
587 assertTrue (strToFloat(format("12%c34e-10", ds), result, ds, ts));
588 assertEqualDelta(d, result, 0.01);
589 assertTrue (strToFloat(format("-12%c34", ds), result, ds, ts));
590 assertEqualDelta(-12.34, result, 0.01);
591
592 assertTrue (strToFloat(format(" 12%c34", ds), result, ds, ts));
593 assertEqualDelta(12.34, result, 0.01);
594 assertTrue (strToFloat(format("12%c34 ", ds), result, ds, ts));
595 assertEqualDelta(12.34, result, 0.01);
596 assertTrue (strToFloat(format(" 12%c34 ", ds), result, ds, ts));
597 assertEqualDelta(12.34, result, 0.01);
598 }
599 }
600
601 assertTrue (std::isnan(strToFloat("nan")));
602 assertTrue (std::isnan(strToFloat("xNaNy")));
603 assertTrue (!std::isnan(strToFloat("inf")));
604 assertTrue (!std::isnan(strToFloat("-inf")));
605 assertTrue (std::isnan(strToFloat("infinity")));
606 assertTrue (!std::isnan(strToFloat("infinity", "infinity")));
607 assertTrue (!std::isnan(strToFloat("-infinity", "infinity")));
608 assertTrue (std::isnan(strToFloat("Inf")));
609 assertTrue (!std::isnan(strToFloat("Inf", "Inf")));
610
611 assertTrue (std::isinf(strToFloat("inf")));
612 assertTrue (std::isinf(strToFloat("-inf")));
613 assertTrue (std::isinf(strToFloat("infinity", "infinity")));
614 assertTrue (std::isinf(strToFloat("-infinity", "infinity")));
615 assertTrue (!std::isinf(strToFloat("Inf")));
616 assertTrue (std::isinf(strToFloat("Inf", "Inf")));
617
618 assertTrue (FPEnvironment::isNaN(strToFloat("nan")));
619 assertTrue (FPEnvironment::isNaN(strToFloat("xNaNy")));
620 assertTrue (!FPEnvironment::isNaN(strToFloat("inf")));
621 assertTrue (!FPEnvironment::isNaN(strToFloat("-inf")));
622 assertTrue (FPEnvironment::isNaN(strToFloat("infinity")));
623 assertTrue (!FPEnvironment::isNaN(strToFloat("infinity", "infinity")));
624 assertTrue (!FPEnvironment::isNaN(strToFloat("-infinity", "infinity")));
625 assertTrue (!FPEnvironment::isNaN(strToFloat("1.23")));
626 assertTrue (FPEnvironment::isNaN(strToFloat("Inf")));
627 assertTrue (!FPEnvironment::isNaN(strToFloat("Inf", "Inf")));
628
629 assertTrue (FPEnvironment::isInfinite(strToFloat("inf")));
630 assertTrue (FPEnvironment::isInfinite(strToFloat("-inf")));
631 assertTrue (FPEnvironment::isInfinite(strToFloat("infinity", "infinity")));
632 assertTrue (FPEnvironment::isInfinite(strToFloat("-infinity", "infinity")));
633 assertTrue (!FPEnvironment::isInfinite(strToFloat("1.23")));
634 assertTrue (!FPEnvironment::isInfinite(strToFloat("abc")));
635 assertTrue (FPEnvironment::isInfinite(strToFloat("Inf", "Inf")));
636}
637
638
639void StringTest::testStringToDouble()
640{
641 double result;
642 std::string sep(".,");
643
644 for (int i = 0; i < 2; ++i)
645 {
646 char ds = sep[i];
647 for (int j = 0; j < 2; ++j)
648 {
649 char ts = sep[j];
650 if (ts == ds) continue;
651
652 assertTrue (strToDouble("1", result, ds, ts));
653 assertEqualDelta(1.0, result, 0.01);
654 assertTrue (strToDouble(format("%c1", ds), result, ds, ts));
655 assertEqualDelta(.1, result, 0.01);
656 assertTrue (strToDouble(format("1%c", ds), result, ds, ts));
657 assertEqualDelta(1., result, 0.01);
658 assertTrue (strToDouble("0", result, ds, ts));
659 assertEqualDelta(0.0, result, 0.01);
660 assertTrue (strToDouble(format("0%c", ds), result, ds, ts));
661 assertEqualDelta(0.0, result, 0.01);
662 assertTrue (strToDouble(format("%c0", ds), result, ds, ts));
663 assertEqualDelta(0.0, result, 0.01);
664 assertTrue (strToDouble(format("0%c0", ds), result, ds, ts));
665 assertEqualDelta(0.0, result, 0.01);
666 assertTrue (strToDouble(format("0%c0", ds), result, ds, ts));
667 assertEqualDelta(0., result, 0.01);
668 assertTrue (strToDouble(format("0%c0", ds), result, ds, ts));
669 assertEqualDelta(.0, result, 0.01);
670 assertTrue (strToDouble(format("12%c34", ds), result, ds, ts));
671 assertEqualDelta(12.34, result, 0.01);
672 assertTrue (strToDouble(format("12%c34", ds), result, ds, ts));
673 assertEqualDelta(12.34, result, 0.01);
674 assertTrue (strToDouble(format("-12%c34", ds), result, ds, ts));
675 assertEqualDelta(-12.34, result, 0.01);
676 assertTrue (strToDouble(format("%c34", ds), result, ds, ts));
677 assertEqualDelta(.34, result, 0.01);
678 assertTrue (strToDouble(format("-%c34", ds), result, ds, ts));
679 assertEqualDelta(-.34, result, 0.01);
680 assertTrue (strToDouble(format("12%c", ds), result, ds, ts));
681 assertEqualDelta(12., result, 0.01);
682 assertTrue (strToDouble(format("-12%c", ds), result, ds, ts));
683 assertEqualDelta(-12., result, 0.01);
684 assertTrue (strToDouble("12", result, ds, ts));
685 assertEqualDelta(12, result, 0.01);
686 assertTrue (strToDouble("-12", result, ds, ts));
687 assertEqualDelta(-12, result, 0.01);
688 assertTrue (strToDouble(format("12%c3456789012345678901234567890", ds), result, ds, ts));
689 assertEqualDelta(12.34, result, 0.01);
690
691 assertTrue (strToDouble("1234345", result, ds, ts));
692 assertEqualDelta(1234345, result, 0.00000001);
693 assertTrue (strToDouble(format("1%c234%c345", ts, ts), result, ds, ts));
694 assertEqualDelta(1234345, result, 0.00000001);
695 assertTrue (strToDouble(format("1%c234%c3456789012345678901234567890", ts, ds), result, ds, ts));
696 assertEqualDelta(1234.3456789, result, 0.00000001);
697 assertTrue (strToDouble(format("12%c345%c3456789012345678901234567890", ts, ds), result, ds, ts));
698 assertEqualDelta(12345.3456789, result, 0.00000001);
699 assertTrue (strToDouble(format("123%c456%c3456789012345678901234567890", ts, ds), result, ds, ts));
700 assertEqualDelta(123456.3456789, result, 0.00000001);
701 assertTrue (strToDouble(format("1%c234%c567%c3456789012345678901234567890", ts, ts, ds), result, ds, ts));
702 assertEqualDelta(1234567.3456789, result, 0.00000001);
703 assertTrue (strToDouble(format("12%c345%c678%c3456789012345678901234567890", ts, ts, ds), result, ds, ts));
704 assertEqualDelta(12345678.3456789, result, 0.00000001);
705 assertTrue (strToDouble(format("123%c456%c789%c3456789012345678901234567890", ts, ts, ds), result, ds, ts));
706 assertEqualDelta(123456789.3456789, result, 0.00000001);
707
708 if ((std::numeric_limits<double>::max() / 10) < 1.23456e10)
709 fail ("test value larger than max value for this platform");
710 else
711 {
712 double d = 12e34;
713 assertTrue (strToDouble(format("12e34", ds), result, ds, ts));
714 assertEqualDelta(d, result, 0.01e34);
715
716 d = 1.234e100;
717 assertTrue (strToDouble(format("1%c234e100", ds), result, ds, ts));
718 assertEqualDelta(d, result, 0.01);
719 assertTrue (strToDouble(format("1%c234E+100", ds), result, ds, ts));
720 assertEqualDelta(d, result, 0.01);
721
722 d = 1.234e-100;
723 assertTrue (strToDouble(format("1%c234E-100", ds), result, ds, ts));
724 assertEqualDelta(d, result, 0.01);
725
726 d = -1.234e100;
727 assertTrue (strToDouble(format("-1%c234e+100", ds), result, ds, ts));
728 assertEqualDelta(d, result, 0.01);
729 assertTrue (strToDouble(format("-1%c234E100", ds), result, ds, ts));
730 assertEqualDelta(d, result, 0.01);
731
732 d = 1.234e-100;
733 assertTrue (strToDouble(format(" 1%c234e-100 ", ds), result, ds, ts));
734 assertEqualDelta(d, result, 0.01);
735 assertTrue (strToDouble(format(" 1%c234e-100 ", ds), result, ds, ts));
736 assertEqualDelta(d, result, 0.01);
737 assertTrue (strToDouble(format(" 1%c234e-100 ", ds), result, ds, ts));
738 assertEqualDelta(d, result, 0.01);
739
740 d = 1234.234e-100;
741 assertTrue (strToDouble(format(" 1%c234%c234e-100 ", ts, ds), result, ds, ts));
742 assertEqualDelta(d, result, 0.01);
743 d = 12345.234e-100;
744 assertTrue (strToDouble(format(" 12%c345%c234e-100 ", ts, ds), result, ds, ts));
745 assertEqualDelta(d, result, 0.01);
746 d = 123456.234e-100;
747 assertTrue (strToDouble(format(" 123%c456%c234e-100 ", ts, ds), result, ds, ts));
748 assertEqualDelta(d, result, 0.01);
749
750 d = -1234.234e-100;
751 assertTrue (strToDouble(format(" -1%c234%c234e-100 ", ts, ds), result, ds, ts));
752 assertEqualDelta(d, result, 0.01);
753 d = -12345.234e-100;
754 assertTrue (strToDouble(format(" -12%c345%c234e-100 ", ts, ds), result, ds, ts));
755 assertEqualDelta(d, result, 0.01);
756 d = -123456.234e-100;
757 char ou = 0;
758 assertTrue (strToDouble(format(" -123%c456%c234e-100 ", ts, ds), result, ds, ts));
759 assertEqualDelta(d, result, 0.01);
760 assertTrue (ou == 0);
761 }
762
763 double d = 12.34e-10;
764 assertTrue (strToDouble(format("12%c34e-10", ds), result, ds, ts));
765 assertEqualDelta(d, result, 0.01);
766 assertTrue (strToDouble(format("-12%c34", ds), result, ds, ts));
767 assertEqualDelta(-12.34, result, 0.01);
768
769 assertTrue (strToDouble(format(" 12%c34", ds), result, ds, ts));
770 assertEqualDelta(12.34, result, 0.01);
771 assertTrue (strToDouble(format("12%c34 ", ds), result, ds, ts));
772 assertEqualDelta(12.34, result, 0.01);
773 assertTrue (strToDouble(format(" 12%c34 ", ds), result, ds, ts));
774 assertEqualDelta(12.34, result, 0.01);
775 }
776 }
777
778 assertTrue (std::isnan(strToDouble("nan")));
779 assertTrue (std::isnan(strToDouble("xNaNy")));
780 assertTrue (!std::isnan(strToDouble("inf")));
781 assertTrue (!std::isnan(strToDouble("-inf")));
782 assertTrue (std::isnan(strToDouble("infinity")));
783 assertTrue (!std::isnan(strToDouble("infinity", "infinity")));
784 assertTrue (!std::isnan(strToDouble("-infinity", "infinity")));
785 assertTrue (std::isnan(strToDouble("Inf")));
786 assertTrue (!std::isnan(strToDouble("Inf", "Inf")));
787
788 assertTrue (std::isinf(strToDouble("inf")));
789 assertTrue (std::isinf(strToDouble("-inf")));
790 assertTrue (std::isinf(strToDouble("infinity", "infinity")));
791 assertTrue (std::isinf(strToDouble("-infinity", "infinity")));
792 assertTrue (!std::isinf(strToDouble("Inf")));
793 assertTrue (std::isinf(strToDouble("Inf", "Inf")));
794
795 assertTrue (FPEnvironment::isNaN(strToDouble("nan")));
796 assertTrue (FPEnvironment::isNaN(strToDouble("xNaNy")));
797 assertTrue (!FPEnvironment::isNaN(strToDouble("inf")));
798 assertTrue (!FPEnvironment::isNaN(strToDouble("-inf")));
799 assertTrue (FPEnvironment::isNaN(strToDouble("infinity")));
800 assertTrue (!FPEnvironment::isNaN(strToDouble("infinity", "infinity")));
801 assertTrue (!FPEnvironment::isNaN(strToDouble("-infinity", "infinity")));
802 assertTrue (!FPEnvironment::isNaN(strToDouble("1.23")));
803 assertTrue (FPEnvironment::isNaN(strToDouble("Inf")));
804 assertTrue (!FPEnvironment::isNaN(strToDouble("Inf", "Inf")));
805
806 assertTrue (FPEnvironment::isInfinite(strToDouble("inf")));
807 assertTrue (FPEnvironment::isInfinite(strToDouble("-inf")));
808 assertTrue (FPEnvironment::isInfinite(strToDouble("infinity", "infinity")));
809 assertTrue (FPEnvironment::isInfinite(strToDouble("-infinity", "infinity")));
810 assertTrue (!FPEnvironment::isInfinite(strToDouble("1.23")));
811 assertTrue (!FPEnvironment::isInfinite(strToDouble("abc")));
812 assertTrue (FPEnvironment::isInfinite(strToDouble("Inf", "Inf")));
813}
814
815
816void StringTest::testNumericStringPadding()
817{
818 std::string str;
819 assertTrue (floatToStr(str, 0.999f, 2, 4) == "1.00");
820 assertTrue (floatToStr(str, 0.945f, 2, 4) == "0.95");
821 assertTrue (floatToStr(str, 0.944f, 2, 4) == "0.94");
822 assertTrue (floatToStr(str, 12.45f, 2, 5) == "12.45");
823 assertTrue (floatToStr(str, 12.45f, 1, 4) == "12.5");
824 assertTrue (floatToStr(str, 12.45f, 2, 6) == " 12.45");
825 assertTrue (floatToStr(str, 12.455f, 3, 7) == " 12.455");
826 assertTrue (floatToStr(str, 12.455f, 2, 6) == " 12.46");
827 assertTrue (floatToStr(str, 1.23556E-16f, 2, 6) == "1.24e-16");
828
829 assertTrue (doubleToStr(str, 0.999, 2, 4) == "1.00");
830 assertTrue (doubleToStr(str, 0.945, 2, 4) == "0.95");
831 assertTrue (doubleToStr(str, 0.944, 2, 4) == "0.94");
832 assertTrue (doubleToStr(str, 12.45, 2, 5) == "12.45");
833 assertTrue (doubleToStr(str, 12.45, 1, 4) == "12.5");
834 assertTrue (doubleToStr(str, 12.45, 2, 6) == " 12.45");
835 assertTrue (doubleToStr(str, 12.455, 3, 7) == " 12.455");
836 assertTrue (doubleToStr(str, 12.455, 2, 6) == " 12.46");
837 assertTrue (doubleToStr(str, 1.23556E-16, 2, 6) == "1.24e-16");
838}
839
840void StringTest::testStringToFloatError()
841{
842 char ds = decimalSeparator();
843 if (ds == 0) ds = '.';
844 char ts = thousandSeparator();
845 if (ts == 0) ts = ',';
846 assertTrue (ds != ts);
847
848 double result = 0.0;
849 assertTrue (!strToDouble(format("a12%c3", ds), result));
850 assertTrue (!strToDouble(format("1b2%c3", ds), result));
851 assertTrue (!strToDouble(format("12c%c3", ds), result));
852 assertTrue (!strToDouble(format("12%cx3", ds), result));
853
854 assertTrue (!strToDouble(format("123%c456%c234e1000000", ts, ds), result));
855 assertTrue (!strToDouble(format("123%c456%c234e+1000000", ts, ds), result));
856 //assertTrue (!strToDouble(0, result, ou)); // strToDouble is resilient to null pointers
857 assertTrue (!strToDouble("", result));
858}
859
860
861void StringTest::testNumericLocale()
862{
863#if !defined(POCO_NO_LOCALE) && POCO_OS == POCO_OS_WINDOWS_NT
864 try
865 {
866 char buffer[POCO_MAX_FLT_STRING_LEN];
867
868 char dp = decimalSeparator();
869 char ts = thousandSeparator();
870 std::locale loc;
871 std::cout << "Original locale: '" << loc.name() << '\'' << std::endl;
872 std::cout << "Decimal point: '" << decimalSeparator() << '\'' << std::endl;
873 std::cout << "Thousand separator: '" << ts << '\'' << std::endl;
874 doubleToStr(buffer, POCO_MAX_FLT_STRING_LEN, 1.23);
875 assertTrue (std::strncmp(buffer, "1.23", 4) == 0);
876 std::cout << "1.23 == '" << buffer << '\'' << std::endl;
877
878 std::locale::global(std::locale("German"));
879 std::locale locGerman;
880 assertTrue (',' == decimalSeparator());
881 assertTrue ('.' == thousandSeparator());
882 std::cout << "New locale: '" << locGerman.name() << '\'' << std::endl;
883 std::cout << "Decimal point: '" << decimalSeparator() << '\'' << std::endl;
884 std::cout << "Thousand separator: '" << thousandSeparator() << '\'' << std::endl;
885 doubleToStr(buffer, POCO_MAX_FLT_STRING_LEN, 1.23);
886 assertTrue (std::strncmp(buffer, "1.23", 4) == 0);
887 std::cout << "1.23 == '" << buffer << '\'' << std::endl;
888
889 std::locale::global(std::locale("US"));
890 std::locale locUS;
891 assertTrue ('.' == decimalSeparator());
892 assertTrue (',' == thousandSeparator());
893 std::cout << "New locale: '" << locUS.name() << '\'' << std::endl;
894 std::cout << "Decimal point: '" << decimalSeparator() << '\'' << std::endl;
895 std::cout << "Thousand separator: '" << thousandSeparator() << '\'' << std::endl;
896 doubleToStr(buffer, POCO_MAX_FLT_STRING_LEN, 1.23);
897 assertTrue (std::strncmp(buffer, "1.23", 4) == 0);
898 std::cout << "1.23 == '" << buffer << '\'' << std::endl;
899
900 std::locale::global(loc);
901 dp = decimalSeparator();
902 ts = thousandSeparator();
903 std::cout << "Final locale: '" << loc.name() << '\'' << std::endl;
904 std::cout << "Decimal point: '" << decimalSeparator() << '\'' << std::endl;
905 std::cout << "Thousand separator: '" << thousandSeparator() << '\'' << std::endl;
906 doubleToStr(buffer, POCO_MAX_FLT_STRING_LEN, 1.23);
907 assertTrue (std::strncmp(buffer, "1.23", 4) == 0);
908 std::cout << "1.23 == '" << buffer << '\'' << std::endl;
909
910 assertTrue (dp == decimalSeparator());
911 assertTrue (ts == thousandSeparator());
912 } catch (std::runtime_error& ex)
913 {
914 std::cout << ex.what() << std::endl;
915 warnmsg ("Locale not found, skipping test");
916 }
917#endif
918}
919
920
921void StringTest::benchmarkStrToInt()
922{
923 Poco::Stopwatch sw;
924 std::string num = "123456789";
925 int res;
926 sw.start();
927 for (int i = 0; i < 1000000; ++i) parseStream(num, res);
928 sw.stop();
929 std::cout << "parseStream Number: " << res << std::endl;
930 double timeStream = sw.elapsed() / 1000.0;
931
932 char* pC = 0;
933 sw.restart();
934 for (int i = 0; i < 1000000; ++i) res = std::strtol(num.c_str(), &pC, 10);
935 sw.stop();
936 std::cout << "std::strtol Number: " << res << std::endl;
937 double timeStrtol = sw.elapsed() / 1000.0;
938
939 sw.restart();
940 for (int i = 0; i < 1000000; ++i) strToInt(num.c_str(), res, 10);
941 sw.stop();
942 std::cout << "strToInt Number: " << res << std::endl;
943 double timeStrToInt = sw.elapsed() / 1000.0;
944
945 sw.restart();
946 for (int i = 0; i < 1000000; ++i) std::sscanf(num.c_str(), "%d", &res);
947 sw.stop();
948 std::cout << "sscanf Number: " << res << std::endl;
949 double timeScanf = sw.elapsed() / 1000.0;
950
951 int graph;
952 std::cout << std::endl << "Timing and speedup relative to I/O stream:" << std::endl << std::endl;
953 std::cout << std::setw(14) << "Stream:\t" << std::setw(10) << std::setfill(' ') << timeStream << "[ms]" << std::endl;
954
955 std::cout << std::setw(14) << "std::strtol:\t" << std::setw(10) << std::setfill(' ') << timeStrtol << "[ms]" <<
956 std::setw(10) << std::setfill(' ') << "Speedup: " << (timeStream / timeStrtol) << '\t' ;
957 graph = (int) (timeStream / timeStrtol); for (int i = 0; i < graph; ++i) std::cout << '|';
958
959 std::cout << std::endl << std::setw(14) << "strToInt:\t" << std::setw(10) << std::setfill(' ') << timeStrToInt << "[ms]" <<
960 std::setw(10) << std::setfill(' ') << "Speedup: " << (timeStream / timeStrToInt) << '\t' ;
961 graph = (int) (timeStream / timeStrToInt); for (int i = 0; i < graph; ++i) std::cout << '|';
962
963 std::cout << std::endl << std::setw(14) << "std::sscanf:\t" << std::setw(10) << std::setfill(' ') << timeScanf << "[ms]" <<
964 std::setw(10) << std::setfill(' ') << "Speedup: " << (timeStream / timeScanf) << '\t' ;
965 graph = (int) (timeStream / timeScanf); for (int i = 0; i < graph; ++i) std::cout << '|';
966 std::cout << std::endl;
967}
968
969
970void StringTest::benchmarkStrToFloat()
971{
972 Poco::Stopwatch sw;
973 std::string num = "1.0372157551632929e-112";
974 std::cout << "The Number: " << num << std::endl;
975 double res;
976 sw.start();
977 for (int i = 0; i < 1000000; ++i) parseStream(num, res);
978 sw.stop();
979 std::cout << "parseStream Number: " << std::setprecision(std::numeric_limits<double>::digits10) << res << std::endl;
980 double timeStream = sw.elapsed() / 1000.0;
981
982 // standard strtod
983 char* pC = 0;
984 sw.restart();
985 for (int i = 0; i < 1000000; ++i) res = std::strtod(num.c_str(), &pC);
986 sw.stop();
987 std::cout << "std::strtod Number: " << res << std::endl;
988 double timeStdStrtod = sw.elapsed() / 1000.0;
989
990 // POCO Way
991 sw.restart();
992 char ou = 0;
993 for (int i = 0; i < 1000000; ++i) strToDouble(num, res, ou);
994 sw.stop();
995 std::cout << "strToDouble Number: " << res << std::endl;
996 double timeStrToDouble = sw.elapsed() / 1000.0;
997
998 // standard sscanf
999 sw.restart();
1000 for (int i = 0; i < 1000000; ++i) std::sscanf(num.c_str(), "%lf", &res);
1001 sw.stop();
1002 std::cout << "sscanf Number: " << res << std::endl;
1003 double timeScanf = sw.elapsed() / 1000.0;
1004
1005 // double-conversion Strtod
1006 sw.restart();
1007 for (int i = 0; i < 1000000; ++i) strToDouble(num.c_str());
1008 sw.stop();
1009 std::cout << "Strtod Number: " << res << std::endl;
1010 double timeStrtod = sw.elapsed() / 1000.0;
1011
1012 int graph;
1013 std::cout << std::endl << "Timing and speedup relative to I/O stream:" << std::endl << std::endl;
1014 std::cout << std::setw(14) << "Stream:\t" << std::setw(10) << std::setfill(' ') << std::setprecision(4) << timeStream << "[ms]" << std::endl;
1015
1016 std::cout << std::setw(14) << "std::strtod:\t" << std::setw(10) << std::setfill(' ') << timeStdStrtod << "[ms]" <<
1017 std::setw(10) << std::setfill(' ') << "Speedup: " << (timeStream / timeStdStrtod) << '\t' ;
1018 graph = (int) (timeStream / timeStdStrtod); for (int i = 0; i < graph; ++i) std::cout << '#';
1019
1020 std::cout << std::endl << std::setw(14) << "strToDouble:\t" << std::setw(10) << std::setfill(' ') << timeStrToDouble << "[ms]" <<
1021 std::setw(10) << std::setfill(' ') << "Speedup: " << (timeStream / timeStrToDouble) << '\t' ;
1022 graph = (int) (timeStream / timeStrToDouble); for (int i = 0; i < graph; ++i) std::cout << '#';
1023
1024 std::cout << std::endl << std::setw(14) << "std::sscanf:\t" << std::setw(10) << std::setfill(' ') << timeScanf << "[ms]" <<
1025 std::setw(10) << std::setfill(' ') << "Speedup: " << (timeStream / timeScanf) << '\t' ;
1026 graph = (int) (timeStream / timeScanf); for (int i = 0; i < graph; ++i) std::cout << '#';
1027
1028 std::cout << std::endl << std::setw(14) << "StrtoD:\t" << std::setw(10) << std::setfill(' ') << timeScanf << "[ms]" <<
1029 std::setw(10) << std::setfill(' ') << "Speedup: " << (timeStream / timeStrtod) << '\t' ;
1030 graph = (int) (timeStream / timeStrtod); for (int i = 0; i < graph; ++i) std::cout << '#';
1031
1032 std::cout << std::endl;
1033}
1034
1035
1036void StringTest::testIntToString()
1037{
1038 //intToStr(T number, unsigned short base, std::string& result, bool prefix = false, int width = -1, char fill = ' ', char thSep = 0)
1039
1040 // decimal
1041 std::string result;
1042 result = intToStr(0, 10);
1043 assertTrue (result == "0");
1044 result.clear();
1045 result = intToStr(0, 10, false, 10, '0');
1046 assertTrue (result == "0000000000");
1047 result.clear();
1048 result = intToStr(1234567890, 10);
1049 assertTrue (result == "1234567890");
1050 result.clear();
1051 result = intToStr(-1234567890, 10);
1052 assertTrue (result == "-1234567890");
1053 result.clear();
1054 result = intToStr(-1234567890, 10, false, 15, '0');
1055 assertTrue (result == "-00001234567890");
1056 result.clear();
1057 result = intToStr(-1234567890, 10, false, 15);
1058 assertTrue (result == " -1234567890");
1059 result.clear();
1060 result = intToStr(-1234567890, 10, false, 0, 0, ',');
1061 assertTrue (result == "-1,234,567,890");
1062 result.clear();
1063
1064 // binary
1065 result = intToStr(1234567890, 2);
1066 assertTrue (result == "1001001100101100000001011010010");
1067 result.clear();
1068 result = intToStr(1234567890, 2, true);
1069 assertTrue (result == "1001001100101100000001011010010");
1070 result.clear();
1071 result = intToStr(1234567890, 2, true, 35, '0');
1072 assertTrue (result == "00001001001100101100000001011010010");
1073 result.clear();
1074 result = uIntToStr(0xFF, 2);
1075 assertTrue (result == "11111111");
1076 result.clear();
1077 result = uIntToStr(0x0F, 2, false, 8, '0');
1078 assertTrue (result == "00001111");
1079 result.clear();
1080 result = uIntToStr(0x0F, 2);
1081 assertTrue (result == "1111");
1082 result.clear();
1083 result = uIntToStr(0xF0, 2);
1084 assertTrue (result == "11110000");
1085 result.clear();
1086 result = uIntToStr(0xFFFF, 2);
1087 assertTrue (result == "1111111111111111");
1088 result.clear();
1089 result = uIntToStr(0xFF00, 2);
1090 assertTrue (result == "1111111100000000");
1091 result.clear();
1092 result = uIntToStr(0xFFFFFFFF, 2);
1093 assertTrue (result == "11111111111111111111111111111111");
1094 result.clear();
1095 result = uIntToStr(0xFF00FF00, 2);
1096 assertTrue (result == "11111111000000001111111100000000");
1097 result.clear();
1098 result = uIntToStr(0xF0F0F0F0, 2);
1099 assertTrue (result == "11110000111100001111000011110000");
1100 result.clear();
1101#if defined(POCO_HAVE_INT64)
1102 result = uIntToStr(0xFFFFFFFFFFFFFFFF, 2);
1103 assertTrue (result == "1111111111111111111111111111111111111111111111111111111111111111");
1104 result.clear();
1105 result = uIntToStr(0xFF00000FF00000FF, 2);
1106 assertTrue (result == "1111111100000000000000000000111111110000000000000000000011111111");
1107 result.clear();
1108#endif
1109
1110 // octal
1111 result = uIntToStr(1234567890, 010);
1112 assertTrue (result == "11145401322");
1113 result.clear();
1114 result = uIntToStr(1234567890, 010, true);
1115 assertTrue (result == "011145401322");
1116 result.clear();
1117 result = uIntToStr(1234567890, 010, true, 15, '0');
1118 assertTrue (result == "000011145401322");
1119 result.clear();
1120 result = uIntToStr(012345670, 010, true);
1121 assertTrue (result == "012345670");
1122 result.clear();
1123 result = uIntToStr(012345670, 010);
1124 assertTrue (result == "12345670");
1125 result.clear();
1126
1127 // hexadecimal
1128 result = uIntToStr(0, 0x10, true);
1129 assertTrue (result == "0x0");
1130 result.clear();
1131 result = uIntToStr(0, 0x10, true, 4, '0');
1132 assertTrue (result == "0x00");
1133 result.clear();
1134 result = uIntToStr(0, 0x10, false, 4, '0');
1135 assertTrue (result == "0000");
1136 result.clear();
1137 result = uIntToStr(1234567890, 0x10);
1138 assertTrue (result == "499602D2");
1139 result.clear();
1140 result = uIntToStr(1234567890, 0x10, true);
1141 assertTrue (result == "0x499602D2");
1142 result.clear();
1143 result = uIntToStr(1234567890, 0x10, true, 15, '0');
1144 assertTrue (result == "0x00000499602D2");
1145 result.clear();
1146 result = uIntToStr(0x1234567890ABCDEF, 0x10, true);
1147 assertTrue (result == "0x1234567890ABCDEF");
1148 result.clear();
1149 result = uIntToStr(0xDEADBEEF, 0x10);
1150 assertTrue (result == "DEADBEEF");
1151 result.clear();
1152#if defined(POCO_HAVE_INT64)
1153 result = uIntToStr(0xFFFFFFFFFFFFFFFF, 0x10);
1154 assertTrue (result == "FFFFFFFFFFFFFFFF");
1155 result.clear();
1156 result = uIntToStr(0xFFFFFFFFFFFFFFFF, 0x10, true);
1157 assertTrue (result == "0xFFFFFFFFFFFFFFFF");
1158 result.clear();
1159#endif
1160
1161 try
1162 {
1163 char pResult[POCO_MAX_INT_STRING_LEN];
1164 std::size_t sz = POCO_MAX_INT_STRING_LEN;
1165 intToStr(0, 10, pResult, sz, false, (int) sz + 1, ' ');
1166 fail ("must throw RangeException");
1167 } catch (RangeException&) { }
1168}
1169
1170
1171void StringTest::testFloatToString()
1172{
1173 double val = 1.03721575516329e-112;
1174 std::string str;
1175
1176 assertTrue (doubleToStr(str, val, 14, 21) == "1.03721575516329e-112");
1177 assertTrue (doubleToStr(str, val, 14, 22) == " 1.03721575516329e-112");
1178 val = -val;
1179 assertTrue (doubleToStr(str, val, 14, 22) == "-1.03721575516329e-112");
1180 assertTrue (doubleToStr(str, val, 14, 23) == " -1.03721575516329e-112");
1181
1182 val = -10372157551632.9;
1183 assertTrue (doubleToStr(str, val, 1, 21, ',') == "-10,372,157,551,632.9");
1184 assertTrue (doubleToStr(str, val, 1, 22, ',') == " -10,372,157,551,632.9");
1185 assertTrue (doubleToStr(str, val, 2, 22, ',') == "-10,372,157,551,632.90");
1186 assertTrue (doubleToStr(str, val, 2, 22, '.', ',') == "-10.372.157.551.632,90");
1187 assertTrue (doubleToStr(str, val, 2, 22, ' ', ',') == "-10 372 157 551 632,90");
1188
1189 int ival = 1234567890;
1190 assertTrue (doubleToStr(str, ival, 1, 15, ',') == "1,234,567,890.0");
1191 ival = -123456789;
1192 assertTrue (doubleToStr(str, ival, 1, 14, ',') == "-123,456,789.0");
1193}
1194
1195
1196void StringTest::testNumericStringLimit()
1197{
1198 char c = 0, t = -1;
1199 assertTrue(!isIntOverflow<char>(c));
1200 assertTrue(safeIntCast<char>(c, t) == c);
1201 assertTrue(t == c);
1202
1203 short s = SHRT_MAX;
1204 assertTrue(isIntOverflow<char>(s));
1205 try
1206 {
1207 safeIntCast(s, t);
1208 fail("cast must fail");
1209 }
1210 catch(Poco::BadCastException&){}
1211
1212 s = SHRT_MIN;
1213 assertTrue(isIntOverflow<char>(s));
1214 try
1215 {
1216 safeIntCast(s, t);
1217 fail("short => char cast must fail");
1218 }
1219 catch(Poco::BadCastException&){}
1220
1221 signed char sc = 0, st = -1;
1222 assertTrue(!isIntOverflow<signed char>(sc));
1223 assertTrue(safeIntCast<char>(sc, st) == sc);
1224 assertTrue(st == sc);
1225
1226 short ss = SHRT_MAX;
1227 assertTrue(isIntOverflow<signed char>(ss));
1228 assertTrue(isIntOverflow<char>(ss));
1229 try
1230 {
1231 safeIntCast(ss, st);
1232 fail("short => signed char cast must fail");
1233 }
1234 catch(Poco::BadCastException&){}
1235
1236 ss = SHRT_MIN;
1237 assertTrue(isIntOverflow<signed char>(ss));
1238 assertTrue(isIntOverflow<char>(ss));
1239 try
1240 {
1241 safeIntCast(ss, st);
1242 fail("short => signed char cast must fail");
1243 }
1244 catch(Poco::BadCastException&){}
1245
1246 assertTrue(safeIntCast<signed char>(sc, st) == c);
1247 assertTrue(st == sc);
1248
1249 unsigned char uc = 0, ut = -1;
1250 assertTrue(!isIntOverflow<unsigned char>(uc));
1251 assertTrue(safeIntCast<char>(uc, ut) == uc);
1252 assertTrue(ut == uc);
1253
1254 ss = SHRT_MAX;
1255 assertTrue(isIntOverflow<unsigned char>(ss));
1256 try
1257 {
1258 safeIntCast(ss, st);
1259 fail("cast must fail");
1260 }
1261 catch(Poco::BadCastException&){}
1262
1263 ss = -1;
1264 assertTrue(isIntOverflow<unsigned char>(ss));
1265 try
1266 {
1267 safeIntCast(ss, uc);
1268 fail("unsigned short => unsigned char cast must fail");
1269 }
1270 catch(Poco::BadCastException&){}
1271
1272 int i = 0;
1273 assertTrue(!isIntOverflow<int>(i));
1274 assertTrue(!isIntOverflow<unsigned>(i));
1275 i = -1;
1276 unsigned int ti = -1;
1277 assertTrue(isIntOverflow<unsigned>(i));
1278 try
1279 {
1280 safeIntCast(i, ti);
1281 fail("unsigned int => int cast must fail");
1282 }
1283 catch(Poco::BadCastException&){}
1284
1285 if (sizeof(long) > sizeof(int))
1286 {
1287 long l = LONG_MAX;
1288 assertTrue(isIntOverflow<int>(l));
1289 l = -1L;
1290 assertTrue(isIntOverflow<unsigned>(l));
1291 i = -1;
1292 assertTrue(!isIntOverflow<long>(i));
1293 long tl = 0;
1294 assertTrue(safeIntCast(i, tl) == i);
1295 unsigned long ul = ULONG_MAX, tul = 0;
1296 assertTrue(isIntOverflow<long>(ul));
1297 try
1298 {
1299 safeIntCast(ul, tl);
1300 fail("unsigned long => long cast must fail");
1301 }
1302 catch(Poco::BadCastException&){}
1303 assertTrue(!isIntOverflow<unsigned long>(ul));
1304 tl = 0;
1305 assertTrue(safeIntCast(ul, tul) == ul);
1306 l = LONG_MIN;
1307 assertTrue(isIntOverflow<unsigned long>(l));
1308 try
1309 {
1310 safeIntCast(l, ul);
1311 fail("unsigned long => long cast must fail");
1312 }
1313 catch(Poco::BadCastException&){}
1314 ul = LONG_MAX;
1315 assertTrue(!isIntOverflow<long>(ul));
1316 assertTrue(safeIntCast(ul, l) == ul);
1317 }
1318
1319 numericStringLimitSameSign<unsigned short, unsigned char>();
1320 numericStringLimitSameSign<short, char>();
1321 numericStringLimitSameSign<unsigned int, unsigned short>();
1322 numericStringLimitSameSign<int, short>();
1323
1324 if (sizeof(long) > sizeof(int))
1325 {
1326 numericStringLimitSameSign<unsigned long, unsigned int>();
1327 numericStringLimitSameSign<long, int>();
1328 }
1329
1330 numericStringLowerLimit<short, char>();
1331 numericStringLowerLimit<int, short>();
1332
1333 if (sizeof(long) > sizeof(int))
1334 {
1335 numericStringLowerLimit<int64_t, int32_t>();
1336 }
1337
1338#ifdef POCO_ENABLE_CPP11
1339 assertTrue(!isIntOverflow<int8_t>(0));
1340 assertTrue(isIntOverflow<int8_t>(std::numeric_limits<int16_t>::max()));
1341 assertTrue(isIntOverflow<int8_t>(std::numeric_limits<int16_t>::min()));
1342 assertTrue(!isIntOverflow<uint8_t>(0));
1343 assertTrue(isIntOverflow<uint8_t>(std::numeric_limits<int16_t>::max()));
1344 assertTrue(isIntOverflow<uint8_t>(-1));
1345 assertTrue(!isIntOverflow<int32_t>(0));
1346 assertTrue(isIntOverflow<int32_t>(std::numeric_limits<int64_t>::max()));
1347 assertTrue(!isIntOverflow<uint32_t>(0));
1348 assertTrue(isIntOverflow<uint32_t>(-1));
1349 assertTrue(isIntOverflow<uint32_t>(-1L));
1350 assertTrue(isIntOverflow<uint32_t>(-1LL));
1351 assertTrue(!isIntOverflow<int64_t>(-1));
1352 assertTrue(isIntOverflow<int64_t>(std::numeric_limits<uint64_t>::max()));
1353 assertTrue(!isIntOverflow<uint64_t>(std::numeric_limits<uint64_t>::max()));
1354 assertTrue(isIntOverflow<uint64_t>(std::numeric_limits<int64_t>::min()));
1355 assertTrue(!isIntOverflow<uint64_t>(std::numeric_limits<uint64_t>::min()));
1356 assertTrue(!isIntOverflow<int64_t>(std::numeric_limits<int64_t>::max()));
1357
1358 numericStringLimitSameSign<uint16_t, uint8_t>();
1359 numericStringLimitSameSign<int16_t, int8_t>();
1360 numericStringLimitSameSign<uint32_t, uint16_t>();
1361 numericStringLimitSameSign<int32_t, int16_t>();
1362 numericStringLimitSameSign<uint64_t, uint32_t>();
1363 numericStringLimitSameSign<int64_t, int32_t>();
1364
1365 numericStringLowerLimit<int16_t, int8_t>();
1366 numericStringLowerLimit<int32_t, int16_t>();
1367 numericStringLowerLimit<int64_t, int32_t>();
1368#endif
1369}
1370
1371
1372void formatStream(double value, std::string& str)
1373{
1374 char buffer[128];
1375 Poco::MemoryOutputStream ostr(buffer, sizeof(buffer));
1376#if !defined(POCO_NO_LOCALE)
1377 ostr.imbue(std::locale::classic());
1378#endif
1379 ostr << std::setprecision(16) << value;
1380 str.assign(buffer, static_cast<std::string::size_type>(ostr.charsWritten()));
1381}
1382
1383
1384void formatSprintf(double value, std::string& str)
1385{
1386 char buffer[128];
1387 std::sprintf(buffer, "%.*g", 16, value);
1388 str = buffer;
1389}
1390
1391
1392void StringTest::benchmarkFloatToStr()
1393{
1394 Poco::Stopwatch sw;
1395 double val = 1.0372157551632929e-112;
1396 std::cout << "The Number: " << std::setprecision(std::numeric_limits<double>::digits10) << val << std::endl;
1397 std::string str;
1398 sw.start();
1399 for (int i = 0; i < 1000000; ++i) formatStream(val, str);
1400 sw.stop();
1401 std::cout << "formatStream Number: " << str << std::endl;
1402 double timeStream = sw.elapsed() / 1000.0;
1403
1404 // standard sprintf
1405 str = "";
1406 sw.restart();
1407 for (int i = 0; i < 1000000; ++i) formatSprintf(val, str);
1408 sw.stop();
1409 std::cout << "std::sprintf Number: " << str << std::endl;
1410 double timeSprintf = sw.elapsed() / 1000.0;
1411
1412 // POCO Way (via double-conversion)
1413 // no padding
1414 sw.restart();
1415 char buffer[POCO_MAX_FLT_STRING_LEN];
1416 for (int i = 0; i < 1000000; ++i) doubleToStr(buffer, POCO_MAX_FLT_STRING_LEN, val);
1417 sw.stop();
1418 std::cout << "doubleToStr(char) Number: " << buffer << std::endl;
1419 double timeDoubleToStrChar = sw.elapsed() / 1000.0;
1420
1421 // with padding
1422 str = "";
1423 sw.restart();
1424 for (int i = 0; i < 1000000; ++i) doubleToStr(str, val);
1425 sw.stop();
1426 std::cout << "doubleToStr(std::string) Number: " << str << std::endl;
1427 double timeDoubleToStrString = sw.elapsed() / 1000.0;
1428
1429 int graph;
1430 std::cout << std::endl << "Timing and speedup relative to I/O stream:" << std::endl << std::endl;
1431 std::cout << std::setw(14) << "Stream:\t" << std::setw(10) << std::setfill(' ') << std::setprecision(4) << timeStream << "[ms]" << std::endl;
1432
1433 std::cout << std::setw(14) << "sprintf:\t" << std::setw(10) << std::setfill(' ') << timeSprintf << "[ms]" <<
1434 std::setw(10) << std::setfill(' ') << "Speedup: " << (timeStream / timeSprintf) << '\t' ;
1435 graph = (int) (timeStream / timeSprintf); for (int i = 0; i < graph; ++i) std::cout << '#';
1436
1437 std::cout << std::endl << std::setw(14) << "doubleToChar:\t" << std::setw(10) << std::setfill(' ') << timeDoubleToStrChar << "[ms]" <<
1438 std::setw(10) << std::setfill(' ') << "Speedup: " << (timeStream / timeDoubleToStrChar) << '\t' ;
1439 graph = (int) (timeStream / timeDoubleToStrChar); for (int i = 0; i < graph; ++i) std::cout << '#';
1440
1441 std::cout << std::endl << std::setw(14) << "doubleToString:\t" << std::setw(10) << std::setfill(' ') << timeDoubleToStrString << "[ms]" <<
1442 std::setw(10) << std::setfill(' ') << "Speedup: " << (timeStream / timeDoubleToStrString) << '\t' ;
1443 graph = (int) (timeStream / timeDoubleToStrString); for (int i = 0; i < graph; ++i) std::cout << '#';
1444
1445 std::cout << std::endl;
1446}
1447
1448
1449void StringTest::testJSONString()
1450{
1451 assertTrue (toJSON("\\", false) == "\\\\");
1452 assertTrue (toJSON("\"", false) == "\\\"");
1453 assertTrue (toJSON("/", false) == "\\/");
1454 assertTrue (toJSON("\a", false) == "\\u0007");
1455 assertTrue (toJSON("\b", false) == "\\b");
1456 assertTrue (toJSON("\f", false) == "\\f");
1457 assertTrue (toJSON("\n", false) == "\\n");
1458 assertTrue (toJSON("\r", false) == "\\r");
1459 assertTrue (toJSON("\t", false) == "\\t");
1460 assertTrue (toJSON("\v", false) == "\\u000B");
1461 assertTrue (toJSON("a", false) == "a");
1462 assertTrue (toJSON("\xD0\x82", 0) == "\xD0\x82");
1463 assertTrue (toJSON("\xD0\x82", Poco::JSON_ESCAPE_UNICODE) == "\\u0402");
1464
1465 // ??? on MSVC, the assert macro expansion
1466 // fails to compile when this string is inline ???
1467 std::string str = "\"foo\\\\\"";
1468 assertTrue (toJSON("foo\\") == str);
1469
1470 assertTrue (toJSON("bar/") == "\"bar\\/\"");
1471 assertTrue (toJSON("baz") == "\"baz\"");
1472 assertTrue (toJSON("q\"uote\"d") == "\"q\\\"uote\\\"d\"");
1473 assertTrue (toJSON("bs\b") == "\"bs\\b\"");
1474 assertTrue (toJSON("nl\n") == "\"nl\\n\"");
1475 assertTrue (toJSON("tb\t") == "\"tb\\t\"");
1476 assertTrue (toJSON("\xD0\x82") == "\"\xD0\x82\"");
1477 assertTrue (toJSON("\xD0\x82", Poco::JSON_WRAP_STRINGS) == "\"\xD0\x82\"");
1478 assertTrue (toJSON("\xD0\x82",
1479 Poco::JSON_WRAP_STRINGS | Poco::JSON_ESCAPE_UNICODE) == "\"\\u0402\"");
1480
1481 std::ostringstream ostr;
1482 toJSON("foo\\", ostr);
1483 assertTrue (ostr.str() == str);
1484 ostr.str("");
1485
1486 toJSON("foo\\", ostr);
1487 assertTrue (toJSON("bar/") == "\"bar\\/\"");
1488 ostr.str("");
1489 toJSON("baz", ostr);
1490 assertTrue (ostr.str() == "\"baz\"");
1491 ostr.str("");
1492 toJSON("q\"uote\"d", ostr);
1493 assertTrue (ostr.str() == "\"q\\\"uote\\\"d\"");
1494 ostr.str("");
1495 toJSON("bs\b", ostr);
1496 assertTrue (ostr.str() == "\"bs\\b\"");
1497 ostr.str("");
1498 toJSON("nl\n", ostr);
1499 assertTrue (ostr.str() == "\"nl\\n\"");
1500 ostr.str("");
1501 toJSON("tb\t", ostr);
1502 assertTrue (ostr.str() == "\"tb\\t\"");
1503 ostr.str("");
1504 toJSON("\xD0\x82", ostr);
1505 assertTrue (ostr.str() == "\"\xD0\x82\"");
1506 ostr.str("");
1507 toJSON("\xD0\x82", ostr, Poco::JSON_WRAP_STRINGS);
1508 assertTrue (ostr.str() == "\"\xD0\x82\"");
1509 ostr.str("");
1510 toJSON("\xD0\x82", ostr, Poco::JSON_WRAP_STRINGS | Poco::JSON_ESCAPE_UNICODE);
1511 assertTrue (ostr.str() == "\"\\u0402\"");
1512 ostr.str("");
1513}
1514
1515
1516void StringTest::setUp()
1517{
1518}
1519
1520
1521void StringTest::tearDown()
1522{
1523}
1524
1525
1526CppUnit::Test* StringTest::suite()
1527{
1528 CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("StringTest");
1529
1530 CppUnit_addTest(pSuite, StringTest, testTrimLeft);
1531 CppUnit_addTest(pSuite, StringTest, testTrimLeftInPlace);
1532 CppUnit_addTest(pSuite, StringTest, testTrimRight);
1533 CppUnit_addTest(pSuite, StringTest, testTrimInPlace);
1534 CppUnit_addTest(pSuite, StringTest, testTrim);
1535 CppUnit_addTest(pSuite, StringTest, testTrimRightInPlace);
1536 CppUnit_addTest(pSuite, StringTest, testToUpper);
1537 CppUnit_addTest(pSuite, StringTest, testToLower);
1538 CppUnit_addTest(pSuite, StringTest, testIstring);
1539 CppUnit_addTest(pSuite, StringTest, testIcompare);
1540 CppUnit_addTest(pSuite, StringTest, testCILessThan);
1541 CppUnit_addTest(pSuite, StringTest, testTranslate);
1542 CppUnit_addTest(pSuite, StringTest, testTranslateInPlace);
1543 CppUnit_addTest(pSuite, StringTest, testReplace);
1544 CppUnit_addTest(pSuite, StringTest, testReplaceInPlace);
1545 CppUnit_addTest(pSuite, StringTest, testCat);
1546 CppUnit_addTest(pSuite, StringTest, testStartsWith);
1547 CppUnit_addTest(pSuite, StringTest, testEndsWith);
1548 CppUnit_addTest(pSuite, StringTest, testStringToInt);
1549 CppUnit_addTest(pSuite, StringTest, testStringToFloat);
1550 CppUnit_addTest(pSuite, StringTest, testStringToDouble);
1551 CppUnit_addTest(pSuite, StringTest, testNumericStringPadding);
1552 CppUnit_addTest(pSuite, StringTest, testNumericStringLimit);
1553 CppUnit_addTest(pSuite, StringTest, testStringToFloatError);
1554 CppUnit_addTest(pSuite, StringTest, testNumericLocale);
1555 //CppUnit_addTest(pSuite, StringTest, benchmarkStrToFloat);
1556 //CppUnit_addTest(pSuite, StringTest, benchmarkStrToInt);
1557 CppUnit_addTest(pSuite, StringTest, testIntToString);
1558 CppUnit_addTest(pSuite, StringTest, testFloatToString);
1559 //CppUnit_addTest(pSuite, StringTest, benchmarkFloatToStr);
1560 CppUnit_addTest(pSuite, StringTest, testJSONString);
1561
1562 return pSuite;
1563}
1564