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.
- checksums.yaml +7 -0
- data/LICENSE +31 -0
- data/README.md +46 -0
- data/lib/comment_strip.rb +46 -0
- data/lib/comment_strip/comment_strip.rb +52 -0
- data/lib/comment_strip/strip.rb +253 -0
- data/lib/comment_strip/version.rb +62 -0
- data/test/unit/tc_strip.rb +3711 -0
- data/test/unit/tc_version.rb +41 -0
- data/test/unit/ts_all.rb +12 -0
- metadata +108 -0
@@ -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 << "<"; break;
|
2420
|
+
case '&': os << "&"; break;
|
2421
|
+
|
2422
|
+
case '>':
|
2423
|
+
|
2424
|
+
if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']')
|
2425
|
+
os << ">";
|
2426
|
+
else
|
2427
|
+
os << c;
|
2428
|
+
break;
|
2429
|
+
|
2430
|
+
case '\"':
|
2431
|
+
if (m_forWhat == ForAttributes)
|
2432
|
+
os << """;
|
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 << "<"; break;
|
2710
|
+
case '&': os << "&"; break;
|
2711
|
+
|
2712
|
+
case '>':
|
2713
|
+
|
2714
|
+
if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']')
|
2715
|
+
os << ">";
|
2716
|
+
else
|
2717
|
+
os << c;
|
2718
|
+
break;
|
2719
|
+
|
2720
|
+
case '\"':
|
2721
|
+
if (m_forWhat == ForAttributes)
|
2722
|
+
os << """;
|
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
|
+
|