ledger-core
LedgerApiParser.hpp
1 /*
2  *
3  * LedgerApiParser
4  * ledger-core
5  *
6  * Created by Pierre Pollastri on 14/04/2017.
7  *
8  * The MIT License (MIT)
9  *
10  * Copyright (c) 2016 Ledger
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a copy
13  * of this software and associated documentation files (the "Software"), to deal
14  * in the Software without restriction, including without limitation the rights
15  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16  * copies of the Software, and to permit persons to whom the Software is
17  * furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included in all
20  * copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28  * SOFTWARE.
29  *
30  */
31 #ifndef LEDGER_CORE_LEDGERAPIPARSER_HPP
32 #define LEDGER_CORE_LEDGERAPIPARSER_HPP
33 
34 #include <cstdint>
35 #include <rapidjson/reader.h>
36 #include <net/HttpClient.hpp>
37 #include <collections/collections.hpp>
38 
39 namespace ledger {
40  namespace core {
41  template <typename ResultType, typename Parser>
43  public:
44  LedgerApiParser() : _parser(_lastKey) {
45  _statusCode = 0;
46  _depth = 0;
47  _result = std::make_shared<ResultType>();
48  _parser.init(_result.get());
49  }
50 
52  _statusCode(cpy._statusCode),
53  _statusText(cpy._statusText),
54  _depth(cpy._depth),
55  _result(cpy._result),
56  _lastKey(cpy._lastKey),
57  _parser(_lastKey) {
58  _parser.init(_result.get());
59  }
60 
61  bool Null() {
62  return delegate([&] () {
63  _parser.Null();
64  });
65  }
66 
67  bool Bool(bool b) {
68  return delegate([&] () {
69  _parser.Bool(b);
70  });
71  }
72 
73  bool Int(int i) {
74  return delegate([&] () {
75  _parser.Int(i);
76  });
77  }
78 
79  bool Uint(unsigned i) {
80  return delegate([&] () {
81  _parser.Uint(i);
82  });
83  }
84 
85  bool Int64(int64_t i) {
86  return delegate([&] () {
87  _parser.Int64(i);
88  });
89  }
90 
91  bool Uint64(uint64_t i) {
92  return delegate([&] () {
93  _parser.Uint64(i);
94  });
95  }
96 
97  bool Double(double d) {
98  return delegate([&] () {
99  _parser.Double(d);
100  });
101  }
102 
103  bool RawNumber(const rapidjson::Reader::Ch* str, rapidjson::SizeType length, bool copy) {
104  return delegate([&] () {
105  _parser.RawNumber(str, length, copy);
106  });
107  }
108 
109  bool String(const rapidjson::Reader::Ch* str, rapidjson::SizeType length, bool copy) {
110  if (_depth == 1 && isFailure() && _lastKey == "error") {
111  _error = std::string(str, length);
112  }
113  return delegate([&] () {
114  _parser.String(str, length, copy);
115  });
116  }
117 
118  bool StartObject() {
119  _depth += 1;
120  return delegate([&] () {
121  _parser.StartObject();
122  });
123  }
124 
125  bool Key(const rapidjson::Reader::Ch* str, rapidjson::SizeType length, bool copy) {
126  _lastKey = std::string(str, length);
127  delegate([&] () {
128  _parser.Key(str, length, copy);
129  });
130  return continueParsing();
131  }
132 
133  bool EndObject(rapidjson::SizeType memberCount) {
134  _depth -= 1;
135  delegate([&] () {
136  _parser.EndObject(memberCount);
137  });
138  return continueParsing();
139  }
140 
141  bool StartArray() {
142  _depth += 1;
143  delegate([&] () {
144  _parser.StartArray();
145  });
146  return continueParsing();
147  }
148 
149  bool EndArray(rapidjson::SizeType elementCount) {
150  _depth -= 1;
151  delegate([&] () {
152  _parser.EndArray(elementCount);
153  });
154  return continueParsing();
155  }
156 
158  if (isFailure()) {
159  auto ex = make_exception(api::ErrorCode::API_ERROR, "{} - {}: {}", _statusCode, _statusText, _error);
161  } else {
163  }
164  };
165 
166  void attach(const std::shared_ptr<api::HttpUrlConnection>& connection) {
167  _statusCode = (uint32_t) connection->getStatusCode();
168  _statusText = connection->getStatusText();
169  }
170 
171  void attach(const std::string& statusText, uint32_t statusCode) {
172  _statusCode = statusCode;
173  _statusText = statusText;
174  }
175 
176  inline bool isFailure() const {
177  return _statusCode < 200 || _statusCode >= 400;
178  }
179 
180  inline bool continueParsing() const {
181  return _exception.isEmpty();
182  }
183 
184  private:
185  bool delegate(std::function<void ()>&& fn) {
186  if (!isFailure()) {
187  _exception = Try<Unit>::from([&] () {
188  fn();
189  return unit;
190  }).exception();
191  }
192  return continueParsing();
193  }
194  private:
195  Parser _parser;
196  std::shared_ptr<ResultType> _result;
197  uint32_t _depth;
198  std::string _statusText;
199  uint32_t _statusCode;
200  std::string _error;
201  std::string _lastKey;
202  Option<Exception> _exception;
203  };
204  }
205 }
206 
207 #endif //LEDGER_CORE_LEDGERAPIPARSER_HPP
Definition: Try.hpp:49
Definition: Either.hpp:43
Definition: Option.hpp:49
Definition: Account.cpp:8
Definition: LedgerApiParser.hpp:42