comment_strip-ruby 0.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+