comment_strip-ruby 0.0.13

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3711 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), '../..', 'lib')
4
+
5
+
6
+ require 'comment_strip'
7
+
8
+ require 'xqsr3/extensions/test/unit'
9
+
10
+ require 'test/unit'
11
+
12
+ class Test_strip_1 < Test::Unit::TestCase
13
+
14
+ include ::CommentStrip
15
+
16
+ def test_nil
17
+
18
+ assert_nil strip(nil, 'C')
19
+ end
20
+
21
+ def test_unrecognised_families
22
+
23
+ unrecognised_families = %w{
24
+
25
+ Python
26
+ Perl
27
+ Ruby
28
+
29
+ Java
30
+ Kotlin
31
+ Scala
32
+
33
+ Rust
34
+ }
35
+
36
+ unrecognised_families.each do |family|
37
+
38
+ assert_raise_with_message(::RuntimeError, /family.*unrecognised/) { strip('', family) }
39
+ end
40
+ end
41
+
42
+ def test_empty
43
+
44
+ assert_equal "", strip('', 'C')
45
+ end
46
+
47
+ def test_simple_main
48
+
49
+ input = <<-EOF_main
50
+ #include <stdio.h>
51
+ int main(int argc, char* argv[])
52
+ {
53
+ return 0;
54
+ }
55
+ EOF_main
56
+ expected = input
57
+
58
+ assert_equal expected, strip(input, 'C')
59
+ end
60
+
61
+ def test_x_1
62
+
63
+ input = <<-EOF_main
64
+ #ifdef CLARA_PLATFORM_WINDOWS
65
+ case '/': from = i+1; return SlashOpt;
66
+ #endif
67
+
68
+ std::string description;
69
+ std::string detail;
70
+ std::string placeholder; // Only value if boundField takes an arg
71
+
72
+ bool takesArg() const {
73
+ return !placeholder.empty();
74
+ }
75
+ EOF_main
76
+ expected = <<-EOF_main
77
+ #ifdef CLARA_PLATFORM_WINDOWS
78
+ case '/': from = i+1; return SlashOpt;
79
+ #endif
80
+
81
+ std::string description;
82
+ std::string detail;
83
+ std::string placeholder;
84
+
85
+ bool takesArg() const {
86
+ return !placeholder.empty();
87
+ }
88
+ EOF_main
89
+
90
+ actual = strip(input, 'C')
91
+
92
+ assert_equal expected, actual
93
+ end
94
+
95
+ def test_x_2
96
+
97
+ input = <<-EOF_main
98
+
99
+ } // namespace something
100
+ EOF_main
101
+ expected = <<-EOF_main
102
+
103
+ }
104
+ EOF_main
105
+
106
+ actual = strip(input, 'C')
107
+
108
+ assert_equal expected, actual
109
+ end
110
+
111
+ def test_x_3
112
+
113
+ input = <<-EOF_main
114
+
115
+ #endif /* !LOG_PERROR */
116
+ EOF_main
117
+ expected = <<-EOF_main
118
+
119
+ #endif
120
+ EOF_main
121
+
122
+ actual = strip(input, 'C')
123
+
124
+ assert_equal expected, actual
125
+ end
126
+
127
+ def test_code_with_single_quoted_characters_1
128
+
129
+ input = <<-EOF_main
130
+
131
+ case '"': // " this is the comment "
132
+ EOF_main
133
+ expected = <<-EOF_main
134
+
135
+ case '"':
136
+ EOF_main
137
+
138
+ actual = strip(input, 'C')
139
+
140
+ assert_equal expected, actual
141
+ end
142
+
143
+ def test_code_with_single_quoted_characters_2
144
+
145
+ input = <<-EOF_main
146
+
147
+ case '\\"': // " this is the comment "
148
+ EOF_main
149
+ expected = <<-EOF_main
150
+
151
+ case '\\"':
152
+ EOF_main
153
+
154
+ actual = strip(input, 'C')
155
+
156
+ assert_equal expected, actual
157
+ end
158
+
159
+ def test_code_with_single_quoted_characters_3
160
+
161
+ input = <<-EOF_main
162
+
163
+ case '\\'': // " this is the comment "
164
+ EOF_main
165
+ expected = <<-EOF_main
166
+
167
+ case '\\'':
168
+ EOF_main
169
+
170
+ actual = strip(input, 'C')
171
+
172
+ assert_equal expected, actual
173
+ end
174
+
175
+ def test_code_with_single_quoted_characters_4
176
+
177
+ input = <<-EOF_main
178
+
179
+ case '\\\\': // " this is the comment "
180
+ EOF_main
181
+ expected = <<-EOF_main
182
+
183
+ case '\\\\':
184
+ EOF_main
185
+
186
+ actual = strip(input, 'C')
187
+
188
+ assert_equal expected, actual
189
+ end
190
+
191
+ def test_code_with_single_quoted_characters_5
192
+
193
+ input = <<-EOF_main
194
+
195
+ case '\\\\': // " this is the comment "
196
+ EOF_main
197
+ expected = <<-EOF_main
198
+
199
+ case '\\\\':
200
+ EOF_main
201
+
202
+ actual = strip(input, 'C')
203
+
204
+ assert_equal expected, actual
205
+ end
206
+
207
+ def test_code_with_single_quoted_characters_6
208
+
209
+ input = <<-EOF_main
210
+
211
+ #define SOME_CHAR '\\x80' /* some char */
212
+ EOF_main
213
+ expected = <<-EOF_main
214
+
215
+ #define SOME_CHAR '\\x80'
216
+ EOF_main
217
+
218
+ actual = strip(input, 'C')
219
+
220
+ assert_equal expected, actual
221
+ end
222
+
223
+ def test_code_with_double_quoted_characters_1
224
+
225
+ input = <<-EOF_main
226
+
227
+ case "'": // " this is the comment "
228
+ EOF_main
229
+ expected = <<-EOF_main
230
+
231
+ case "'":
232
+ EOF_main
233
+
234
+ actual = strip(input, 'C')
235
+
236
+ assert_equal expected, actual
237
+ end
238
+
239
+ def test_code_with_double_quoted_characters_2
240
+
241
+ input = <<-EOF_main
242
+
243
+ case "\\"": // " this is the comment "
244
+ EOF_main
245
+ expected = <<-EOF_main
246
+
247
+ case "\\"":
248
+ EOF_main
249
+
250
+ actual = strip(input, 'C')
251
+
252
+ assert_equal expected, actual
253
+ end
254
+
255
+ def test_code_with_double_quoted_characters_3
256
+
257
+ input = <<-EOF_main
258
+
259
+ case "\\'": // " this is the comment "
260
+ EOF_main
261
+ expected = <<-EOF_main
262
+
263
+ case "\\'":
264
+ EOF_main
265
+
266
+ actual = strip(input, 'C')
267
+
268
+ assert_equal expected, actual
269
+ end
270
+
271
+ def test_code_with_double_quoted_characters_4
272
+
273
+ input = <<-EOF_main
274
+
275
+ case "\\\\": // " this is the comment "
276
+ EOF_main
277
+ expected = <<-EOF_main
278
+
279
+ case "\\\\":
280
+ EOF_main
281
+
282
+ actual = strip(input, 'C')
283
+
284
+ assert_equal expected, actual
285
+ end
286
+
287
+ def test_code_with_double_quoted_characters_5
288
+
289
+ input = <<-EOF_main
290
+
291
+ case "\\\\": // " this is the comment "
292
+ EOF_main
293
+ expected = <<-EOF_main
294
+
295
+ case "\\\\":
296
+ EOF_main
297
+
298
+ actual = strip(input, 'C')
299
+
300
+ assert_equal expected, actual
301
+ end
302
+
303
+ def test_simple_main_with_trailing_cppcomment
304
+
305
+ input = <<-EOF_main
306
+ #include <stdio.h>
307
+ int main(int argc, char* argv[])
308
+ {
309
+ return 0; // same as EXIT_SUCCESS
310
+ }
311
+ EOF_main
312
+ expected = <<-EOF_main
313
+ #include <stdio.h>
314
+ int main(int argc, char* argv[])
315
+ {
316
+ return 0;
317
+ }
318
+ EOF_main
319
+
320
+ assert_equal expected, strip(input, 'C')
321
+ end
322
+
323
+ def test_simple_main_with_trailing_cppcomment_and_divide_maths
324
+
325
+ input = <<-EOF_main
326
+ #include <stdio.h>
327
+ int main(int argc, char* argv[])
328
+ {
329
+ return 0 / 1; // same as EXIT_SUCCESS
330
+ }
331
+ EOF_main
332
+ expected = <<-EOF_main
333
+ #include <stdio.h>
334
+ int main(int argc, char* argv[])
335
+ {
336
+ return 0 / 1;
337
+ }
338
+ EOF_main
339
+
340
+ assert_equal expected, strip(input, 'C')
341
+ end
342
+
343
+ def test_simple_main_with_ccomment
344
+
345
+ input = <<-EOF_main
346
+ #include <stdio.h>
347
+ int main(int argc, char* argv[])
348
+ {
349
+ return 2; /* same as EXIT_SUCCESS */
350
+ }
351
+ EOF_main
352
+ expected = <<-EOF_main
353
+ #include <stdio.h>
354
+ int main(int argc, char* argv[])
355
+ {
356
+ return 2;
357
+ }
358
+ EOF_main
359
+
360
+ assert_equal expected, strip(input, 'C')
361
+ end
362
+
363
+ def test_ccomment_inline
364
+
365
+ input = 'int i = func(/*x=*/x, /*y=*/y);'
366
+ expected = 'int i = func(x, y);'
367
+
368
+ assert_equal expected, strip(input, 'C')
369
+ end
370
+
371
+ def test_multiline_1
372
+
373
+ input = <<-EOF_main
374
+
375
+ /** Some function description
376
+ */
377
+ int func();
378
+ EOF_main
379
+ expected = <<-EOF_main
380
+
381
+
382
+
383
+ int func();
384
+ EOF_main
385
+
386
+ assert_equal expected, strip(input, 'C')
387
+ end
388
+
389
+ def test_multiline_2
390
+
391
+ input = <<-EOF_main
392
+
393
+ /** Some function description
394
+ */
395
+ int func();
396
+
397
+ /** Some other function description
398
+ *
399
+ */
400
+
401
+ int fn();
402
+ EOF_main
403
+ expected = <<-EOF_main
404
+
405
+
406
+
407
+ int func();
408
+
409
+
410
+
411
+
412
+
413
+ int fn();
414
+ EOF_main
415
+
416
+ assert_equal expected, strip(input, 'C')
417
+ end
418
+
419
+ def test_multiline_3
420
+
421
+ input = <<-EOF_main
422
+
423
+ /** Some function description
424
+ *
425
+ * ABC
426
+ */
427
+ int func();
428
+ EOF_main
429
+ expected = <<-EOF_main
430
+
431
+
432
+
433
+
434
+
435
+ int func();
436
+ EOF_main
437
+
438
+ assert_equal expected, strip(input, 'C')
439
+ end
440
+
441
+ def test_multiline_4
442
+
443
+ input = <<-EOF_main
444
+
445
+ /** //////////////////////////////////
446
+ *
447
+ * ABC
448
+ */
449
+ int func();
450
+ EOF_main
451
+ expected = <<-EOF_main
452
+
453
+
454
+
455
+
456
+
457
+ int func();
458
+ EOF_main
459
+
460
+ assert_equal expected, strip(input, 'C')
461
+ end
462
+
463
+ def test_comments_in_strings_1
464
+
465
+ input = <<-EOF_main
466
+
467
+ string s("//"); // THIS is the comment
468
+ EOF_main
469
+ expected = <<-EOF_main
470
+
471
+ string s("//");
472
+ EOF_main
473
+ actual = strip(input, 'C')
474
+
475
+ assert_equal expected, actual
476
+ end
477
+
478
+ def test_comments_in_strings_2
479
+
480
+ input = <<-EOF_main
481
+
482
+ string s("/*"); // THIS is the comment
483
+ EOF_main
484
+ expected = <<-EOF_main
485
+
486
+ string s("/*");
487
+ EOF_main
488
+ actual = strip(input, 'C')
489
+
490
+ assert_equal expected, actual
491
+ end
492
+
493
+ def test_real_sample_1
494
+
495
+ input = <<-EOF_main
496
+ /* /////////////////////////////////////////////////////////////////////////
497
+ * includes
498
+ *
499
+ * some thing or other
500
+ */
501
+
502
+ #include "ximpl_core.hpp"
503
+ #ifndef UNIXSTL_NO_ATOMIC_INTEGER_OPERATIONS_ON_WINDOWS
504
+ # define UNIXSTL_NO_ATOMIC_INTEGER_OPERATIONS_ON_WINDOWS
505
+ #endif
506
+ #include <fastformat/quality/cover.h>
507
+
508
+ #ifdef FASTFORMAT_MT
509
+ # include <platformstl/synch/thread_mutex.hpp>
510
+ #else /* ? FASTFORMAT_MT */
511
+ # include <stlsoft/synch/null_mutex.hpp>
512
+ #endif /* FASTFORMAT_MT */
513
+
514
+ #include <stlsoft/memory/auto_buffer.hpp>
515
+ #include <stlsoft/synch/lock_scope.hpp>
516
+
517
+ #if defined(_DEBUG) && \
518
+ defined(PLATFORMSTL_OS_IS_WINDOWS)
519
+ # include <winstl/memory/processheap_allocator.hpp>
520
+ #endif /* VC++ _DEBUG */
521
+
522
+ #if defined(STLSOFT_COMPILER_IS_MSVC)
523
+ # pragma warning(disable : 4702) // suppresses "unreachable code"
524
+ #endif /* compiler */
525
+ EOF_main
526
+ expected = <<-EOF_main
527
+
528
+
529
+
530
+
531
+
532
+
533
+ #include "ximpl_core.hpp"
534
+ #ifndef UNIXSTL_NO_ATOMIC_INTEGER_OPERATIONS_ON_WINDOWS
535
+ # define UNIXSTL_NO_ATOMIC_INTEGER_OPERATIONS_ON_WINDOWS
536
+ #endif
537
+ #include <fastformat/quality/cover.h>
538
+
539
+ #ifdef FASTFORMAT_MT
540
+ # include <platformstl/synch/thread_mutex.hpp>
541
+ #else
542
+ # include <stlsoft/synch/null_mutex.hpp>
543
+ #endif
544
+
545
+ #include <stlsoft/memory/auto_buffer.hpp>
546
+ #include <stlsoft/synch/lock_scope.hpp>
547
+
548
+ #if defined(_DEBUG) && \
549
+ defined(PLATFORMSTL_OS_IS_WINDOWS)
550
+ # include <winstl/memory/processheap_allocator.hpp>
551
+ #endif
552
+
553
+ #if defined(STLSOFT_COMPILER_IS_MSVC)
554
+ # pragma warning(disable : 4702)
555
+ #endif
556
+ EOF_main
557
+ actual = strip(input, 'C')
558
+
559
+ assert_equal expected, actual
560
+ end
561
+
562
+ def test_real_sample_2
563
+
564
+ input = <<-EOF_main
565
+ /* /////////////////////////////////////////////////////////////////////////
566
+ * includes
567
+ */
568
+
569
+ #include "ximpl_core.hpp"
570
+ #ifndef UNIXSTL_NO_ATOMIC_INTEGER_OPERATIONS_ON_WINDOWS
571
+ # define UNIXSTL_NO_ATOMIC_INTEGER_OPERATIONS_ON_WINDOWS
572
+ #endif
573
+ #include <fastformat/internal/format_element.h>
574
+ #include <fastformat/internal/threading.h>
575
+ #include <fastformat/init_codes.h>
576
+ #include <fastformat/quality/contract.h>
577
+ #include <fastformat/quality/cover.h>
578
+
579
+ #ifdef FASTFORMAT_MT
580
+ # include <platformstl/synch/thread_mutex.hpp>
581
+ #else /* ? FASTFORMAT_MT */
582
+ # include <stlsoft/synch/null_mutex.hpp>
583
+ #endif /* FASTFORMAT_MT */
584
+
585
+ #include <stlsoft/memory/auto_buffer.hpp>
586
+ #include <stlsoft/smartptr/scoped_handle.hpp>
587
+ #include <stlsoft/smartptr/shared_ptr.hpp>
588
+ #include <stlsoft/string/string_view.hpp>
589
+ #include <stlsoft/synch/lock_scope.hpp>
590
+
591
+ #if defined(_DEBUG) && \
592
+ defined(PLATFORMSTL_OS_IS_WINDOWS)
593
+ # include <winstl/memory/processheap_allocator.hpp>
594
+ #endif /* VC++ _DEBUG */
595
+
596
+ #if defined(STLSOFT_COMPILER_IS_MSVC)
597
+ # pragma warning(disable : 4702) // suppresses "unreachable code"
598
+ #endif /* compiler */
599
+
600
+
601
+ #include <map>
602
+ #include <new>
603
+
604
+ #include <ctype.h>
605
+
606
+ #if defined(_DEBUG) && \
607
+ defined(STLSOFT_COMPILER_IS_MSVC)
608
+ # include <crtdbg.h>
609
+ #endif
610
+ EOF_main
611
+ expected = <<-EOF_main
612
+
613
+
614
+
615
+
616
+ #include "ximpl_core.hpp"
617
+ #ifndef UNIXSTL_NO_ATOMIC_INTEGER_OPERATIONS_ON_WINDOWS
618
+ # define UNIXSTL_NO_ATOMIC_INTEGER_OPERATIONS_ON_WINDOWS
619
+ #endif
620
+ #include <fastformat/internal/format_element.h>
621
+ #include <fastformat/internal/threading.h>
622
+ #include <fastformat/init_codes.h>
623
+ #include <fastformat/quality/contract.h>
624
+ #include <fastformat/quality/cover.h>
625
+
626
+ #ifdef FASTFORMAT_MT
627
+ # include <platformstl/synch/thread_mutex.hpp>
628
+ #else
629
+ # include <stlsoft/synch/null_mutex.hpp>
630
+ #endif
631
+
632
+ #include <stlsoft/memory/auto_buffer.hpp>
633
+ #include <stlsoft/smartptr/scoped_handle.hpp>
634
+ #include <stlsoft/smartptr/shared_ptr.hpp>
635
+ #include <stlsoft/string/string_view.hpp>
636
+ #include <stlsoft/synch/lock_scope.hpp>
637
+
638
+ #if defined(_DEBUG) && \
639
+ defined(PLATFORMSTL_OS_IS_WINDOWS)
640
+ # include <winstl/memory/processheap_allocator.hpp>
641
+ #endif
642
+
643
+ #if defined(STLSOFT_COMPILER_IS_MSVC)
644
+ # pragma warning(disable : 4702)
645
+ #endif
646
+
647
+
648
+ #include <map>
649
+ #include <new>
650
+
651
+ #include <ctype.h>
652
+
653
+ #if defined(_DEBUG) && \
654
+ defined(STLSOFT_COMPILER_IS_MSVC)
655
+ # include <crtdbg.h>
656
+ #endif
657
+ EOF_main
658
+
659
+ assert_equal expected, strip(input, 'C')
660
+ end
661
+
662
+ def test_real_sample_3
663
+
664
+ input = <<-EOF_main
665
+ /* /////////////////////////////////////////////////////////////////////////
666
+ * File: src/fmt_cache.cpp
667
+ *
668
+ * Purpose: Implementation file for FastFormat core API: format cache.
669
+ *
670
+ * Created: 18th September 2006
671
+ * Updated: 7th August 2015
672
+ *
673
+ * Home: http://www.fastformat.org/
674
+ *
675
+ * Copyright (c) 2006-2015, Matthew Wilson and Synesis Software
676
+ * All rights reserved.
677
+ *
678
+ * Redistribution and use in source and binary forms, with or without
679
+ * modification, are permitted provided that the following conditions are
680
+ * met:
681
+ *
682
+ * - Redistributions of source code must retain the above copyright notice,
683
+ * this list of conditions and the following disclaimer.
684
+ * - Redistributions in binary form must reproduce the above copyright
685
+ * notice, this list of conditions and the following disclaimer in the
686
+ * documentation and/or other materials provided with the distribution.
687
+ * - Neither the names of Matthew Wilson and Synesis Software nor the names
688
+ * of any contributors may be used to endorse or promote products derived
689
+ * from this software without specific prior written permission.
690
+ *
691
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
692
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
693
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
694
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
695
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
696
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
697
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
698
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
699
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
700
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
701
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
702
+ *
703
+ * ////////////////////////////////////////////////////////////////////// */
704
+
705
+
706
+
707
+ /* /////////////////////////////////////////////////////////////////////////
708
+ * includes
709
+ */
710
+
711
+ #include "ximpl_core.hpp"
712
+ #ifndef UNIXSTL_NO_ATOMIC_INTEGER_OPERATIONS_ON_WINDOWS
713
+ # define UNIXSTL_NO_ATOMIC_INTEGER_OPERATIONS_ON_WINDOWS
714
+ #endif
715
+ #include <fastformat/internal/format_element.h>
716
+ #include <fastformat/internal/threading.h>
717
+ #include <fastformat/init_codes.h>
718
+ #include <fastformat/quality/contract.h>
719
+ #include <fastformat/quality/cover.h>
720
+
721
+ #ifdef FASTFORMAT_MT
722
+ # include <platformstl/synch/thread_mutex.hpp>
723
+ #else /* ? FASTFORMAT_MT */
724
+ # include <stlsoft/synch/null_mutex.hpp>
725
+ #endif /* FASTFORMAT_MT */
726
+
727
+ #include <stlsoft/memory/auto_buffer.hpp>
728
+ #include <stlsoft/smartptr/scoped_handle.hpp>
729
+ #include <stlsoft/smartptr/shared_ptr.hpp>
730
+ #include <stlsoft/string/string_view.hpp>
731
+ #include <stlsoft/synch/lock_scope.hpp>
732
+
733
+ #if defined(_DEBUG) && \
734
+ defined(PLATFORMSTL_OS_IS_WINDOWS)
735
+ # include <winstl/memory/processheap_allocator.hpp>
736
+ #endif /* VC++ _DEBUG */
737
+
738
+ #if defined(STLSOFT_COMPILER_IS_MSVC)
739
+ # pragma warning(disable : 4702) // suppresses "unreachable code"
740
+ #endif /* compiler */
741
+
742
+
743
+ #include <map>
744
+ #include <new>
745
+ EOF_main
746
+
747
+ expected = <<-EOF_main
748
+
749
+
750
+
751
+
752
+
753
+
754
+
755
+
756
+
757
+
758
+
759
+
760
+
761
+
762
+
763
+
764
+
765
+
766
+
767
+
768
+
769
+
770
+
771
+
772
+
773
+
774
+
775
+
776
+
777
+
778
+
779
+
780
+
781
+
782
+
783
+
784
+
785
+
786
+
787
+
788
+
789
+
790
+
791
+
792
+
793
+
794
+ #include "ximpl_core.hpp"
795
+ #ifndef UNIXSTL_NO_ATOMIC_INTEGER_OPERATIONS_ON_WINDOWS
796
+ # define UNIXSTL_NO_ATOMIC_INTEGER_OPERATIONS_ON_WINDOWS
797
+ #endif
798
+ #include <fastformat/internal/format_element.h>
799
+ #include <fastformat/internal/threading.h>
800
+ #include <fastformat/init_codes.h>
801
+ #include <fastformat/quality/contract.h>
802
+ #include <fastformat/quality/cover.h>
803
+
804
+ #ifdef FASTFORMAT_MT
805
+ # include <platformstl/synch/thread_mutex.hpp>
806
+ #else
807
+ # include <stlsoft/synch/null_mutex.hpp>
808
+ #endif
809
+
810
+ #include <stlsoft/memory/auto_buffer.hpp>
811
+ #include <stlsoft/smartptr/scoped_handle.hpp>
812
+ #include <stlsoft/smartptr/shared_ptr.hpp>
813
+ #include <stlsoft/string/string_view.hpp>
814
+ #include <stlsoft/synch/lock_scope.hpp>
815
+
816
+ #if defined(_DEBUG) && \
817
+ defined(PLATFORMSTL_OS_IS_WINDOWS)
818
+ # include <winstl/memory/processheap_allocator.hpp>
819
+ #endif
820
+
821
+ #if defined(STLSOFT_COMPILER_IS_MSVC)
822
+ # pragma warning(disable : 4702)
823
+ #endif
824
+
825
+
826
+ #include <map>
827
+ #include <new>
828
+ EOF_main
829
+
830
+ actual = strip(input, 'C')
831
+
832
+ assert_equal expected, strip(input, 'C')
833
+ end
834
+
835
+ def test_real_sample_4
836
+
837
+ input = <<-EOF_main
838
+ /* /////////////////////////////////////////////////////////////////////////
839
+ * File: src/fmt_cache.cpp
840
+ *
841
+ * Purpose: Implementation file for FastFormat core API: format cache.
842
+ *
843
+ * Created: 18th September 2006
844
+ * Updated: 7th August 2015
845
+ *
846
+ * Home: http://www.fastformat.org/
847
+ *
848
+ * Copyright (c) 2006-2015, Matthew Wilson and Synesis Software
849
+ * All rights reserved.
850
+ *
851
+ * Redistribution and use in source and binary forms, with or without
852
+ * modification, are permitted provided that the following conditions are
853
+ * met:
854
+ *
855
+ * - Redistributions of source code must retain the above copyright notice,
856
+ * this list of conditions and the following disclaimer.
857
+ * - Redistributions in binary form must reproduce the above copyright
858
+ * notice, this list of conditions and the following disclaimer in the
859
+ * documentation and/or other materials provided with the distribution.
860
+ * - Neither the names of Matthew Wilson and Synesis Software nor the names
861
+ * of any contributors may be used to endorse or promote products derived
862
+ * from this software without specific prior written permission.
863
+ *
864
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
865
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
866
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
867
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
868
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
869
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
870
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
871
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
872
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
873
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
874
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
875
+ *
876
+ * ////////////////////////////////////////////////////////////////////// */
877
+
878
+
879
+
880
+ /* /////////////////////////////////////////////////////////////////////////
881
+ * includes
882
+ */
883
+
884
+ #include "ximpl_core.hpp"
885
+ #ifndef UNIXSTL_NO_ATOMIC_INTEGER_OPERATIONS_ON_WINDOWS
886
+ # define UNIXSTL_NO_ATOMIC_INTEGER_OPERATIONS_ON_WINDOWS
887
+ #endif
888
+ #include <fastformat/internal/format_element.h>
889
+ #include <fastformat/internal/threading.h>
890
+ #include <fastformat/init_codes.h>
891
+ #include <fastformat/quality/contract.h>
892
+ #include <fastformat/quality/cover.h>
893
+
894
+ #ifdef FASTFORMAT_MT
895
+ # include <platformstl/synch/thread_mutex.hpp>
896
+ #else /* ? FASTFORMAT_MT */
897
+ # include <stlsoft/synch/null_mutex.hpp>
898
+ #endif /* FASTFORMAT_MT */
899
+
900
+ #include <stlsoft/memory/auto_buffer.hpp>
901
+ #include <stlsoft/smartptr/scoped_handle.hpp>
902
+ #include <stlsoft/smartptr/shared_ptr.hpp>
903
+ #include <stlsoft/string/string_view.hpp>
904
+ #include <stlsoft/synch/lock_scope.hpp>
905
+
906
+ #if defined(_DEBUG) && \
907
+ defined(PLATFORMSTL_OS_IS_WINDOWS)
908
+ # include <winstl/memory/processheap_allocator.hpp>
909
+ #endif /* VC++ _DEBUG */
910
+
911
+ #if defined(STLSOFT_COMPILER_IS_MSVC)
912
+ # pragma warning(disable : 4702) // suppresses "unreachable code"
913
+ #endif /* compiler */
914
+
915
+
916
+ #include <map>
917
+ #include <new>
918
+
919
+ #include <ctype.h>
920
+
921
+ #if defined(_DEBUG) && \
922
+ defined(STLSOFT_COMPILER_IS_MSVC)
923
+ # include <crtdbg.h>
924
+ #endif
925
+
926
+ /* /////////////////////////////////////////////////////////////////////////
927
+ * Implementation selection
928
+ */
929
+
930
+ //#define _FASTFORMAT_USE_TSS_CACHE
931
+ //#define _FASTFORMAT_USE_1PHASE_CACHE
932
+ #define _FASTFORMAT_USE_2PHASE_CACHE
933
+
934
+ /* /////////////////////////////////////////////////////////////////////////
935
+ * Namespace
936
+ */
937
+
938
+ #if !defined(FASTFORMAT_NO_NAMESPACE)
939
+ namespace fastformat
940
+ {
941
+ #endif /* !FASTFORMAT_NO_NAMESPACE */
942
+
943
+ /* /////////////////////////////////////////////////////////////////////////
944
+ * Types & Non-local variables
945
+ */
946
+
947
+ namespace
948
+ {
949
+ void* operator_new(size_t cb)
950
+ {
951
+ FASTFORMAT_COVER_MARK_ENTRY();
952
+
953
+ #if defined(_DEBUG) && \
954
+ defined(PLATFORMSTL_OS_IS_WINDOWS)
955
+ return ::HeapAlloc(::GetProcessHeap(), 0, cb);
956
+ #else /* ? VC++ _DEBUG */
957
+ return ::operator new(cb);
958
+ #endif /* VC++ _DEBUG */
959
+ }
960
+
961
+ void operator_delete(void* pv)
962
+ {
963
+ FASTFORMAT_COVER_MARK_ENTRY();
964
+
965
+ #if defined(_DEBUG) && \
966
+ defined(PLATFORMSTL_OS_IS_WINDOWS)
967
+ ::HeapFree(::GetProcessHeap(), 0, pv);
968
+ #else /* ? VC++ _DEBUG */
969
+ ::operator delete(pv);
970
+ #endif /* VC++ _DEBUG */
971
+ }
972
+
973
+
974
+ struct pattern_record_base_t
975
+ {
976
+ unsigned numFormatElements;
977
+ unsigned numResultElements;
978
+ size_t cchPattern;
979
+ format_element_t const* elements;
980
+ format_element_t elements_[2]; // Two, so can test packing
981
+ };
982
+
983
+ /* That weird linker defect with VC++ 8+ raises its ugly head again
984
+ * here, so we have to specialise in more details. Super-boring
985
+ */
986
+ #if defined(STLSOFT_COMPILER_IS_MSVC) && \
987
+ _MSC_VER >= 1400
988
+ typedef stlsoft::basic_string_view<
989
+ ff_char_t
990
+ , std::char_traits<ff_char_t>
991
+ , std::allocator<ff_char_t>
992
+ > pattern_t;
993
+ #else /* ? compiler */
994
+ # ifdef FASTFORMAT_USE_WIDE_STRINGS
995
+ typedef stlsoft::wstring_view pattern_t;
996
+ # else /* ? FASTFORMAT_USE_WIDE_STRINGS */
997
+ typedef stlsoft::string_view pattern_t;
998
+ # endif /* FASTFORMAT_USE_WIDE_STRINGS */
999
+ #endif /* compiler */
1000
+
1001
+ struct pattern_record_t
1002
+ : public pattern_record_base_t
1003
+ {
1004
+ public: /// Member Types
1005
+ typedef pattern_record_t class_type;
1006
+ typedef ff_char_t char_type;
1007
+
1008
+ public: /// Construction
1009
+ pattern_record_t(
1010
+ pattern_t pattern
1011
+ , format_element_t const* elements
1012
+ , unsigned numFormatElements
1013
+ , unsigned numResultElements
1014
+ );
1015
+
1016
+ void* operator new(size_t, size_t numFormatElements, size_t cchPattern);
1017
+ #if !defined(STLSOFT_COMPILER_IS_BORLAND) || \
1018
+ __BORLANDC__ > 0x0582
1019
+ void operator delete(void*, size_t numFormatElements, size_t cchPattern);
1020
+ #endif /* compiler */
1021
+ void operator delete(void*);
1022
+
1023
+ public: /// Accessors
1024
+ pattern_t pattern() const;
1025
+
1026
+ private: /// Implementation
1027
+ ff_char_t* get_pattern_memory_() const;
1028
+ };
1029
+
1030
+ // A comparison function class that avoids any strcmp/memcmp
1031
+ // when the lengths are different
1032
+ struct pattern_fast_less_t
1033
+ {
1034
+ bool operator ()(pattern_t const& lhs, pattern_t const& rhs) const
1035
+ {
1036
+ size_t lhsLen = lhs.size();
1037
+ size_t rhsLen = rhs.size();
1038
+
1039
+ if(lhsLen != rhsLen)
1040
+ {
1041
+ return lhsLen < rhsLen;
1042
+ }
1043
+ else
1044
+ {
1045
+ return lhs < rhs;
1046
+ }
1047
+ }
1048
+
1049
+ };
1050
+
1051
+ class format_cache
1052
+ {
1053
+ private: /// Member Types
1054
+ #ifdef FASTFORMAT_MT
1055
+ typedef ::platformstl::thread_mutex mutex_type_;
1056
+ #else /* ? FASTFORMAT_MT */
1057
+ typedef ::stlsoft::null_mutex mutex_type_;
1058
+ #endif /* FASTFORMAT_MT */
1059
+ typedef stlsoft::shared_ptr<pattern_record_t> record_ptr_type_;
1060
+ typedef std::map< pattern_t
1061
+ , record_ptr_type_
1062
+ #if !defined(UNIXSTL_OS_IS_MACOSX)
1063
+ # if 1
1064
+ , std::less<pattern_t>
1065
+ # else /* ? 0 */
1066
+ , pattern_fast_less_t
1067
+ # endif /* 0 */
1068
+
1069
+ # if !defined(STLSOFT_COMPILER_IS_MWERKS)
1070
+ # if defined(_DEBUG) && \
1071
+ defined(PLATFORMSTL_OS_IS_WINDOWS) && \
1072
+ ( !defined(STLSOFT_COMPILER_IS_MSVC) || \
1073
+ _MSC_VER < 1400)
1074
+ , winstl::processheap_allocator<pattern_t>
1075
+ # else /* ? VC++ _DEBUG */
1076
+ , std::allocator<pattern_t>
1077
+ # endif /* VC++ _DEBUG */
1078
+ # endif /* compiler */
1079
+ #endif /* UNIXSTL_OS_IS_MACOSX */
1080
+ > map_type_;
1081
+ typedef stlsoft::auto_buffer<format_element_t> format_elements_type_;
1082
+
1083
+ public: /// Construction
1084
+ void* operator new(size_t cb);
1085
+ void operator delete(void* pv);
1086
+
1087
+ public:
1088
+ unsigned lookup_pattern(
1089
+ pattern_t pattern
1090
+ , format_element_t const** elements
1091
+ );
1092
+ unsigned lookup_pattern_tss(
1093
+ pattern_t pattern
1094
+ , format_element_t const** elements
1095
+ );
1096
+ unsigned lookup_pattern_1phase(
1097
+ pattern_t pattern
1098
+ , format_element_t const** elements
1099
+ );
1100
+ unsigned lookup_pattern_2phase(
1101
+ pattern_t pattern
1102
+ , format_element_t const** elements
1103
+ );
1104
+
1105
+ private:
1106
+ mutex_type_ m_mx;
1107
+ map_type_ m_map;
1108
+ };
1109
+
1110
+ } // anonymous namespace
1111
+
1112
+ /* /////////////////////////////////////////////////////////////////////////
1113
+ * Implementation Functions
1114
+ */
1115
+
1116
+ // class ximpl_core
1117
+
1118
+ int ximpl_core::fastformat_impl_formatCache_init(void** ptoken)
1119
+ {
1120
+ FASTFORMAT_CONTRACT_ENFORCE_PRECONDITION_STATE_INTERNAL(NULL != ptoken, "token pointer must not be null");
1121
+
1122
+ FASTFORMAT_COVER_MARK_ENTRY();
1123
+
1124
+ try
1125
+ {
1126
+ FASTFORMAT_COVER_MARK_ENTRY();
1127
+
1128
+ format_cache* cache = new format_cache();
1129
+
1130
+ if(NULL == cache)
1131
+ {
1132
+ FASTFORMAT_COVER_MARK_ENTRY();
1133
+
1134
+ return FASTFORMAT_INIT_RC_OUT_OF_MEMORY;
1135
+ }
1136
+
1137
+ *ptoken = cache;
1138
+
1139
+ return FASTFORMAT_INIT_RC_SUCCESS;
1140
+ }
1141
+ catch(std::bad_alloc&)
1142
+ {
1143
+ FASTFORMAT_COVER_MARK_ENTRY();
1144
+
1145
+ return FASTFORMAT_INIT_RC_OUT_OF_MEMORY;
1146
+ }
1147
+ catch(std::exception&)
1148
+ {
1149
+ FASTFORMAT_COVER_MARK_ENTRY();
1150
+
1151
+ return FASTFORMAT_INIT_RC_UNSPECIFIED_EXCEPTION;
1152
+ }
1153
+ catch(...)
1154
+ {
1155
+ FASTFORMAT_COVER_MARK_ENTRY();
1156
+
1157
+ return FASTFORMAT_INIT_RC_UNSPECIFIED_ERROR;
1158
+ }
1159
+ }
1160
+
1161
+ void ximpl_core::fastformat_impl_formatCache_uninit(void* token)
1162
+ {
1163
+ FASTFORMAT_COVER_MARK_ENTRY();
1164
+
1165
+ FASTFORMAT_CONTRACT_ENFORCE_PRECONDITION_STATE_INTERNAL(NULL != token, "token must not be null");
1166
+
1167
+ delete static_cast<format_cache*>(token);
1168
+ }
1169
+
1170
+ unsigned ximpl_core::fastformat_impl_formatCache_lookupPattern(
1171
+ void* token
1172
+ , ff_char_t const* pattern
1173
+ , size_t cchPattern
1174
+ , format_element_t const** elements
1175
+ )
1176
+ {
1177
+ FASTFORMAT_CONTRACT_ENFORCE_PRECONDITION_PARAMS_INTERNAL(NULL != token, "state pointer must be null");
1178
+
1179
+ FASTFORMAT_COVER_MARK_ENTRY();
1180
+
1181
+ format_cache* cache = static_cast<format_cache*>(token);
1182
+
1183
+ if(0 == cchPattern)
1184
+ {
1185
+ FASTFORMAT_COVER_MARK_ENTRY();
1186
+
1187
+ return 0;
1188
+ }
1189
+ else
1190
+ {
1191
+ FASTFORMAT_COVER_MARK_ENTRY();
1192
+
1193
+ pattern_t p(pattern, cchPattern);
1194
+
1195
+ return cache->lookup_pattern(p, elements);
1196
+ }
1197
+ }
1198
+
1199
+
1200
+ namespace
1201
+ {
1202
+
1203
+ void* format_cache::operator new(size_t cb)
1204
+ {
1205
+ FASTFORMAT_COVER_MARK_ENTRY();
1206
+
1207
+ return operator_new(cb);
1208
+ }
1209
+
1210
+ void format_cache::operator delete(void* pv)
1211
+ {
1212
+ FASTFORMAT_COVER_MARK_ENTRY();
1213
+
1214
+ operator_delete(pv);
1215
+ }
1216
+
1217
+
1218
+ unsigned format_cache::lookup_pattern(
1219
+ pattern_t pattern
1220
+ , format_element_t const** elements
1221
+ )
1222
+ {
1223
+ FASTFORMAT_COVER_MARK_ENTRY();
1224
+
1225
+ #if defined(_FASTFORMAT_USE_TSS_CACHE)
1226
+ return this->lookup_pattern_tss(pattern, elements);
1227
+ #elif defined(_FASTFORMAT_USE_1PHASE_CACHE)
1228
+ return this->lookup_pattern_1phase(pattern, elements);
1229
+ #elif defined(_FASTFORMAT_USE_2PHASE_CACHE)
1230
+ return this->lookup_pattern_2phase(pattern, elements);
1231
+ #else /* ? cache */
1232
+ # error Implementation not discriminated
1233
+ #endif /* cache */
1234
+ }
1235
+
1236
+ unsigned format_cache::lookup_pattern_1phase(
1237
+ pattern_t pattern
1238
+ , format_element_t const** elements
1239
+ )
1240
+ {
1241
+ FASTFORMAT_COVER_MARK_ENTRY();
1242
+
1243
+ FASTFORMAT_CONTRACT_ENFORCE_PRECONDITION_PARAMS_INTERNAL(NULL != elements, "elements parameter may not be null");
1244
+
1245
+ FASTFORMAT_COVER_MARK_ENTRY();
1246
+
1247
+ stlsoft::lock_scope<mutex_type_> lock(m_mx);
1248
+ map_type_::const_iterator it = m_map.find(pattern);
1249
+
1250
+ if(it == m_map.end())
1251
+ {
1252
+ FASTFORMAT_COVER_MARK_ENTRY();
1253
+
1254
+ /* (1 + len) / 2
1255
+
1256
+ " " 1 => 1 1
1257
+ "{0}" 3 => 1 2
1258
+ " {0}" 4 => 2 2
1259
+ " {0} " 5 => 3 3
1260
+ "{0} {0} " 8 => 4 4
1261
+ " {0} {0} " 9 => 5 5
1262
+ " {0} {0} {0}" 12 => 6 6
1263
+ "{0} {0} {0} {0}" 15 => 7 8
1264
+ "{0} {0} {0} {0} " 16 => 8 8
1265
+ " {0} {0} {0} {0}" 16 => 8 8
1266
+ " {0} {0} {0} {0} " 17 => 9 9
1267
+
1268
+ "{0,2}" 5 => 2 3
1269
+ " {0,2}" 6 => 3 3
1270
+ "{0,2} " 6 => 3 3
1271
+ " {0,2} " 7 => 4 4
1272
+ " {0,2} {0,2} " 13 => 7 7
1273
+ "{0,2}{0,2}{0,2}" 15 => 6 8
1274
+ "{0,2} {0,2} {0,2} " 18 => 9 9
1275
+ " {0,2} {0,2} {0,2}" 18 => 9 9
1276
+ " {0,2} {0,2} {0,2} " 19 => 10 10
1277
+ */
1278
+
1279
+ format_elements_type_ formatElements(1 + pattern.size() / 2);
1280
+ unsigned numFormatElements;
1281
+ unsigned numResultElements;
1282
+
1283
+ unsigned n = fastformat_parseFormat(pattern.data(), pattern.size(), &formatElements[0], formatElements.size(), NULL, NULL);
1284
+
1285
+ numFormatElements = n & 0xffff;
1286
+ numResultElements = n >> 16;
1287
+
1288
+ STLSOFT_ASSERT(numFormatElements <= formatElements.size());
1289
+
1290
+ #if defined(_DEBUG) && \
1291
+ defined(STLSOFT_COMPILER_IS_MSVC)
1292
+ // This code ensures that subsequent allocations made in this scope
1293
+ // to the MSVCRT heap will not be tracked.
1294
+ //
1295
+ // This is done because FF's caching can lead to false positivies in
1296
+ // leak reporting, which we don't want and you don't want. The
1297
+ // possible downside is that if FF has some genuine leaks in this
1298
+ // area, they may not be reported. Given the maturity of the project
1299
+ // we feel that this is a very low risk, and therfore worth taking.
1300
+ int prev = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
1301
+ _CrtSetDbgFlag(prev & ~_CRTDBG_ALLOC_MEM_DF);
1302
+
1303
+ stlsoft::scoped_handle<int> scoperCrt(prev, _CrtSetDbgFlag);
1304
+ #endif
1305
+
1306
+ record_ptr_type_ ptr(new(numFormatElements, pattern.size()) pattern_record_t(pattern, &formatElements[0], numFormatElements, numResultElements));
1307
+
1308
+ it = m_map.insert(std::make_pair(ptr->pattern(), ptr)).first;
1309
+ }
1310
+
1311
+ FASTFORMAT_COVER_MARK_ENTRY();
1312
+
1313
+ record_ptr_type_ recptr = (*it).second;
1314
+
1315
+ *elements = recptr->elements;
1316
+
1317
+ FASTFORMAT_COVER_MARK_ENTRY();
1318
+
1319
+ return (recptr->numFormatElements & 0xffff) | ((recptr->numResultElements & 0xffff) << 16);
1320
+ }
1321
+
1322
+ unsigned format_cache::lookup_pattern_2phase(
1323
+ pattern_t pattern
1324
+ , format_element_t const** elements
1325
+ )
1326
+ {
1327
+ FASTFORMAT_COVER_MARK_ENTRY();
1328
+
1329
+ FASTFORMAT_CONTRACT_ENFORCE_PRECONDITION_PARAMS_INTERNAL(NULL != elements, "elements parameter may not be null");
1330
+
1331
+ #ifndef FASTFORMAT_MT
1332
+
1333
+ return this->lookup_pattern_1phase(pattern, elements);
1334
+
1335
+ #else /* ? FASTFORMAT_MT */
1336
+
1337
+ FASTFORMAT_COVER_MARK_ENTRY();
1338
+
1339
+ { // Phase 1
1340
+
1341
+ FASTFORMAT_COVER_MARK_ENTRY();
1342
+
1343
+ stlsoft::lock_scope<mutex_type_> lock(m_mx);
1344
+ map_type_::const_iterator it = m_map.find(pattern);
1345
+
1346
+ if(it != m_map.end())
1347
+ {
1348
+ FASTFORMAT_COVER_MARK_ENTRY();
1349
+
1350
+ record_ptr_type_ ptr = (*it).second;
1351
+
1352
+ *elements = ptr->elements;
1353
+
1354
+ return (ptr->numFormatElements & 0xffff) | ((ptr->numResultElements & 0xffff) << 16);
1355
+ }
1356
+ }
1357
+
1358
+ FASTFORMAT_COVER_MARK_ENTRY();
1359
+
1360
+ // If we have reached this point, we know that the pattern has not
1361
+ // yet been cached. So we parse it, and then attempt to cache it.
1362
+
1363
+ format_elements_type_ formatElements(1 + pattern.size() / 2);
1364
+ unsigned numFormatElements;
1365
+ unsigned numResultElements;
1366
+
1367
+ unsigned n = fastformat_parseFormat(pattern.data(), pattern.size(), &formatElements[0], formatElements.size(), NULL, NULL);
1368
+
1369
+ numFormatElements = n & 0xffff;
1370
+ numResultElements = n >> 16;
1371
+
1372
+ FASTFORMAT_CONTRACT_ENFORCE_POSTCONDITION_RETURN_INTERNAL(numFormatElements <= formatElements.size(), "number of pattern elements calculated cannot be greater than the number specified available");
1373
+
1374
+ #if defined(_DEBUG) && \
1375
+ defined(STLSOFT_COMPILER_IS_MSVC)
1376
+ // This code ensures that subsequent allocations made in this scope
1377
+ // to the MSVCRT heap will not be tracked.
1378
+ //
1379
+ // This is done because FF's caching can lead to false positivies in
1380
+ // leak reporting, which we don't want and you don't want. The
1381
+ // possible downside is that if FF has some genuine leaks in this
1382
+ // area, they may not be reported. Given the maturity of the project
1383
+ // we feel that this is a very low risk, and therfore worth taking.
1384
+ int prev = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
1385
+ _CrtSetDbgFlag(prev & ~_CRTDBG_ALLOC_MEM_DF);
1386
+
1387
+ stlsoft::scoped_handle<int> scoperCrt(prev, _CrtSetDbgFlag);
1388
+ #endif
1389
+
1390
+ record_ptr_type_ ptr(new(numFormatElements, pattern.size()) pattern_record_t(pattern, &formatElements[0], numFormatElements, numResultElements));
1391
+
1392
+ { // Phase 2
1393
+
1394
+ FASTFORMAT_COVER_MARK_ENTRY();
1395
+
1396
+ stlsoft::lock_scope<mutex_type_> lock(m_mx);
1397
+
1398
+ // We must check again, since another thread might have parsed and
1399
+ // inserted in the time between the end of phase 1 and now
1400
+
1401
+ map_type_::const_iterator it = m_map.find(pattern);
1402
+
1403
+ if(it != m_map.end())
1404
+ {
1405
+ FASTFORMAT_COVER_MARK_ENTRY();
1406
+
1407
+ // It was inserted by another thread;
1408
+ }
1409
+ else
1410
+ {
1411
+ FASTFORMAT_COVER_MARK_ENTRY();
1412
+
1413
+ it = m_map.insert(std::make_pair(ptr->pattern(), ptr)).first;
1414
+ }
1415
+
1416
+ record_ptr_type_ recptr = (*it).second;
1417
+
1418
+ *elements = recptr->elements;
1419
+
1420
+ FASTFORMAT_COVER_MARK_ENTRY();
1421
+
1422
+ return (recptr->numFormatElements & 0xffff) | ((recptr->numResultElements & 0xffff) << 16);
1423
+ }
1424
+ #endif /* FASTFORMAT_MT */
1425
+ }
1426
+
1427
+ namespace
1428
+ {
1429
+
1430
+ const size_t offsetElement0 = STLSOFT_RAW_OFFSETOF(pattern_record_base_t, elements_[0]);
1431
+ const size_t offsetElement1 = STLSOFT_RAW_OFFSETOF(pattern_record_base_t, elements_[1]);
1432
+ const size_t sizeofElement = offsetElement1 - offsetElement0;
1433
+
1434
+ } // anonymous namespace
1435
+
1436
+ void* pattern_record_t::operator new(size_t /* cb */, size_t numFormatElements, size_t cchPattern)
1437
+ {
1438
+ FASTFORMAT_COVER_MARK_ENTRY();
1439
+
1440
+ const size_t size = offsetElement0
1441
+ + ((numFormatElements < 2) ? 2 : numFormatElements) * sizeofElement
1442
+ + sizeof(ff_char_t) * (cchPattern + 1);
1443
+
1444
+ return operator_new(size);
1445
+ }
1446
+
1447
+ #if !defined(STLSOFT_COMPILER_IS_BORLAND) || \
1448
+ __BORLANDC__ > 0x0582
1449
+ void pattern_record_t::operator delete(void* pv, size_t /* numFormatElements */, size_t /* cchPattern */)
1450
+ {
1451
+ FASTFORMAT_COVER_MARK_ENTRY();
1452
+
1453
+ operator_delete(pv);
1454
+ }
1455
+ #endif /* compiler */
1456
+
1457
+ void pattern_record_t::operator delete(void* pv)
1458
+ {
1459
+ FASTFORMAT_COVER_MARK_ENTRY();
1460
+
1461
+ operator_delete(pv);
1462
+ }
1463
+
1464
+ inline ff_char_t* pattern_record_t::get_pattern_memory_() const
1465
+ {
1466
+ const size_t elementsSize = offsetElement0
1467
+ + ((numFormatElements < 2) ? 2 : numFormatElements) * sizeofElement;
1468
+
1469
+ return reinterpret_cast<char_type*>(const_cast<void*>(stlsoft::ptr_byte_offset(this, ptrdiff_t(elementsSize))));
1470
+ }
1471
+
1472
+
1473
+ pattern_record_t::pattern_record_t(
1474
+ pattern_t pattern
1475
+ , format_element_t const* elements
1476
+ , unsigned numFormatElements
1477
+ , unsigned numResultElements
1478
+ )
1479
+ {
1480
+ FASTFORMAT_COVER_MARK_ENTRY();
1481
+
1482
+ this->numFormatElements = numFormatElements;
1483
+ this->numResultElements = numResultElements;
1484
+ this->cchPattern = pattern.size();
1485
+
1486
+ char_type* embeddedPattern = get_pattern_memory_();
1487
+
1488
+ ::memcpy(embeddedPattern, pattern.data(), sizeof(char_type) * pattern.size());
1489
+ embeddedPattern[pattern.size()] = '\0';
1490
+
1491
+ this->elements = &this->elements_[0];
1492
+
1493
+ {
1494
+ FASTFORMAT_COVER_MARK_ENTRY();
1495
+
1496
+ format_element_t* element = &this->elements_[0];
1497
+ size_t i = 0;
1498
+
1499
+ for(; i != numFormatElements; ++i, ++element, ++elements)
1500
+ {
1501
+ FASTFORMAT_COVER_MARK_ENTRY();
1502
+
1503
+ #if 1
1504
+ element->len = elements->len;
1505
+ element->ptr = embeddedPattern + (elements->ptr - pattern.data());
1506
+ element->index = elements->index;
1507
+ element->minWidth = elements->minWidth;
1508
+ element->maxWidth = elements->maxWidth;
1509
+ element->alignment = elements->alignment;
1510
+ element->fill = elements->fill;
1511
+ #else /* ? 0 */
1512
+ ::memcpy(element, elements, sizeof(*element));
1513
+ element->ptr = embeddedPattern + (elements->ptr - pattern.data());
1514
+ #endif /* 0 */
1515
+
1516
+ STLSOFT_ASSERT(0 == ::memcmp(element->ptr, elements->ptr, element->len));
1517
+ }
1518
+ }
1519
+ }
1520
+
1521
+ pattern_t pattern_record_t::pattern() const
1522
+ {
1523
+ /// TODO: place a length record into the memory, between the elements and
1524
+ /// the pattern, and then this invocation will not have to do a strlen.
1525
+ return pattern_t(get_pattern_memory_(), cchPattern);
1526
+ }
1527
+
1528
+
1529
+ } // anonymous namespace
1530
+
1531
+ /* /////////////////////////////////////////////////////////////////////////
1532
+ * Namespace
1533
+ */
1534
+
1535
+ #if !defined(FASTFORMAT_NO_NAMESPACE)
1536
+ } /* namespace fastformat */
1537
+ #endif /* !FASTFORMAT_NO_NAMESPACE */
1538
+
1539
+ /* ///////////////////////////// end of file //////////////////////////// */
1540
+ EOF_main
1541
+
1542
+ expected = <<-EOF_main
1543
+
1544
+
1545
+
1546
+
1547
+
1548
+
1549
+
1550
+
1551
+
1552
+
1553
+
1554
+
1555
+
1556
+
1557
+
1558
+
1559
+
1560
+
1561
+
1562
+
1563
+
1564
+
1565
+
1566
+
1567
+
1568
+
1569
+
1570
+
1571
+
1572
+
1573
+
1574
+
1575
+
1576
+
1577
+
1578
+
1579
+
1580
+
1581
+
1582
+
1583
+
1584
+
1585
+
1586
+
1587
+
1588
+
1589
+ #include "ximpl_core.hpp"
1590
+ #ifndef UNIXSTL_NO_ATOMIC_INTEGER_OPERATIONS_ON_WINDOWS
1591
+ # define UNIXSTL_NO_ATOMIC_INTEGER_OPERATIONS_ON_WINDOWS
1592
+ #endif
1593
+ #include <fastformat/internal/format_element.h>
1594
+ #include <fastformat/internal/threading.h>
1595
+ #include <fastformat/init_codes.h>
1596
+ #include <fastformat/quality/contract.h>
1597
+ #include <fastformat/quality/cover.h>
1598
+
1599
+ #ifdef FASTFORMAT_MT
1600
+ # include <platformstl/synch/thread_mutex.hpp>
1601
+ #else
1602
+ # include <stlsoft/synch/null_mutex.hpp>
1603
+ #endif
1604
+
1605
+ #include <stlsoft/memory/auto_buffer.hpp>
1606
+ #include <stlsoft/smartptr/scoped_handle.hpp>
1607
+ #include <stlsoft/smartptr/shared_ptr.hpp>
1608
+ #include <stlsoft/string/string_view.hpp>
1609
+ #include <stlsoft/synch/lock_scope.hpp>
1610
+
1611
+ #if defined(_DEBUG) && \
1612
+ defined(PLATFORMSTL_OS_IS_WINDOWS)
1613
+ # include <winstl/memory/processheap_allocator.hpp>
1614
+ #endif
1615
+
1616
+ #if defined(STLSOFT_COMPILER_IS_MSVC)
1617
+ # pragma warning(disable : 4702)
1618
+ #endif
1619
+
1620
+
1621
+ #include <map>
1622
+ #include <new>
1623
+
1624
+ #include <ctype.h>
1625
+
1626
+ #if defined(_DEBUG) && \
1627
+ defined(STLSOFT_COMPILER_IS_MSVC)
1628
+ # include <crtdbg.h>
1629
+ #endif
1630
+
1631
+
1632
+
1633
+
1634
+
1635
+
1636
+
1637
+ #define _FASTFORMAT_USE_2PHASE_CACHE
1638
+
1639
+
1640
+
1641
+
1642
+
1643
+ #if !defined(FASTFORMAT_NO_NAMESPACE)
1644
+ namespace fastformat
1645
+ {
1646
+ #endif
1647
+
1648
+
1649
+
1650
+
1651
+
1652
+ namespace
1653
+ {
1654
+ void* operator_new(size_t cb)
1655
+ {
1656
+ FASTFORMAT_COVER_MARK_ENTRY();
1657
+
1658
+ #if defined(_DEBUG) && \
1659
+ defined(PLATFORMSTL_OS_IS_WINDOWS)
1660
+ return ::HeapAlloc(::GetProcessHeap(), 0, cb);
1661
+ #else
1662
+ return ::operator new(cb);
1663
+ #endif
1664
+ }
1665
+
1666
+ void operator_delete(void* pv)
1667
+ {
1668
+ FASTFORMAT_COVER_MARK_ENTRY();
1669
+
1670
+ #if defined(_DEBUG) && \
1671
+ defined(PLATFORMSTL_OS_IS_WINDOWS)
1672
+ ::HeapFree(::GetProcessHeap(), 0, pv);
1673
+ #else
1674
+ ::operator delete(pv);
1675
+ #endif
1676
+ }
1677
+
1678
+
1679
+ struct pattern_record_base_t
1680
+ {
1681
+ unsigned numFormatElements;
1682
+ unsigned numResultElements;
1683
+ size_t cchPattern;
1684
+ format_element_t const* elements;
1685
+ format_element_t elements_[2];
1686
+ };
1687
+
1688
+
1689
+
1690
+
1691
+ #if defined(STLSOFT_COMPILER_IS_MSVC) && \
1692
+ _MSC_VER >= 1400
1693
+ typedef stlsoft::basic_string_view<
1694
+ ff_char_t
1695
+ , std::char_traits<ff_char_t>
1696
+ , std::allocator<ff_char_t>
1697
+ > pattern_t;
1698
+ #else
1699
+ # ifdef FASTFORMAT_USE_WIDE_STRINGS
1700
+ typedef stlsoft::wstring_view pattern_t;
1701
+ # else
1702
+ typedef stlsoft::string_view pattern_t;
1703
+ # endif
1704
+ #endif
1705
+
1706
+ struct pattern_record_t
1707
+ : public pattern_record_base_t
1708
+ {
1709
+ public:
1710
+ typedef pattern_record_t class_type;
1711
+ typedef ff_char_t char_type;
1712
+
1713
+ public:
1714
+ pattern_record_t(
1715
+ pattern_t pattern
1716
+ , format_element_t const* elements
1717
+ , unsigned numFormatElements
1718
+ , unsigned numResultElements
1719
+ );
1720
+
1721
+ void* operator new(size_t, size_t numFormatElements, size_t cchPattern);
1722
+ #if !defined(STLSOFT_COMPILER_IS_BORLAND) || \
1723
+ __BORLANDC__ > 0x0582
1724
+ void operator delete(void*, size_t numFormatElements, size_t cchPattern);
1725
+ #endif
1726
+ void operator delete(void*);
1727
+
1728
+ public:
1729
+ pattern_t pattern() const;
1730
+
1731
+ private:
1732
+ ff_char_t* get_pattern_memory_() const;
1733
+ };
1734
+
1735
+
1736
+
1737
+ struct pattern_fast_less_t
1738
+ {
1739
+ bool operator ()(pattern_t const& lhs, pattern_t const& rhs) const
1740
+ {
1741
+ size_t lhsLen = lhs.size();
1742
+ size_t rhsLen = rhs.size();
1743
+
1744
+ if(lhsLen != rhsLen)
1745
+ {
1746
+ return lhsLen < rhsLen;
1747
+ }
1748
+ else
1749
+ {
1750
+ return lhs < rhs;
1751
+ }
1752
+ }
1753
+
1754
+ };
1755
+
1756
+ class format_cache
1757
+ {
1758
+ private:
1759
+ #ifdef FASTFORMAT_MT
1760
+ typedef ::platformstl::thread_mutex mutex_type_;
1761
+ #else
1762
+ typedef ::stlsoft::null_mutex mutex_type_;
1763
+ #endif
1764
+ typedef stlsoft::shared_ptr<pattern_record_t> record_ptr_type_;
1765
+ typedef std::map< pattern_t
1766
+ , record_ptr_type_
1767
+ #if !defined(UNIXSTL_OS_IS_MACOSX)
1768
+ # if 1
1769
+ , std::less<pattern_t>
1770
+ # else
1771
+ , pattern_fast_less_t
1772
+ # endif
1773
+
1774
+ # if !defined(STLSOFT_COMPILER_IS_MWERKS)
1775
+ # if defined(_DEBUG) && \
1776
+ defined(PLATFORMSTL_OS_IS_WINDOWS) && \
1777
+ ( !defined(STLSOFT_COMPILER_IS_MSVC) || \
1778
+ _MSC_VER < 1400)
1779
+ , winstl::processheap_allocator<pattern_t>
1780
+ # else
1781
+ , std::allocator<pattern_t>
1782
+ # endif
1783
+ # endif
1784
+ #endif
1785
+ > map_type_;
1786
+ typedef stlsoft::auto_buffer<format_element_t> format_elements_type_;
1787
+
1788
+ public:
1789
+ void* operator new(size_t cb);
1790
+ void operator delete(void* pv);
1791
+
1792
+ public:
1793
+ unsigned lookup_pattern(
1794
+ pattern_t pattern
1795
+ , format_element_t const** elements
1796
+ );
1797
+ unsigned lookup_pattern_tss(
1798
+ pattern_t pattern
1799
+ , format_element_t const** elements
1800
+ );
1801
+ unsigned lookup_pattern_1phase(
1802
+ pattern_t pattern
1803
+ , format_element_t const** elements
1804
+ );
1805
+ unsigned lookup_pattern_2phase(
1806
+ pattern_t pattern
1807
+ , format_element_t const** elements
1808
+ );
1809
+
1810
+ private:
1811
+ mutex_type_ m_mx;
1812
+ map_type_ m_map;
1813
+ };
1814
+
1815
+ }
1816
+
1817
+
1818
+
1819
+
1820
+
1821
+
1822
+
1823
+ int ximpl_core::fastformat_impl_formatCache_init(void** ptoken)
1824
+ {
1825
+ FASTFORMAT_CONTRACT_ENFORCE_PRECONDITION_STATE_INTERNAL(NULL != ptoken, "token pointer must not be null");
1826
+
1827
+ FASTFORMAT_COVER_MARK_ENTRY();
1828
+
1829
+ try
1830
+ {
1831
+ FASTFORMAT_COVER_MARK_ENTRY();
1832
+
1833
+ format_cache* cache = new format_cache();
1834
+
1835
+ if(NULL == cache)
1836
+ {
1837
+ FASTFORMAT_COVER_MARK_ENTRY();
1838
+
1839
+ return FASTFORMAT_INIT_RC_OUT_OF_MEMORY;
1840
+ }
1841
+
1842
+ *ptoken = cache;
1843
+
1844
+ return FASTFORMAT_INIT_RC_SUCCESS;
1845
+ }
1846
+ catch(std::bad_alloc&)
1847
+ {
1848
+ FASTFORMAT_COVER_MARK_ENTRY();
1849
+
1850
+ return FASTFORMAT_INIT_RC_OUT_OF_MEMORY;
1851
+ }
1852
+ catch(std::exception&)
1853
+ {
1854
+ FASTFORMAT_COVER_MARK_ENTRY();
1855
+
1856
+ return FASTFORMAT_INIT_RC_UNSPECIFIED_EXCEPTION;
1857
+ }
1858
+ catch(...)
1859
+ {
1860
+ FASTFORMAT_COVER_MARK_ENTRY();
1861
+
1862
+ return FASTFORMAT_INIT_RC_UNSPECIFIED_ERROR;
1863
+ }
1864
+ }
1865
+
1866
+ void ximpl_core::fastformat_impl_formatCache_uninit(void* token)
1867
+ {
1868
+ FASTFORMAT_COVER_MARK_ENTRY();
1869
+
1870
+ FASTFORMAT_CONTRACT_ENFORCE_PRECONDITION_STATE_INTERNAL(NULL != token, "token must not be null");
1871
+
1872
+ delete static_cast<format_cache*>(token);
1873
+ }
1874
+
1875
+ unsigned ximpl_core::fastformat_impl_formatCache_lookupPattern(
1876
+ void* token
1877
+ , ff_char_t const* pattern
1878
+ , size_t cchPattern
1879
+ , format_element_t const** elements
1880
+ )
1881
+ {
1882
+ FASTFORMAT_CONTRACT_ENFORCE_PRECONDITION_PARAMS_INTERNAL(NULL != token, "state pointer must be null");
1883
+
1884
+ FASTFORMAT_COVER_MARK_ENTRY();
1885
+
1886
+ format_cache* cache = static_cast<format_cache*>(token);
1887
+
1888
+ if(0 == cchPattern)
1889
+ {
1890
+ FASTFORMAT_COVER_MARK_ENTRY();
1891
+
1892
+ return 0;
1893
+ }
1894
+ else
1895
+ {
1896
+ FASTFORMAT_COVER_MARK_ENTRY();
1897
+
1898
+ pattern_t p(pattern, cchPattern);
1899
+
1900
+ return cache->lookup_pattern(p, elements);
1901
+ }
1902
+ }
1903
+
1904
+
1905
+ namespace
1906
+ {
1907
+
1908
+ void* format_cache::operator new(size_t cb)
1909
+ {
1910
+ FASTFORMAT_COVER_MARK_ENTRY();
1911
+
1912
+ return operator_new(cb);
1913
+ }
1914
+
1915
+ void format_cache::operator delete(void* pv)
1916
+ {
1917
+ FASTFORMAT_COVER_MARK_ENTRY();
1918
+
1919
+ operator_delete(pv);
1920
+ }
1921
+
1922
+
1923
+ unsigned format_cache::lookup_pattern(
1924
+ pattern_t pattern
1925
+ , format_element_t const** elements
1926
+ )
1927
+ {
1928
+ FASTFORMAT_COVER_MARK_ENTRY();
1929
+
1930
+ #if defined(_FASTFORMAT_USE_TSS_CACHE)
1931
+ return this->lookup_pattern_tss(pattern, elements);
1932
+ #elif defined(_FASTFORMAT_USE_1PHASE_CACHE)
1933
+ return this->lookup_pattern_1phase(pattern, elements);
1934
+ #elif defined(_FASTFORMAT_USE_2PHASE_CACHE)
1935
+ return this->lookup_pattern_2phase(pattern, elements);
1936
+ #else
1937
+ # error Implementation not discriminated
1938
+ #endif
1939
+ }
1940
+
1941
+ unsigned format_cache::lookup_pattern_1phase(
1942
+ pattern_t pattern
1943
+ , format_element_t const** elements
1944
+ )
1945
+ {
1946
+ FASTFORMAT_COVER_MARK_ENTRY();
1947
+
1948
+ FASTFORMAT_CONTRACT_ENFORCE_PRECONDITION_PARAMS_INTERNAL(NULL != elements, "elements parameter may not be null");
1949
+
1950
+ FASTFORMAT_COVER_MARK_ENTRY();
1951
+
1952
+ stlsoft::lock_scope<mutex_type_> lock(m_mx);
1953
+ map_type_::const_iterator it = m_map.find(pattern);
1954
+
1955
+ if(it == m_map.end())
1956
+ {
1957
+ FASTFORMAT_COVER_MARK_ENTRY();
1958
+
1959
+
1960
+
1961
+
1962
+
1963
+
1964
+
1965
+
1966
+
1967
+
1968
+
1969
+
1970
+
1971
+
1972
+
1973
+
1974
+
1975
+
1976
+
1977
+
1978
+
1979
+
1980
+
1981
+
1982
+
1983
+
1984
+ format_elements_type_ formatElements(1 + pattern.size() / 2);
1985
+ unsigned numFormatElements;
1986
+ unsigned numResultElements;
1987
+
1988
+ unsigned n = fastformat_parseFormat(pattern.data(), pattern.size(), &formatElements[0], formatElements.size(), NULL, NULL);
1989
+
1990
+ numFormatElements = n & 0xffff;
1991
+ numResultElements = n >> 16;
1992
+
1993
+ STLSOFT_ASSERT(numFormatElements <= formatElements.size());
1994
+
1995
+ #if defined(_DEBUG) && \
1996
+ defined(STLSOFT_COMPILER_IS_MSVC)
1997
+
1998
+
1999
+
2000
+
2001
+
2002
+
2003
+
2004
+
2005
+ int prev = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
2006
+ _CrtSetDbgFlag(prev & ~_CRTDBG_ALLOC_MEM_DF);
2007
+
2008
+ stlsoft::scoped_handle<int> scoperCrt(prev, _CrtSetDbgFlag);
2009
+ #endif
2010
+
2011
+ record_ptr_type_ ptr(new(numFormatElements, pattern.size()) pattern_record_t(pattern, &formatElements[0], numFormatElements, numResultElements));
2012
+
2013
+ it = m_map.insert(std::make_pair(ptr->pattern(), ptr)).first;
2014
+ }
2015
+
2016
+ FASTFORMAT_COVER_MARK_ENTRY();
2017
+
2018
+ record_ptr_type_ recptr = (*it).second;
2019
+
2020
+ *elements = recptr->elements;
2021
+
2022
+ FASTFORMAT_COVER_MARK_ENTRY();
2023
+
2024
+ return (recptr->numFormatElements & 0xffff) | ((recptr->numResultElements & 0xffff) << 16);
2025
+ }
2026
+
2027
+ unsigned format_cache::lookup_pattern_2phase(
2028
+ pattern_t pattern
2029
+ , format_element_t const** elements
2030
+ )
2031
+ {
2032
+ FASTFORMAT_COVER_MARK_ENTRY();
2033
+
2034
+ FASTFORMAT_CONTRACT_ENFORCE_PRECONDITION_PARAMS_INTERNAL(NULL != elements, "elements parameter may not be null");
2035
+
2036
+ #ifndef FASTFORMAT_MT
2037
+
2038
+ return this->lookup_pattern_1phase(pattern, elements);
2039
+
2040
+ #else
2041
+
2042
+ FASTFORMAT_COVER_MARK_ENTRY();
2043
+
2044
+ {
2045
+
2046
+ FASTFORMAT_COVER_MARK_ENTRY();
2047
+
2048
+ stlsoft::lock_scope<mutex_type_> lock(m_mx);
2049
+ map_type_::const_iterator it = m_map.find(pattern);
2050
+
2051
+ if(it != m_map.end())
2052
+ {
2053
+ FASTFORMAT_COVER_MARK_ENTRY();
2054
+
2055
+ record_ptr_type_ ptr = (*it).second;
2056
+
2057
+ *elements = ptr->elements;
2058
+
2059
+ return (ptr->numFormatElements & 0xffff) | ((ptr->numResultElements & 0xffff) << 16);
2060
+ }
2061
+ }
2062
+
2063
+ FASTFORMAT_COVER_MARK_ENTRY();
2064
+
2065
+
2066
+
2067
+
2068
+ format_elements_type_ formatElements(1 + pattern.size() / 2);
2069
+ unsigned numFormatElements;
2070
+ unsigned numResultElements;
2071
+
2072
+ unsigned n = fastformat_parseFormat(pattern.data(), pattern.size(), &formatElements[0], formatElements.size(), NULL, NULL);
2073
+
2074
+ numFormatElements = n & 0xffff;
2075
+ numResultElements = n >> 16;
2076
+
2077
+ FASTFORMAT_CONTRACT_ENFORCE_POSTCONDITION_RETURN_INTERNAL(numFormatElements <= formatElements.size(), "number of pattern elements calculated cannot be greater than the number specified available");
2078
+
2079
+ #if defined(_DEBUG) && \
2080
+ defined(STLSOFT_COMPILER_IS_MSVC)
2081
+
2082
+
2083
+
2084
+
2085
+
2086
+
2087
+
2088
+
2089
+ int prev = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
2090
+ _CrtSetDbgFlag(prev & ~_CRTDBG_ALLOC_MEM_DF);
2091
+
2092
+ stlsoft::scoped_handle<int> scoperCrt(prev, _CrtSetDbgFlag);
2093
+ #endif
2094
+
2095
+ record_ptr_type_ ptr(new(numFormatElements, pattern.size()) pattern_record_t(pattern, &formatElements[0], numFormatElements, numResultElements));
2096
+
2097
+ {
2098
+
2099
+ FASTFORMAT_COVER_MARK_ENTRY();
2100
+
2101
+ stlsoft::lock_scope<mutex_type_> lock(m_mx);
2102
+
2103
+
2104
+
2105
+
2106
+ map_type_::const_iterator it = m_map.find(pattern);
2107
+
2108
+ if(it != m_map.end())
2109
+ {
2110
+ FASTFORMAT_COVER_MARK_ENTRY();
2111
+
2112
+
2113
+ }
2114
+ else
2115
+ {
2116
+ FASTFORMAT_COVER_MARK_ENTRY();
2117
+
2118
+ it = m_map.insert(std::make_pair(ptr->pattern(), ptr)).first;
2119
+ }
2120
+
2121
+ record_ptr_type_ recptr = (*it).second;
2122
+
2123
+ *elements = recptr->elements;
2124
+
2125
+ FASTFORMAT_COVER_MARK_ENTRY();
2126
+
2127
+ return (recptr->numFormatElements & 0xffff) | ((recptr->numResultElements & 0xffff) << 16);
2128
+ }
2129
+ #endif
2130
+ }
2131
+
2132
+ namespace
2133
+ {
2134
+
2135
+ const size_t offsetElement0 = STLSOFT_RAW_OFFSETOF(pattern_record_base_t, elements_[0]);
2136
+ const size_t offsetElement1 = STLSOFT_RAW_OFFSETOF(pattern_record_base_t, elements_[1]);
2137
+ const size_t sizeofElement = offsetElement1 - offsetElement0;
2138
+
2139
+ }
2140
+
2141
+ void* pattern_record_t::operator new(size_t , size_t numFormatElements, size_t cchPattern)
2142
+ {
2143
+ FASTFORMAT_COVER_MARK_ENTRY();
2144
+
2145
+ const size_t size = offsetElement0
2146
+ + ((numFormatElements < 2) ? 2 : numFormatElements) * sizeofElement
2147
+ + sizeof(ff_char_t) * (cchPattern + 1);
2148
+
2149
+ return operator_new(size);
2150
+ }
2151
+
2152
+ #if !defined(STLSOFT_COMPILER_IS_BORLAND) || \
2153
+ __BORLANDC__ > 0x0582
2154
+ void pattern_record_t::operator delete(void* pv, size_t , size_t )
2155
+ {
2156
+ FASTFORMAT_COVER_MARK_ENTRY();
2157
+
2158
+ operator_delete(pv);
2159
+ }
2160
+ #endif
2161
+
2162
+ void pattern_record_t::operator delete(void* pv)
2163
+ {
2164
+ FASTFORMAT_COVER_MARK_ENTRY();
2165
+
2166
+ operator_delete(pv);
2167
+ }
2168
+
2169
+ inline ff_char_t* pattern_record_t::get_pattern_memory_() const
2170
+ {
2171
+ const size_t elementsSize = offsetElement0
2172
+ + ((numFormatElements < 2) ? 2 : numFormatElements) * sizeofElement;
2173
+
2174
+ return reinterpret_cast<char_type*>(const_cast<void*>(stlsoft::ptr_byte_offset(this, ptrdiff_t(elementsSize))));
2175
+ }
2176
+
2177
+
2178
+ pattern_record_t::pattern_record_t(
2179
+ pattern_t pattern
2180
+ , format_element_t const* elements
2181
+ , unsigned numFormatElements
2182
+ , unsigned numResultElements
2183
+ )
2184
+ {
2185
+ FASTFORMAT_COVER_MARK_ENTRY();
2186
+
2187
+ this->numFormatElements = numFormatElements;
2188
+ this->numResultElements = numResultElements;
2189
+ this->cchPattern = pattern.size();
2190
+
2191
+ char_type* embeddedPattern = get_pattern_memory_();
2192
+
2193
+ ::memcpy(embeddedPattern, pattern.data(), sizeof(char_type) * pattern.size());
2194
+ embeddedPattern[pattern.size()] = '\0';
2195
+
2196
+ this->elements = &this->elements_[0];
2197
+
2198
+ {
2199
+ FASTFORMAT_COVER_MARK_ENTRY();
2200
+
2201
+ format_element_t* element = &this->elements_[0];
2202
+ size_t i = 0;
2203
+
2204
+ for(; i != numFormatElements; ++i, ++element, ++elements)
2205
+ {
2206
+ FASTFORMAT_COVER_MARK_ENTRY();
2207
+
2208
+ #if 1
2209
+ element->len = elements->len;
2210
+ element->ptr = embeddedPattern + (elements->ptr - pattern.data());
2211
+ element->index = elements->index;
2212
+ element->minWidth = elements->minWidth;
2213
+ element->maxWidth = elements->maxWidth;
2214
+ element->alignment = elements->alignment;
2215
+ element->fill = elements->fill;
2216
+ #else
2217
+ ::memcpy(element, elements, sizeof(*element));
2218
+ element->ptr = embeddedPattern + (elements->ptr - pattern.data());
2219
+ #endif
2220
+
2221
+ STLSOFT_ASSERT(0 == ::memcmp(element->ptr, elements->ptr, element->len));
2222
+ }
2223
+ }
2224
+ }
2225
+
2226
+ pattern_t pattern_record_t::pattern() const
2227
+ {
2228
+
2229
+
2230
+ return pattern_t(get_pattern_memory_(), cchPattern);
2231
+ }
2232
+
2233
+
2234
+ }
2235
+
2236
+
2237
+
2238
+
2239
+
2240
+ #if !defined(FASTFORMAT_NO_NAMESPACE)
2241
+ }
2242
+ #endif
2243
+
2244
+
2245
+ EOF_main
2246
+
2247
+ assert_equal expected, strip(input, 'C')
2248
+ end
2249
+
2250
+ def test_real_sample_5
2251
+
2252
+ input = <<-EOF_main
2253
+ /*****************************************************************************
2254
+ /* Start of crcmodel.c
2255
+ /*****************************************************************************
2256
+ /*
2257
+ /* Author : Ross Williams (ross@guest.adelaide.edu.au.).
2258
+ /* Date : 3 June 1993.
2259
+ /* Status : Public domain.
2260
+ /*
2261
+ /* Description : This is the implementation (.c) file for the reference
2262
+ /* implementation of the Rocksoft^tm Model CRC Algorithm. For more
2263
+ /* information on the Rocksoft^tm Model CRC Algorithm, see the document
2264
+ /* titled "A Painless Guide to CRC Error Detection Algorithms" by Ross
2265
+ /* Williams (ross@guest.adelaide.edu.au.). This document is likely to be in
2266
+ /* "ftp.adelaide.edu.au/pub/rocksoft".
2267
+ /*
2268
+ /* Note: Rocksoft is a trademark of Rocksoft Pty Ltd, Adelaide, Australia.
2269
+ /*
2270
+ /*****************************************************************************
2271
+ /*
2272
+ /* Implementation Notes
2273
+ /* --------------------
2274
+ /* To avoid inconsistencies, the specification of each function is not echoed
2275
+ /* here. See the header file for a description of these functions.
2276
+ /* This package is light on checking because I want to keep it short and
2277
+ /* simple and portable (i.e. it would be too messy to distribute my entire
2278
+ /* C culture (e.g. assertions package) with this package.
2279
+ /* */
2280
+ /******************************************************************************/
2281
+
2282
+ #include "crcmodel.h"
2283
+
2284
+ /******************************************************************************/
2285
+
2286
+ /* The following definitions make the code more readable. */
2287
+
2288
+ #define BITMASK(X) (1L << (X))
2289
+ #define MASK32 0xFFFFFFFFL
2290
+ #define LOCAL static
2291
+
2292
+ /******************************************************************************/
2293
+
2294
+ LOCAL ulong reflect (ulong v, int b)
2295
+ /* Returns the value v with the bottom b [0,32] bits reflected. */
2296
+ /* Example: reflect(0x3e23L,3) == 0x3e26 */
2297
+ EOF_main
2298
+ expected = <<-EOF_main
2299
+
2300
+
2301
+
2302
+
2303
+
2304
+
2305
+
2306
+
2307
+
2308
+
2309
+
2310
+
2311
+
2312
+
2313
+
2314
+
2315
+
2316
+
2317
+
2318
+
2319
+
2320
+
2321
+
2322
+
2323
+
2324
+
2325
+
2326
+
2327
+
2328
+ #include "crcmodel.h"
2329
+
2330
+
2331
+
2332
+
2333
+
2334
+ #define BITMASK(X) (1L << (X))
2335
+ #define MASK32 0xFFFFFFFFL
2336
+ #define LOCAL static
2337
+
2338
+
2339
+
2340
+ LOCAL ulong reflect (ulong v, int b)
2341
+
2342
+
2343
+ EOF_main
2344
+ actual = strip(input, 'C')
2345
+
2346
+ assert_equal expected, actual
2347
+ end
2348
+
2349
+ def _test_real_sample_6
2350
+
2351
+ input = <<-EOF_main
2352
+
2353
+
2354
+
2355
+
2356
+
2357
+
2358
+
2359
+ #include "catch_xmlwriter.h"
2360
+
2361
+ #include "catch_enforce.h"
2362
+
2363
+ #include <iomanip>
2364
+
2365
+ using uchar = unsigned char;
2366
+
2367
+ namespace Catch {
2368
+
2369
+ namespace {
2370
+
2371
+ size_t trailingBytes(unsigned char c) {
2372
+ if ((c & 0xE0) == 0xC0) {
2373
+ return 2;
2374
+ }
2375
+ if ((c & 0xF0) == 0xE0) {
2376
+ return 3;
2377
+ }
2378
+ if ((c & 0xF8) == 0xF0) {
2379
+ return 4;
2380
+ }
2381
+ CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
2382
+ }
2383
+
2384
+ uint32_t headerValue(unsigned char c) {
2385
+ if ((c & 0xE0) == 0xC0) {
2386
+ return c & 0x1F;
2387
+ }
2388
+ if ((c & 0xF0) == 0xE0) {
2389
+ return c & 0x0F;
2390
+ }
2391
+ if ((c & 0xF8) == 0xF0) {
2392
+ return c & 0x07;
2393
+ }
2394
+ CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
2395
+ }
2396
+
2397
+ void hexEscapeChar(std::ostream& os, unsigned char c) {
2398
+ std::ios_base::fmtflags f(os.flags());
2399
+ os << "\\x"
2400
+ << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
2401
+ << static_cast<int>(c);
2402
+ os.flags(f);
2403
+ }
2404
+
2405
+ }
2406
+
2407
+ XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat )
2408
+ : m_str( str ),
2409
+ m_forWhat( forWhat )
2410
+ {}
2411
+
2412
+ void XmlEncode::encodeTo( std::ostream& os ) const {
2413
+
2414
+
2415
+
2416
+ for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {
2417
+ uchar c = m_str[idx];
2418
+ switch (c) {
2419
+ case '<': os << "&lt;"; break;
2420
+ case '&': os << "&amp;"; break;
2421
+
2422
+ case '>':
2423
+
2424
+ if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']')
2425
+ os << "&gt;";
2426
+ else
2427
+ os << c;
2428
+ break;
2429
+
2430
+ case '\"':
2431
+ if (m_forWhat == ForAttributes)
2432
+ os << "&quot;";
2433
+ else
2434
+ os << c;
2435
+ break;
2436
+
2437
+ default:
2438
+ // Check for control characters and invalid utf-8
2439
+ EOF_main
2440
+ x1 = <<-EOF_main
2441
+ // Escape control characters in standard ascii
2442
+ // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
2443
+ if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) {
2444
+ hexEscapeChar(os, c);
2445
+ break;
2446
+ }
2447
+
2448
+ // Plain ASCII: Write it to stream
2449
+ if (c < 0x7F) {
2450
+ os << c;
2451
+ break;
2452
+ }
2453
+
2454
+ // UTF-8 territory
2455
+ // Check if the encoding is valid and if it is not, hex escape bytes.
2456
+ // Important: We do not check the exact decoded values for validity, only the encoding format
2457
+ // First check that this bytes is a valid lead byte:
2458
+ // This means that it is not encoded as 1111 1XXX
2459
+ // Or as 10XX XXXX
2460
+ if (c < 0xC0 ||
2461
+ c >= 0xF8) {
2462
+ hexEscapeChar(os, c);
2463
+ break;
2464
+ }
2465
+
2466
+ auto encBytes = trailingBytes(c);
2467
+ // Are there enough bytes left to avoid accessing out-of-bounds memory?
2468
+ if (idx + encBytes - 1 >= m_str.size()) {
2469
+ hexEscapeChar(os, c);
2470
+ break;
2471
+ }
2472
+ // The header is valid, check data
2473
+ // The next encBytes bytes must together be a valid utf-8
2474
+ // This means: bitpattern 10XX XXXX and the extracted value is sane (ish)
2475
+ bool valid = true;
2476
+ uint32_t value = headerValue(c);
2477
+ for (std::size_t n = 1; n < encBytes; ++n) {
2478
+ uchar nc = m_str[idx + n];
2479
+ valid &= ((nc & 0xC0) == 0x80);
2480
+ value = (value << 6) | (nc & 0x3F);
2481
+ }
2482
+
2483
+ if (
2484
+ // Wrong bit pattern of following bytes
2485
+ (!valid) ||
2486
+ // Overlong encodings
2487
+ (value < 0x80) ||
2488
+ (0x80 <= value && value < 0x800 && encBytes > 2) ||
2489
+ (0x800 < value && value < 0x10000 && encBytes > 3) ||
2490
+ // Encoded value out of range
2491
+ (value >= 0x110000)
2492
+ ) {
2493
+ hexEscapeChar(os, c);
2494
+ break;
2495
+ }
2496
+
2497
+ // If we got here, this is in fact a valid(ish) utf-8 sequence
2498
+ for (std::size_t n = 0; n < encBytes; ++n) {
2499
+ os << m_str[idx + n];
2500
+ }
2501
+ idx += encBytes - 1;
2502
+ break;
2503
+ }
2504
+ }
2505
+ }
2506
+
2507
+ std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) {
2508
+ xmlEncode.encodeTo( os );
2509
+ return os;
2510
+ }
2511
+
2512
+ XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer )
2513
+ : m_writer( writer )
2514
+ {}
2515
+
2516
+ XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept
2517
+ : m_writer( other.m_writer ){
2518
+ other.m_writer = nullptr;
2519
+ }
2520
+ XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept {
2521
+ if ( m_writer ) {
2522
+ m_writer->endElement();
2523
+ }
2524
+ m_writer = other.m_writer;
2525
+ other.m_writer = nullptr;
2526
+ return *this;
2527
+ }
2528
+
2529
+
2530
+ XmlWriter::ScopedElement::~ScopedElement() {
2531
+ if( m_writer )
2532
+ m_writer->endElement();
2533
+ }
2534
+
2535
+ XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, bool indent ) {
2536
+ m_writer->writeText( text, indent );
2537
+ return *this;
2538
+ }
2539
+
2540
+ XmlWriter::XmlWriter( std::ostream& os ) : m_os( os )
2541
+ {
2542
+ writeDeclaration();
2543
+ }
2544
+
2545
+ XmlWriter::~XmlWriter() {
2546
+ while( !m_tags.empty() )
2547
+ endElement();
2548
+ }
2549
+
2550
+ XmlWriter& XmlWriter::startElement( std::string const& name ) {
2551
+ ensureTagClosed();
2552
+ newlineIfNecessary();
2553
+ m_os << m_indent << '<' << name;
2554
+ m_tags.push_back( name );
2555
+ m_indent += " ";
2556
+ m_tagIsOpen = true;
2557
+ return *this;
2558
+ }
2559
+
2560
+ XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name ) {
2561
+ ScopedElement scoped( this );
2562
+ startElement( name );
2563
+ return scoped;
2564
+ }
2565
+
2566
+ XmlWriter& XmlWriter::endElement() {
2567
+ newlineIfNecessary();
2568
+ m_indent = m_indent.substr( 0, m_indent.size()-2 );
2569
+ if( m_tagIsOpen ) {
2570
+ m_os << "/>";
2571
+ m_tagIsOpen = false;
2572
+ }
2573
+ else {
2574
+ m_os << m_indent << "</" << m_tags.back() << ">";
2575
+ }
2576
+ m_os << std::endl;
2577
+ m_tags.pop_back();
2578
+ return *this;
2579
+ }
2580
+
2581
+ XmlWriter& XmlWriter::writeAttribute( std::string const& name, std::string const& attribute ) {
2582
+ if( !name.empty() && !attribute.empty() )
2583
+ m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
2584
+ return *this;
2585
+ }
2586
+
2587
+ XmlWriter& XmlWriter::writeAttribute( std::string const& name, bool attribute ) {
2588
+ m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"';
2589
+ return *this;
2590
+ }
2591
+
2592
+ XmlWriter& XmlWriter::writeText( std::string const& text, bool indent ) {
2593
+ if( !text.empty() ){
2594
+ bool tagWasOpen = m_tagIsOpen;
2595
+ ensureTagClosed();
2596
+ if( tagWasOpen && indent )
2597
+ m_os << m_indent;
2598
+ m_os << XmlEncode( text );
2599
+ m_needsNewline = true;
2600
+ }
2601
+ return *this;
2602
+ }
2603
+
2604
+ XmlWriter& XmlWriter::writeComment( std::string const& text ) {
2605
+ ensureTagClosed();
2606
+ m_os << m_indent << "<!--" << text << "-->";
2607
+ m_needsNewline = true;
2608
+ return *this;
2609
+ }
2610
+
2611
+ void XmlWriter::writeStylesheetRef( std::string const& url ) {
2612
+ m_os << "<?xml-stylesheet type=\"text/xsl\" href=\"" << url << "\"?>\n";
2613
+ }
2614
+
2615
+ XmlWriter& XmlWriter::writeBlankLine() {
2616
+ ensureTagClosed();
2617
+ m_os << '\n';
2618
+ return *this;
2619
+ }
2620
+
2621
+ void XmlWriter::ensureTagClosed() {
2622
+ if( m_tagIsOpen ) {
2623
+ m_os << ">" << std::endl;
2624
+ m_tagIsOpen = false;
2625
+ }
2626
+ }
2627
+
2628
+ void XmlWriter::writeDeclaration() {
2629
+ m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
2630
+ }
2631
+
2632
+ void XmlWriter::newlineIfNecessary() {
2633
+ if( m_needsNewline ) {
2634
+ m_os << std::endl;
2635
+ m_needsNewline = false;
2636
+ }
2637
+ }
2638
+ }
2639
+ EOF_main
2640
+
2641
+ expected = <<-EOF_main
2642
+
2643
+
2644
+
2645
+
2646
+
2647
+
2648
+
2649
+ #include "catch_xmlwriter.h"
2650
+
2651
+ #include "catch_enforce.h"
2652
+
2653
+ #include <iomanip>
2654
+
2655
+ using uchar = unsigned char;
2656
+
2657
+ namespace Catch {
2658
+
2659
+ namespace {
2660
+
2661
+ size_t trailingBytes(unsigned char c) {
2662
+ if ((c & 0xE0) == 0xC0) {
2663
+ return 2;
2664
+ }
2665
+ if ((c & 0xF0) == 0xE0) {
2666
+ return 3;
2667
+ }
2668
+ if ((c & 0xF8) == 0xF0) {
2669
+ return 4;
2670
+ }
2671
+ CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
2672
+ }
2673
+
2674
+ uint32_t headerValue(unsigned char c) {
2675
+ if ((c & 0xE0) == 0xC0) {
2676
+ return c & 0x1F;
2677
+ }
2678
+ if ((c & 0xF0) == 0xE0) {
2679
+ return c & 0x0F;
2680
+ }
2681
+ if ((c & 0xF8) == 0xF0) {
2682
+ return c & 0x07;
2683
+ }
2684
+ CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
2685
+ }
2686
+
2687
+ void hexEscapeChar(std::ostream& os, unsigned char c) {
2688
+ std::ios_base::fmtflags f(os.flags());
2689
+ os << "\\x"
2690
+ << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
2691
+ << static_cast<int>(c);
2692
+ os.flags(f);
2693
+ }
2694
+
2695
+ }
2696
+
2697
+ XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat )
2698
+ : m_str( str ),
2699
+ m_forWhat( forWhat )
2700
+ {}
2701
+
2702
+ void XmlEncode::encodeTo( std::ostream& os ) const {
2703
+
2704
+
2705
+
2706
+ for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {
2707
+ uchar c = m_str[idx];
2708
+ switch (c) {
2709
+ case '<': os << "&lt;"; break;
2710
+ case '&': os << "&amp;"; break;
2711
+
2712
+ case '>':
2713
+
2714
+ if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']')
2715
+ os << "&gt;";
2716
+ else
2717
+ os << c;
2718
+ break;
2719
+
2720
+ case '\"':
2721
+ if (m_forWhat == ForAttributes)
2722
+ os << "&quot;";
2723
+ else
2724
+ os << c;
2725
+ break;
2726
+
2727
+ default:
2728
+
2729
+ EOF_main
2730
+ x1 = <<-EOF_main
2731
+
2732
+
2733
+
2734
+ if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) {
2735
+ hexEscapeChar(os, c);
2736
+ break;
2737
+ }
2738
+
2739
+
2740
+ if (c < 0x7F) {
2741
+ os << c;
2742
+ break;
2743
+ }
2744
+
2745
+
2746
+
2747
+
2748
+
2749
+
2750
+
2751
+ if (c < 0xC0 ||
2752
+ c >= 0xF8) {
2753
+ hexEscapeChar(os, c);
2754
+ break;
2755
+ }
2756
+
2757
+ auto encBytes = trailingBytes(c);
2758
+
2759
+ if (idx + encBytes - 1 >= m_str.size()) {
2760
+ hexEscapeChar(os, c);
2761
+ break;
2762
+ }
2763
+
2764
+
2765
+
2766
+ bool valid = true;
2767
+ uint32_t value = headerValue(c);
2768
+ for (std::size_t n = 1; n < encBytes; ++n) {
2769
+ uchar nc = m_str[idx + n];
2770
+ valid &= ((nc & 0xC0) == 0x80);
2771
+ value = (value << 6) | (nc & 0x3F);
2772
+ }
2773
+
2774
+ if (
2775
+
2776
+ (!valid) ||
2777
+
2778
+ (value < 0x80) ||
2779
+ (0x80 <= value && value < 0x800 && encBytes > 2) ||
2780
+ (0x800 < value && value < 0x10000 && encBytes > 3) ||
2781
+
2782
+ (value >= 0x110000)
2783
+ ) {
2784
+ hexEscapeChar(os, c);
2785
+ break;
2786
+ }
2787
+
2788
+
2789
+ for (std::size_t n = 0; n < encBytes; ++n) {
2790
+ os << m_str[idx + n];
2791
+ }
2792
+ idx += encBytes - 1;
2793
+ break;
2794
+ }
2795
+ }
2796
+ }
2797
+
2798
+ std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) {
2799
+ xmlEncode.encodeTo( os );
2800
+ return os;
2801
+ }
2802
+
2803
+ XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer )
2804
+ : m_writer( writer )
2805
+ {}
2806
+
2807
+ XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept
2808
+ : m_writer( other.m_writer ){
2809
+ other.m_writer = nullptr;
2810
+ }
2811
+ XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept {
2812
+ if ( m_writer ) {
2813
+ m_writer->endElement();
2814
+ }
2815
+ m_writer = other.m_writer;
2816
+ other.m_writer = nullptr;
2817
+ return *this;
2818
+ }
2819
+
2820
+
2821
+ XmlWriter::ScopedElement::~ScopedElement() {
2822
+ if( m_writer )
2823
+ m_writer->endElement();
2824
+ }
2825
+
2826
+ XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, bool indent ) {
2827
+ m_writer->writeText( text, indent );
2828
+ return *this;
2829
+ }
2830
+
2831
+ XmlWriter::XmlWriter( std::ostream& os ) : m_os( os )
2832
+ {
2833
+ writeDeclaration();
2834
+ }
2835
+
2836
+ XmlWriter::~XmlWriter() {
2837
+ while( !m_tags.empty() )
2838
+ endElement();
2839
+ }
2840
+
2841
+ XmlWriter& XmlWriter::startElement( std::string const& name ) {
2842
+ ensureTagClosed();
2843
+ newlineIfNecessary();
2844
+ m_os << m_indent << '<' << name;
2845
+ m_tags.push_back( name );
2846
+ m_indent += " ";
2847
+ m_tagIsOpen = true;
2848
+ return *this;
2849
+ }
2850
+
2851
+ XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name ) {
2852
+ ScopedElement scoped( this );
2853
+ startElement( name );
2854
+ return scoped;
2855
+ }
2856
+
2857
+ XmlWriter& XmlWriter::endElement() {
2858
+ newlineIfNecessary();
2859
+ m_indent = m_indent.substr( 0, m_indent.size()-2 );
2860
+ if( m_tagIsOpen ) {
2861
+ m_os << "/>";
2862
+ m_tagIsOpen = false;
2863
+ }
2864
+ else {
2865
+ m_os << m_indent << "</" << m_tags.back() << ">";
2866
+ }
2867
+ m_os << std::endl;
2868
+ m_tags.pop_back();
2869
+ return *this;
2870
+ }
2871
+
2872
+ XmlWriter& XmlWriter::writeAttribute( std::string const& name, std::string const& attribute ) {
2873
+ if( !name.empty() && !attribute.empty() )
2874
+ m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
2875
+ return *this;
2876
+ }
2877
+
2878
+ XmlWriter& XmlWriter::writeAttribute( std::string const& name, bool attribute ) {
2879
+ m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"';
2880
+ return *this;
2881
+ }
2882
+
2883
+ XmlWriter& XmlWriter::writeText( std::string const& text, bool indent ) {
2884
+ if( !text.empty() ){
2885
+ bool tagWasOpen = m_tagIsOpen;
2886
+ ensureTagClosed();
2887
+ if( tagWasOpen && indent )
2888
+ m_os << m_indent;
2889
+ m_os << XmlEncode( text );
2890
+ m_needsNewline = true;
2891
+ }
2892
+ return *this;
2893
+ }
2894
+
2895
+ XmlWriter& XmlWriter::writeComment( std::string const& text ) {
2896
+ ensureTagClosed();
2897
+ m_os << m_indent << "<!--" << text << "-->";
2898
+ m_needsNewline = true;
2899
+ return *this;
2900
+ }
2901
+
2902
+ void XmlWriter::writeStylesheetRef( std::string const& url ) {
2903
+ m_os << "<?xml-stylesheet type=\"text/xsl\" href=\"" << url << "\"?>\n";
2904
+ }
2905
+
2906
+ XmlWriter& XmlWriter::writeBlankLine() {
2907
+ ensureTagClosed();
2908
+ m_os << '\n';
2909
+ return *this;
2910
+ }
2911
+
2912
+ void XmlWriter::ensureTagClosed() {
2913
+ if( m_tagIsOpen ) {
2914
+ m_os << ">" << std::endl;
2915
+ m_tagIsOpen = false;
2916
+ }
2917
+ }
2918
+
2919
+ void XmlWriter::writeDeclaration() {
2920
+ m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
2921
+ }
2922
+
2923
+ void XmlWriter::newlineIfNecessary() {
2924
+ if( m_needsNewline ) {
2925
+ m_os << std::endl;
2926
+ m_needsNewline = false;
2927
+ }
2928
+ }
2929
+ }
2930
+ EOF_main
2931
+
2932
+ actual = strip(input, 'C')
2933
+
2934
+ assert_equal expected, actual
2935
+ end
2936
+
2937
+ def test_real_sample_7
2938
+
2939
+ input = <<-EOF_main
2940
+ #if defined(RECLS_CPP_NO_METHOD_PROPERTY_SUPPORT)
2941
+ /* Do not define RECLS_CPP_METHOD_PROPERTY_SUPPORT */
2942
+ #else /* ? RECLS_CPP_???_METHOD_PROPERTY_SUPPORT */
2943
+ # elif defined(STLSOFT_COMPILER_IS_DMC)
2944
+ # if __DMC__ >= 0x0846
2945
+ # define RECLS_CPP_METHOD_PROPERTY_SUPPORT */
2946
+ # endif /* __DMC__ */
2947
+ # elif defined(STLSOFT_COMPILER_IS_GCC)
2948
+ /* Do not define RECLS_CPP_METHOD_PROPERTY_SUPPORT */
2949
+ # elif defined(STLSOFT_COMPILER_IS_INTEL)
2950
+ # define RECLS_CPP_METHOD_PROPERTY_SUPPORT
2951
+ # elif defined(STLSOFT_COMPILER_IS_MSVC)
2952
+ # if _MSC_VER >= 1310
2953
+ # define RECLS_CPP_METHOD_PROPERTY_SUPPORT
2954
+ # endif /* _MSC_VER */
2955
+ # elif defined(STLSOFT_COMPILER_IS_MWERKS)
2956
+ # define RECLS_CPP_METHOD_PROPERTY_SUPPORT
2957
+ # endif /* compiler */
2958
+ #endif /* RECLS_CPP_???_METHOD_PROPERTY_SUPPORT */
2959
+
2960
+ EOF_main
2961
+ expected = <<-EOF_main
2962
+ #if defined(RECLS_CPP_NO_METHOD_PROPERTY_SUPPORT)
2963
+
2964
+ #else
2965
+ # elif defined(STLSOFT_COMPILER_IS_DMC)
2966
+ # if __DMC__ >= 0x0846
2967
+ # define RECLS_CPP_METHOD_PROPERTY_SUPPORT */
2968
+ # endif
2969
+ # elif defined(STLSOFT_COMPILER_IS_GCC)
2970
+
2971
+ # elif defined(STLSOFT_COMPILER_IS_INTEL)
2972
+ # define RECLS_CPP_METHOD_PROPERTY_SUPPORT
2973
+ # elif defined(STLSOFT_COMPILER_IS_MSVC)
2974
+ # if _MSC_VER >= 1310
2975
+ # define RECLS_CPP_METHOD_PROPERTY_SUPPORT
2976
+ # endif
2977
+ # elif defined(STLSOFT_COMPILER_IS_MWERKS)
2978
+ # define RECLS_CPP_METHOD_PROPERTY_SUPPORT
2979
+ # endif
2980
+ #endif
2981
+
2982
+ EOF_main
2983
+
2984
+ actual = strip(input, 'C')
2985
+
2986
+ assert_equal expected, actual
2987
+ end
2988
+
2989
+ def test_real_sample_8
2990
+
2991
+ input = <<-EOF_main
2992
+ /*****************************************************************************
2993
+ /* Start of crcmodel.c
2994
+ /*****************************************************************************
2995
+ /*
2996
+ /* Author : Ross Williams (ross@guest.adelaide.edu.au.).
2997
+ /* Date : 3 June 1993.
2998
+ /* Status : Public domain.
2999
+ /*
3000
+ /* Description : This is the implementation (.c) file for the reference
3001
+ /* implementation of the Rocksoft^tm Model CRC Algorithm. For more
3002
+ /* information on the Rocksoft^tm Model CRC Algorithm, see the document
3003
+ /* titled "A Painless Guide to CRC Error Detection Algorithms" by Ross
3004
+ /* Williams (ross@guest.adelaide.edu.au.). This document is likely to be in
3005
+ /* "ftp.adelaide.edu.au/pub/rocksoft".
3006
+ /*
3007
+ /* Note: Rocksoft is a trademark of Rocksoft Pty Ltd, Adelaide, Australia.
3008
+ /*
3009
+ /*****************************************************************************
3010
+ /*
3011
+ /* Implementation Notes
3012
+ /* --------------------
3013
+ /* To avoid inconsistencies, the specification of each function is not echoed
3014
+ /* here. See the header file for a description of these functions.
3015
+ /* This package is light on checking because I want to keep it short and
3016
+ /* simple and portable (i.e. it would be too messy to distribute my entire
3017
+ /* C culture (e.g. assertions package) with this package.
3018
+ /* */
3019
+ /******************************************************************************/
3020
+
3021
+ #include "crcmodel.h"
3022
+
3023
+ /******************************************************************************/
3024
+
3025
+ /* The following definitions make the code more readable. */
3026
+
3027
+ #define BITMASK(X) (1L << (X))
3028
+ #define MASK32 0xFFFFFFFFL
3029
+ #define LOCAL static
3030
+
3031
+ /******************************************************************************/
3032
+
3033
+ LOCAL ulong reflect (ulong v, int b)
3034
+ /* Returns the value v with the bottom b [0,32] bits reflected. */
3035
+ /* Example: reflect(0x3e23L,3) == 0x3e26 */
3036
+ {
3037
+ int i;
3038
+ ulong t = v;
3039
+ for (i=0; i<b; i++)
3040
+ {
3041
+ if (t & 1L)
3042
+ v|= BITMASK((b-1)-i);
3043
+ else
3044
+ v&= ~BITMASK((b-1)-i);
3045
+ t>>=1;
3046
+ }
3047
+ return v;
3048
+ }
3049
+
3050
+ /******************************************************************************/
3051
+
3052
+ LOCAL ulong widmask (p_cm_t p_cm)
3053
+ /* Returns a longword whose value is (2^p_cm->cm_width)-1. */
3054
+ /* The trick is to do this portably (e.g. without doing <<32). */
3055
+ {
3056
+ return (((1L<<(p_cm->cm_width-1))-1L)<<1)|1L;
3057
+ }
3058
+
3059
+ /******************************************************************************/
3060
+
3061
+ void cm_ini (p_cm_t p_cm)
3062
+ {
3063
+ p_cm->cm_reg = p_cm->cm_init;
3064
+ }
3065
+
3066
+ /******************************************************************************/
3067
+
3068
+ void cm_nxt (p_cm_t p_cm, int ch)
3069
+ {
3070
+ int i;
3071
+ ulong uch = (ulong) ch;
3072
+ ulong topbit = BITMASK(p_cm->cm_width-1);
3073
+
3074
+ if (p_cm->cm_refin)
3075
+ uch = reflect(uch,8);
3076
+
3077
+ p_cm->cm_reg ^= (uch << (p_cm->cm_width-8));
3078
+ for (i=0; i<8; i++)
3079
+ {
3080
+ if (p_cm->cm_reg & topbit)
3081
+ p_cm->cm_reg = (p_cm->cm_reg << 1) ^ p_cm->cm_poly;
3082
+ else
3083
+ p_cm->cm_reg <<= 1;
3084
+
3085
+ p_cm->cm_reg &= widmask(p_cm);
3086
+ }
3087
+ }
3088
+
3089
+ /******************************************************************************/
3090
+
3091
+ void cm_blk (p_cm_t p_cm, p_ubyte_ blk_adr, ulong blk_len)
3092
+ {
3093
+ while (blk_len--)
3094
+ cm_nxt(p_cm,*blk_adr++);
3095
+ }
3096
+
3097
+ /******************************************************************************/
3098
+
3099
+ ulong cm_crc (p_cm_t p_cm)
3100
+ {
3101
+ if (p_cm->cm_refot)
3102
+ return p_cm->cm_xorot ^ reflect(p_cm->cm_reg,p_cm->cm_width);
3103
+ else
3104
+ return p_cm->cm_xorot ^ p_cm->cm_reg;
3105
+ }
3106
+
3107
+ /******************************************************************************/
3108
+
3109
+ ulong cm_tab (p_cm_t p_cm, int index)
3110
+ {
3111
+ int i;
3112
+ ulong r;
3113
+ ulong topbit = BITMASK(p_cm->cm_width-1);
3114
+ ulong inbyte = (ulong) index;
3115
+
3116
+ if (p_cm->cm_refin)
3117
+ inbyte = reflect(inbyte,8);
3118
+
3119
+ r = inbyte << (p_cm->cm_width-8);
3120
+ for (i=0; i<8; i++)
3121
+ {
3122
+ if (r & topbit)
3123
+ r = (r << 1) ^ p_cm->cm_poly;
3124
+ else
3125
+ r<<=1;
3126
+ }
3127
+ if (p_cm->cm_refin)
3128
+ r = reflect(r,p_cm->cm_width);
3129
+ return r & widmask(p_cm);
3130
+ }
3131
+
3132
+ /******************************************************************************/
3133
+ /* End of crcmodel.c */
3134
+ /******************************************************************************/
3135
+ EOF_main
3136
+ expected = <<-EOF_main
3137
+
3138
+
3139
+
3140
+
3141
+
3142
+
3143
+
3144
+
3145
+
3146
+
3147
+
3148
+
3149
+
3150
+
3151
+
3152
+
3153
+
3154
+
3155
+
3156
+
3157
+
3158
+
3159
+
3160
+
3161
+
3162
+
3163
+
3164
+
3165
+
3166
+ #include "crcmodel.h"
3167
+
3168
+
3169
+
3170
+
3171
+
3172
+ #define BITMASK(X) (1L << (X))
3173
+ #define MASK32 0xFFFFFFFFL
3174
+ #define LOCAL static
3175
+
3176
+
3177
+
3178
+ LOCAL ulong reflect (ulong v, int b)
3179
+
3180
+
3181
+ {
3182
+ int i;
3183
+ ulong t = v;
3184
+ for (i=0; i<b; i++)
3185
+ {
3186
+ if (t & 1L)
3187
+ v|= BITMASK((b-1)-i);
3188
+ else
3189
+ v&= ~BITMASK((b-1)-i);
3190
+ t>>=1;
3191
+ }
3192
+ return v;
3193
+ }
3194
+
3195
+
3196
+
3197
+ LOCAL ulong widmask (p_cm_t p_cm)
3198
+
3199
+
3200
+ {
3201
+ return (((1L<<(p_cm->cm_width-1))-1L)<<1)|1L;
3202
+ }
3203
+
3204
+
3205
+
3206
+ void cm_ini (p_cm_t p_cm)
3207
+ {
3208
+ p_cm->cm_reg = p_cm->cm_init;
3209
+ }
3210
+
3211
+
3212
+
3213
+ void cm_nxt (p_cm_t p_cm, int ch)
3214
+ {
3215
+ int i;
3216
+ ulong uch = (ulong) ch;
3217
+ ulong topbit = BITMASK(p_cm->cm_width-1);
3218
+
3219
+ if (p_cm->cm_refin)
3220
+ uch = reflect(uch,8);
3221
+
3222
+ p_cm->cm_reg ^= (uch << (p_cm->cm_width-8));
3223
+ for (i=0; i<8; i++)
3224
+ {
3225
+ if (p_cm->cm_reg & topbit)
3226
+ p_cm->cm_reg = (p_cm->cm_reg << 1) ^ p_cm->cm_poly;
3227
+ else
3228
+ p_cm->cm_reg <<= 1;
3229
+
3230
+ p_cm->cm_reg &= widmask(p_cm);
3231
+ }
3232
+ }
3233
+
3234
+
3235
+
3236
+ void cm_blk (p_cm_t p_cm, p_ubyte_ blk_adr, ulong blk_len)
3237
+ {
3238
+ while (blk_len--)
3239
+ cm_nxt(p_cm,*blk_adr++);
3240
+ }
3241
+
3242
+
3243
+
3244
+ ulong cm_crc (p_cm_t p_cm)
3245
+ {
3246
+ if (p_cm->cm_refot)
3247
+ return p_cm->cm_xorot ^ reflect(p_cm->cm_reg,p_cm->cm_width);
3248
+ else
3249
+ return p_cm->cm_xorot ^ p_cm->cm_reg;
3250
+ }
3251
+
3252
+
3253
+
3254
+ ulong cm_tab (p_cm_t p_cm, int index)
3255
+ {
3256
+ int i;
3257
+ ulong r;
3258
+ ulong topbit = BITMASK(p_cm->cm_width-1);
3259
+ ulong inbyte = (ulong) index;
3260
+
3261
+ if (p_cm->cm_refin)
3262
+ inbyte = reflect(inbyte,8);
3263
+
3264
+ r = inbyte << (p_cm->cm_width-8);
3265
+ for (i=0; i<8; i++)
3266
+ {
3267
+ if (r & topbit)
3268
+ r = (r << 1) ^ p_cm->cm_poly;
3269
+ else
3270
+ r<<=1;
3271
+ }
3272
+ if (p_cm->cm_refin)
3273
+ r = reflect(r,p_cm->cm_width);
3274
+ return r & widmask(p_cm);
3275
+ }
3276
+
3277
+
3278
+
3279
+
3280
+ EOF_main
3281
+
3282
+ actual = strip(input, 'C')
3283
+
3284
+ assert_equal expected, actual
3285
+ end
3286
+
3287
+ def test_real_sample_9
3288
+
3289
+ input = <<-EOF_main
3290
+ /*
3291
+ * This source file is part of the bstring string library. This code was
3292
+ * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause
3293
+ * BSD open source license or GPL v2.0. Refer to the accompanying documentation
3294
+ * for details on usage and license.
3295
+ */
3296
+
3297
+ /*
3298
+ * bstest.c
3299
+ *
3300
+ * This file is the C unit test for Bstrlib.
3301
+ */
3302
+
3303
+ #include <stdio.h>
3304
+ #include <stdlib.h>
3305
+ #include <stdarg.h>
3306
+ #include <limits.h>
3307
+ #include <ctype.h>
3308
+ #include "bstrlib.h"
3309
+ #include "bstraux.h"
3310
+
3311
+ static bstring dumpOut[16];
3312
+ static int rot = 0;
3313
+
3314
+ static char * dumpBstring (const struct tagbstring * b) {
3315
+ rot = (rot + 1) % (unsigned)16;
3316
+ if (dumpOut[rot] == NULL) {
3317
+ dumpOut[rot] = bfromcstr ("");
3318
+ if (dumpOut[rot] == NULL) return "FATAL INTERNAL ERROR";
3319
+ }
3320
+ dumpOut[rot]->slen = 0;
3321
+ if (b == NULL) {
3322
+ bcatcstr (dumpOut[rot], "NULL");
3323
+ } else {
3324
+ static char msg[256];
3325
+ sprintf (msg, "%p", (void *)b);
3326
+ bcatcstr (dumpOut[rot], msg);
3327
+
3328
+ if (b->slen < 0) {
3329
+ sprintf (msg, ":[err:slen=%d<0]", b->slen);
3330
+ bcatcstr (dumpOut[rot], msg);
3331
+ } else {
3332
+ if (b->mlen > 0 && b->mlen < b->slen) {
3333
+ sprintf (msg, ":[err:mlen=%d<slen=%d]", b->mlen, b->slen);
3334
+ bcatcstr (dumpOut[rot], msg);
3335
+ } else {
3336
+ if (b->mlen == -1) {
3337
+ bcatcstr (dumpOut[rot], "[p]");
3338
+ } else if (b->mlen < 0) {
3339
+ bcatcstr (dumpOut[rot], "[c]");
3340
+ }
3341
+ bcatcstr (dumpOut[rot], ":");
3342
+ if (b->data == NULL) {
3343
+ bcatcstr (dumpOut[rot], "[err:data=NULL]");
3344
+ } else {
3345
+ bcatcstr (dumpOut[rot], "\"");
3346
+ bcatcstr (dumpOut[rot], (const char *) b->data);
3347
+ bcatcstr (dumpOut[rot], "\"");
3348
+ }
3349
+ }
3350
+ }
3351
+ }
3352
+ return (char *) dumpOut[rot]->data;
3353
+ }
3354
+
3355
+ static int test0_0 (const char * s, const char * res) {
3356
+ bstring b0 = bfromcstr (s);
3357
+ int ret = 0;
3358
+
3359
+ if (s == NULL) {
3360
+ if (res != NULL) ret++;
3361
+ printf (".\tbfromcstr (NULL) = %s\n", dumpBstring (b0));
3362
+ return ret;
3363
+ }
3364
+
3365
+ ret += (res == NULL) || ((int) strlen (res) != b0->slen)
3366
+ || (0 != memcmp (res, b0->data, b0->slen));
3367
+ ret += b0->data[b0->slen] != '\0';
3368
+
3369
+ printf (".\tbfromcstr (\"%s\") = %s\n", s, dumpBstring (b0));
3370
+ bdestroy (b0);
3371
+ return ret;
3372
+ }
3373
+
3374
+ static int test0_1 (const char * s, int len, const char * res) {
3375
+ bstring b0 = bfromcstralloc (len, s);
3376
+ int ret = 0;
3377
+
3378
+ if (s == NULL) {
3379
+ if (res != NULL) ret++;
3380
+ printf (".\tbfromcstralloc (*, NULL) = %s\n", dumpBstring (b0));
3381
+ return ret;
3382
+ }
3383
+
3384
+ ret += (res == NULL) || ((int) strlen (res) != b0->slen)
3385
+ || (0 != memcmp (res, b0->data, b0->slen));
3386
+ ret += b0->data[b0->slen] != '\0';
3387
+ ret += len > b0->mlen;
3388
+
3389
+ printf (".\tbfromcstralloc (%d, \"%s\") = %s\n", len, s, dumpBstring (b0));
3390
+ bdestroy (b0);
3391
+ return ret;
3392
+ }
3393
+
3394
+ #define EMPTY_STRING ""
3395
+ #define SHORT_STRING "bogus"
3396
+ #define LONG_STRING "This is a bogus but reasonably long string. Just long enough to cause some mallocing."
3397
+
3398
+ static int test0 (void) {
3399
+ int ret = 0;
3400
+
3401
+ printf ("TEST: bstring bfromcstr (const char * str);\n");
3402
+
3403
+ /* tests with NULL */
3404
+ ret += test0_0 (NULL, NULL);
3405
+
3406
+ /* normal operation tests */
3407
+ ret += test0_0 (EMPTY_STRING, EMPTY_STRING);
3408
+ ret += test0_0 (SHORT_STRING, SHORT_STRING);
3409
+ ret += test0_0 (LONG_STRING, LONG_STRING);
3410
+ printf ("\t# failures: %d\n", ret);
3411
+
3412
+ printf ("TEST: bstring bfromcstralloc (int len, const char * str);\n");
3413
+
3414
+ /* tests with NULL */
3415
+ ret += test0_1 (NULL, 0, NULL);
3416
+ ret += test0_1 (NULL, 30, NULL);
3417
+
3418
+ /* normal operation tests */
3419
+ ret += test0_1 (EMPTY_STRING, 0, EMPTY_STRING);
3420
+ ret += test0_1 (EMPTY_STRING, 30, EMPTY_STRING);
3421
+ ret += test0_1 (SHORT_STRING, 0, SHORT_STRING);
3422
+ ret += test0_1 (SHORT_STRING, 30, SHORT_STRING);
3423
+ ret += test0_1 ( LONG_STRING, 0, LONG_STRING);
3424
+ ret += test0_1 ( LONG_STRING, 30, LONG_STRING);
3425
+ printf ("\t# failures: %d\n", ret);
3426
+
3427
+ return ret;
3428
+ }
3429
+
3430
+ EOF_main
3431
+ expected = <<-EOF_main
3432
+
3433
+
3434
+
3435
+
3436
+
3437
+
3438
+
3439
+
3440
+
3441
+
3442
+
3443
+
3444
+
3445
+ #include <stdio.h>
3446
+ #include <stdlib.h>
3447
+ #include <stdarg.h>
3448
+ #include <limits.h>
3449
+ #include <ctype.h>
3450
+ #include "bstrlib.h"
3451
+ #include "bstraux.h"
3452
+
3453
+ static bstring dumpOut[16];
3454
+ static int rot = 0;
3455
+
3456
+ static char * dumpBstring (const struct tagbstring * b) {
3457
+ rot = (rot + 1) % (unsigned)16;
3458
+ if (dumpOut[rot] == NULL) {
3459
+ dumpOut[rot] = bfromcstr ("");
3460
+ if (dumpOut[rot] == NULL) return "FATAL INTERNAL ERROR";
3461
+ }
3462
+ dumpOut[rot]->slen = 0;
3463
+ if (b == NULL) {
3464
+ bcatcstr (dumpOut[rot], "NULL");
3465
+ } else {
3466
+ static char msg[256];
3467
+ sprintf (msg, "%p", (void *)b);
3468
+ bcatcstr (dumpOut[rot], msg);
3469
+
3470
+ if (b->slen < 0) {
3471
+ sprintf (msg, ":[err:slen=%d<0]", b->slen);
3472
+ bcatcstr (dumpOut[rot], msg);
3473
+ } else {
3474
+ if (b->mlen > 0 && b->mlen < b->slen) {
3475
+ sprintf (msg, ":[err:mlen=%d<slen=%d]", b->mlen, b->slen);
3476
+ bcatcstr (dumpOut[rot], msg);
3477
+ } else {
3478
+ if (b->mlen == -1) {
3479
+ bcatcstr (dumpOut[rot], "[p]");
3480
+ } else if (b->mlen < 0) {
3481
+ bcatcstr (dumpOut[rot], "[c]");
3482
+ }
3483
+ bcatcstr (dumpOut[rot], ":");
3484
+ if (b->data == NULL) {
3485
+ bcatcstr (dumpOut[rot], "[err:data=NULL]");
3486
+ } else {
3487
+ bcatcstr (dumpOut[rot], "\"");
3488
+ bcatcstr (dumpOut[rot], (const char *) b->data);
3489
+ bcatcstr (dumpOut[rot], "\"");
3490
+ }
3491
+ }
3492
+ }
3493
+ }
3494
+ return (char *) dumpOut[rot]->data;
3495
+ }
3496
+
3497
+ static int test0_0 (const char * s, const char * res) {
3498
+ bstring b0 = bfromcstr (s);
3499
+ int ret = 0;
3500
+
3501
+ if (s == NULL) {
3502
+ if (res != NULL) ret++;
3503
+ printf (".\tbfromcstr (NULL) = %s\n", dumpBstring (b0));
3504
+ return ret;
3505
+ }
3506
+
3507
+ ret += (res == NULL) || ((int) strlen (res) != b0->slen)
3508
+ || (0 != memcmp (res, b0->data, b0->slen));
3509
+ ret += b0->data[b0->slen] != '\0';
3510
+
3511
+ printf (".\tbfromcstr (\"%s\") = %s\n", s, dumpBstring (b0));
3512
+ bdestroy (b0);
3513
+ return ret;
3514
+ }
3515
+
3516
+ static int test0_1 (const char * s, int len, const char * res) {
3517
+ bstring b0 = bfromcstralloc (len, s);
3518
+ int ret = 0;
3519
+
3520
+ if (s == NULL) {
3521
+ if (res != NULL) ret++;
3522
+ printf (".\tbfromcstralloc (*, NULL) = %s\n", dumpBstring (b0));
3523
+ return ret;
3524
+ }
3525
+
3526
+ ret += (res == NULL) || ((int) strlen (res) != b0->slen)
3527
+ || (0 != memcmp (res, b0->data, b0->slen));
3528
+ ret += b0->data[b0->slen] != '\0';
3529
+ ret += len > b0->mlen;
3530
+
3531
+ printf (".\tbfromcstralloc (%d, \"%s\") = %s\n", len, s, dumpBstring (b0));
3532
+ bdestroy (b0);
3533
+ return ret;
3534
+ }
3535
+
3536
+ #define EMPTY_STRING ""
3537
+ #define SHORT_STRING "bogus"
3538
+ #define LONG_STRING "This is a bogus but reasonably long string. Just long enough to cause some mallocing."
3539
+
3540
+ static int test0 (void) {
3541
+ int ret = 0;
3542
+
3543
+ printf ("TEST: bstring bfromcstr (const char * str);\n");
3544
+
3545
+
3546
+ ret += test0_0 (NULL, NULL);
3547
+
3548
+
3549
+ ret += test0_0 (EMPTY_STRING, EMPTY_STRING);
3550
+ ret += test0_0 (SHORT_STRING, SHORT_STRING);
3551
+ ret += test0_0 (LONG_STRING, LONG_STRING);
3552
+ printf ("\t# failures: %d\n", ret);
3553
+
3554
+ printf ("TEST: bstring bfromcstralloc (int len, const char * str);\n");
3555
+
3556
+
3557
+ ret += test0_1 (NULL, 0, NULL);
3558
+ ret += test0_1 (NULL, 30, NULL);
3559
+
3560
+
3561
+ ret += test0_1 (EMPTY_STRING, 0, EMPTY_STRING);
3562
+ ret += test0_1 (EMPTY_STRING, 30, EMPTY_STRING);
3563
+ ret += test0_1 (SHORT_STRING, 0, SHORT_STRING);
3564
+ ret += test0_1 (SHORT_STRING, 30, SHORT_STRING);
3565
+ ret += test0_1 ( LONG_STRING, 0, LONG_STRING);
3566
+ ret += test0_1 ( LONG_STRING, 30, LONG_STRING);
3567
+ printf ("\t# failures: %d\n", ret);
3568
+
3569
+ return ret;
3570
+ }
3571
+
3572
+ EOF_main
3573
+
3574
+ actual = strip(input, 'C')
3575
+
3576
+ assert_equal expected, actual
3577
+ end
3578
+
3579
+ def test_real_sample_10
3580
+
3581
+ input = <<-EOF_main
3582
+ // Scintilla source code edit control
3583
+ /** @file CharacterSet.h
3584
+ ** Encapsulates a set of characters. Used to test if a character is within a set.
3585
+ **/
3586
+ // Copyright 2007 by Neil Hodgson <neilh@scintilla.org>
3587
+ // The License.txt file describes the conditions under which this software may be distributed.
3588
+
3589
+ class CharacterSet {
3590
+ int size;
3591
+ bool valueAfter;
3592
+ bool *bset;
3593
+ public:
3594
+ enum setBase {
3595
+ setNone=0,
3596
+ setLower=1,
3597
+ setUpper=2,
3598
+ setDigits=4,
3599
+ setAlpha=setLower|setUpper,
3600
+ setAlphaNum=setAlpha|setDigits
3601
+ };
3602
+ CharacterSet(setBase base=setNone, const char *initialSet="", int size_=0x80, bool valueAfter_=false) {
3603
+ size = size_;
3604
+ valueAfter = valueAfter_;
3605
+ bset = new bool[size];
3606
+ for (int i=0; i < size; i++) {
3607
+ bset[i] = false;
3608
+ }
3609
+ AddString(initialSet);
3610
+ if (base & setLower)
3611
+ AddString("abcdefghijklmnopqrstuvwxyz");
3612
+ if (base & setUpper)
3613
+ AddString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
3614
+ if (base & setDigits)
3615
+ AddString("0123456789");
3616
+ }
3617
+ ~CharacterSet() {
3618
+ delete []bset;
3619
+ bset = 0;
3620
+ size = 0;
3621
+ }
3622
+ void Add(int val) {
3623
+ PLATFORM_ASSERT(val >= 0);
3624
+ PLATFORM_ASSERT(val < size);
3625
+ bset[val] = true;
3626
+ }
3627
+ void AddString(const char *CharacterSet) {
3628
+ for (const char *cp=CharacterSet; *cp; cp++) {
3629
+ int val = static_cast<unsigned char>(*cp);
3630
+ PLATFORM_ASSERT(val >= 0);
3631
+ PLATFORM_ASSERT(val < size);
3632
+ bset[val] = true;
3633
+ }
3634
+ }
3635
+ bool Contains(int val) const {
3636
+ PLATFORM_ASSERT(val >= 0);
3637
+ return (val < size) ? bset[val] : valueAfter;
3638
+ }
3639
+ };
3640
+ EOF_main
3641
+
3642
+ expected = <<-EOF_main
3643
+
3644
+
3645
+
3646
+
3647
+
3648
+
3649
+
3650
+ class CharacterSet {
3651
+ int size;
3652
+ bool valueAfter;
3653
+ bool *bset;
3654
+ public:
3655
+ enum setBase {
3656
+ setNone=0,
3657
+ setLower=1,
3658
+ setUpper=2,
3659
+ setDigits=4,
3660
+ setAlpha=setLower|setUpper,
3661
+ setAlphaNum=setAlpha|setDigits
3662
+ };
3663
+ CharacterSet(setBase base=setNone, const char *initialSet="", int size_=0x80, bool valueAfter_=false) {
3664
+ size = size_;
3665
+ valueAfter = valueAfter_;
3666
+ bset = new bool[size];
3667
+ for (int i=0; i < size; i++) {
3668
+ bset[i] = false;
3669
+ }
3670
+ AddString(initialSet);
3671
+ if (base & setLower)
3672
+ AddString("abcdefghijklmnopqrstuvwxyz");
3673
+ if (base & setUpper)
3674
+ AddString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
3675
+ if (base & setDigits)
3676
+ AddString("0123456789");
3677
+ }
3678
+ ~CharacterSet() {
3679
+ delete []bset;
3680
+ bset = 0;
3681
+ size = 0;
3682
+ }
3683
+ void Add(int val) {
3684
+ PLATFORM_ASSERT(val >= 0);
3685
+ PLATFORM_ASSERT(val < size);
3686
+ bset[val] = true;
3687
+ }
3688
+ void AddString(const char *CharacterSet) {
3689
+ for (const char *cp=CharacterSet; *cp; cp++) {
3690
+ int val = static_cast<unsigned char>(*cp);
3691
+ PLATFORM_ASSERT(val >= 0);
3692
+ PLATFORM_ASSERT(val < size);
3693
+ bset[val] = true;
3694
+ }
3695
+ }
3696
+ bool Contains(int val) const {
3697
+ PLATFORM_ASSERT(val >= 0);
3698
+ return (val < size) ? bset[val] : valueAfter;
3699
+ }
3700
+ };
3701
+ EOF_main
3702
+
3703
+ actual = strip(input, 'C')
3704
+
3705
+ assert_equal expected, actual
3706
+ end
3707
+ end
3708
+
3709
+ # ############################## end of file ############################# #
3710
+
3711
+