optimized_writer.h 4.49 KB
Newer Older
gejun's avatar
gejun committed
1
// Copyright (c) 2015 Baidu, Inc.
gejun's avatar
gejun committed
2 3 4 5 6 7 8 9
// 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"

10
BUTIL_RAPIDJSON_NAMESPACE_BEGIN
gejun's avatar
gejun committed
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

//! 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&);
};
99
BUTIL_RAPIDJSON_NAMESPACE_END
gejun's avatar
gejun committed
100 101

#endif // RAPIDJSON_OPTIMIZED_WRITER_H