1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Copyright (c) 2015 Baidu.com, Inc. All Rights Reserved
// File: optimized_writer.h
// Author: Lin Jiang (jianglin05@baidu.com)
// Date: 2015/7/21 16:44:42
#ifndef RAPIDJSON_OPTIMIZED_WRITER_H
#define RAPIDJSON_OPTIMIZED_WRITER_H
#include "writer.h"
RAPIDJSON_NAMESPACE_BEGIN
//! Optimized writer
/*! This class mainly inherit writer class in rapidjson
* It optimised WriteString function in writer class,
* which not compare and push character one by one and
* in applications when SourceEncoding and TargetEncoding is the same method,
* transcode could be omit.
* When TargetEncoding support unicode, and SourceEncoding and TargetEncoding
* is the same method, WriteString could improve 65% effciency compare with
* writer class in rapidjson.
* */
template<typename OutputStream, typename SourceEncoding = UTF8<>,
typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator>
class OptimizedWriter :
public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> {
public:
typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> Base;
typedef typename SourceEncoding::Ch Ch;
explicit
OptimizedWriter(OutputStream& os, StackAllocator* stackAllocator = 0,
size_t levelDepth = Base::kDefaultLevelDepth) :
Base(os, stackAllocator, levelDepth) {}
explicit
OptimizedWriter(StackAllocator* allocator = 0,
size_t levelDepth = Base::kDefaultLevelDepth) :
Base(allocator, levelDepth) {}
bool String(const Ch* str, SizeType length, bool copy = false) {
(void)copy;
Base::Prefix(kStringType);
return WriteString(str, length);
}
protected:
bool WriteString(const Ch* str, SizeType length) {
//if TargetEncoding support Unicode
//and SourceEncoding and TargetEncoding are the same type
//just use memcpy to improve efficiency
if (TargetEncoding::supportUnicode && is_same<SourceEncoding, TargetEncoding>::value) {
static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
static const char escape[256] = {
#define ESCAPE_ZERO_16 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
//0 1 2 3 4 5 6 7 8 9 A B C D E F
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
ESCAPE_ZERO_16, ESCAPE_ZERO_16, // 30~4F
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\\', 0, 0, 0, // 50
ESCAPE_ZERO_16, ESCAPE_ZERO_16, ESCAPE_ZERO_16, ESCAPE_ZERO_16, ESCAPE_ZERO_16,
ESCAPE_ZERO_16, ESCAPE_ZERO_16, ESCAPE_ZERO_16, ESCAPE_ZERO_16, ESCAPE_ZERO_16 // 60~FF
#undef ESCAPE_ZERO_16
};
Base::os_->Put('\"');
size_t index = 0;
size_t pos = 0;
while (pos < length) {
Ch c = str[pos];
if ((sizeof(Ch) == 1 || (unsigned)c < 256) && escape[(unsigned char)c]) {
Base::os_->Puts(str + index, pos - index);
index = pos + 1;
Base::os_->Put('\\');
Base::os_->Put(escape[(unsigned char)str[pos]]);
if (escape[(unsigned char)str[pos]] == 'u') {
Base::os_->Put('0');
Base::os_->Put('0');
Base::os_->Put(hexDigits[(unsigned char)str[pos] >> 4]);
Base::os_->Put(hexDigits[(unsigned char)str[pos] & 0xF]);
}
}
pos++;
}
if (index < length) {
Base::os_->Puts(str + index, length - index);
}
Base::os_->Put('\"');
return true;
} else {
return Base::WriteString(str, length);
}
}
private:
// Prohibit copy constructor & assignment operator.
OptimizedWriter(const OptimizedWriter&);
OptimizedWriter& operator=(const OptimizedWriter&);
};
RAPIDJSON_NAMESPACE_END
#endif // RAPIDJSON_OPTIMIZED_WRITER_H