1 /******************************************************************************
2  *
3  * Project:  CPL - Common Portability Library
4  * Purpose:  JSon streaming parser
5  * Author:   Even Rouault, even.rouault at spatialys.com
6  *
7  ******************************************************************************
8  * Copyright (c) 2017, Even Rouault <even.rouault at spatialys.com>
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a
11  * copy of this software and associated documentation files (the "Software"),
12  * to deal in the Software without restriction, including without limitation
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  * and/or sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included
18  * in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26  * DEALINGS IN THE SOFTWARE.
27  ****************************************************************************/
28 
29 #ifndef CPL_JSON_STREAMIN_PARSER_H
30 #define CPL_JSON_STREAMIN_PARSER_H
31 
32 /*! @cond Doxygen_Suppress */
33 
34 #if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS)
35 
36 #include <vector>
37 #include <string>
38 #include "cpl_port.h"
39 
40 class CPL_DLL CPLJSonStreamingParser
41 {
42         CPL_DISALLOW_COPY_ASSIGN(CPLJSonStreamingParser)
43 
44         enum State
45         {
46             INIT,
47             OBJECT,
48             ARRAY,
49             STRING,
50             NUMBER,
51             STATE_TRUE,
52             STATE_FALSE,
53             STATE_NULL
54         };
55 
56         bool m_bExceptionOccurred = false;
57         bool m_bElementFound = false;
58         int m_nLastChar = 0;
59         int m_nLineCounter = 1;
60         int m_nCharCounter = 1;
61         std::vector<State> m_aState{};
62         std::string m_osToken{};
63         enum class ArrayState
64         {
65             INIT,
66             AFTER_COMMA,
67             AFTER_VALUE
68         };
69         std::vector<ArrayState> m_abArrayState{};
70         bool m_bInStringEscape = false;
71         bool m_bInUnicode = false;
72         std::string m_osUnicodeHex{};
73         size_t m_nMaxDepth = 1024;
74         size_t m_nMaxStringSize = 10000000;
75 
76         enum MemberState
77         {
78             WAITING_KEY,
79             IN_KEY,
80             KEY_FINISHED,
81             IN_VALUE
82         };
83         std::vector<MemberState> m_aeObjectState{};
84 
currentState()85         enum State currentState() { return m_aState.back(); }
86         void SkipSpace(const char*& pStr, size_t& nLength);
87         void AdvanceChar(const char*& pStr, size_t& nLength);
88         bool EmitException(const char* pszMessage);
89         bool EmitUnexpectedChar(char ch, const char* pszExpecting = nullptr);
90         bool StartNewToken(const char*& pStr, size_t& nLength);
91         bool CheckAndEmitTrueFalseOrNull(char ch);
92         bool CheckStackEmpty();
93         void DecodeUnicode();
94 
95     public:
96         CPLJSonStreamingParser();
97         virtual ~CPLJSonStreamingParser();
98 
99         void SetMaxDepth(size_t nVal);
100         void SetMaxStringSize(size_t nVal);
ExceptionOccurred()101         bool ExceptionOccurred() const { return m_bExceptionOccurred; }
102 
103         static std::string GetSerializedString(const char* pszStr);
104 
105         virtual void Reset();
106         virtual bool Parse(const char* pStr, size_t nLength, bool bFinished);
107 
String(const char *,size_t)108         virtual void String(const char* /*pszValue*/, size_t /*nLength*/) {}
Number(const char *,size_t)109         virtual void Number(const char* /*pszValue*/, size_t /*nLength*/) {}
Boolean(bool)110         virtual void Boolean(bool /*b*/) {}
Null()111         virtual void Null() {}
112 
StartObject()113         virtual void StartObject() {}
EndObject()114         virtual void EndObject() {}
StartObjectMember(const char *,size_t)115         virtual void StartObjectMember(const char* /*pszKey*/, size_t /*nLength*/) {}
116 
StartArray()117         virtual void StartArray() {}
EndArray()118         virtual void EndArray() {}
StartArrayMember()119         virtual void StartArrayMember() {}
120 
Exception(const char *)121         virtual void Exception(const char* /*pszMessage*/) {}
122 };
123 
124 #endif // __cplusplus
125 
126 /*! @endcond */
127 
128 #endif // CPL_JSON_STREAMIN_PARSER_H
129