BDE 4.14.0 Production release
Loading...
Searching...
No Matches
baljsn_parserutil.h
Go to the documentation of this file.
1/// @file baljsn_parserutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// baljsn_parserutil.h -*-C++-*-
8#ifndef INCLUDED_BALJSN_PARSERUTIL
9#define INCLUDED_BALJSN_PARSERUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup baljsn_parserutil baljsn_parserutil
15/// @brief Provide a utility for decoding JSON data into simple types.
16/// @addtogroup bal
17/// @{
18/// @addtogroup baljsn
19/// @{
20/// @addtogroup baljsn_parserutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#baljsn_parserutil-purpose"> Purpose</a>
25/// * <a href="#baljsn_parserutil-classes"> Classes </a>
26/// * <a href="#baljsn_parserutil-description"> Description </a>
27/// * <a href="#baljsn_parserutil-usage"> Usage </a>
28/// * <a href="#baljsn_parserutil-example-1-decoding-into-a-simple-struct-from-json-data"> Example 1: Decoding into a Simple struct from JSON data </a>
29///
30/// # Purpose {#baljsn_parserutil-purpose}
31/// Provide a utility for decoding JSON data into simple types.
32///
33/// # Classes {#baljsn_parserutil-classes}
34///
35/// - baljsn::ParserUtil: utility for parsing JSON data into simple types
36///
37/// @see baljsn_decoder, baljsn_printutil
38///
39/// # Description {#baljsn_parserutil-description}
40/// This component provides a `struct` of utility functions,
41/// `baljsn::ParserUtil`, for decoding data in the JSON format into a `bdeat`
42/// Simple type. The primary method is `getValue`, which decodes into a
43/// specified object and is overloaded for all `bdeat` Simple types.
44///
45/// Refer to the details of the JSON encoding format supported by this utility
46/// in the package documentation file (doc/baljsn.txt).
47///
48/// ## Usage {#baljsn_parserutil-usage}
49///
50///
51/// This section illustrates intended use of this component.
52///
53/// ## Example 1: Decoding into a Simple struct from JSON data {#baljsn_parserutil-example-1-decoding-into-a-simple-struct-from-json-data}
54///
55///
56/// Suppose we want to de-serialize some JSON data into an object.
57///
58/// First, we define a struct, `Employee`, to contain the data:
59/// @code
60/// struct Employee {
61/// bsl::string d_name;
62/// bdlt::Date d_date;
63/// int d_age;
64/// };
65/// @endcode
66/// Then, we create an `Employee` object:
67/// @code
68/// Employee employee;
69/// @endcode
70/// Next, we specify the string values in JSON format used to represent the
71/// object data. Note that the birth date is specified in the ISO 8601 format:
72/// @code
73/// const char *name = "\"John Smith\"";
74/// const char *date = "\"1985-06-24\"";
75/// const char *age = "21";
76///
77/// const bsl::string_view nameRef(name);
78/// const bsl::string_view dateRef(date);
79/// const bsl::string_view ageRef(age);
80/// @endcode
81/// Now, we use the created string refs to populate the employee object:
82/// @code
83/// assert(0 == baljsn::ParserUtil::getValue(&employee.d_name, nameRef));
84/// assert(0 == baljsn::ParserUtil::getValue(&employee.d_date, dateRef));
85/// assert(0 == baljsn::ParserUtil::getValue(&employee.d_age, ageRef));
86/// @endcode
87/// Finally, we will verify that the values are as expected:
88/// @code
89/// assert("John Smith" == employee.d_name);
90/// assert(bdlt::Date(1985, 06, 24) == employee.d_date);
91/// assert(21 == employee.d_age);
92/// @endcode
93/// @}
94/** @} */
95/** @} */
96
97/** @addtogroup bal
98 * @{
99 */
100/** @addtogroup baljsn
101 * @{
102 */
103/** @addtogroup baljsn_parserutil
104 * @{
105 */
106
107#include <balscm_version.h>
108
109#include <bdljsn_stringutil.h>
110
111#include <bdlb_variant.h>
112
113#include <bdldfp_decimal.h>
114
115#include <bdlt_iso8601util.h>
116
117#include <bsls_assert.h>
118#include <bsls_types.h>
119
120#include <bsl_limits.h>
121#include <bsl_cstring.h>
122#include <bsl_string.h>
123#include <bsl_string_view.h>
124#include <bsl_vector.h>
125
126#include <string>
127#include <vector>
128
129
130namespace baljsn {
131
132 // =================
133 // struct ParserUtil
134 // =================
135
136///This class provides utility functions for decoding data in the JSON
137///format into a `bdeat` Simple type. The primary method is `getValue`,
138///which decodes into a specified object and is overloaded for all `bdeat`
139///Simple types.
141
142 private:
143 // PRIVATE CLASS METHODS
144
145 /// Load into the specified `value` the date or time value represented
146 /// as a string in the ISO 8601 format in the specified `data`. Return
147 /// 0 on success and a non-zero value otherwise. Note that `TYPE` is
148 /// expected to be one of `bdlt::Date`, `bdlt::Time`, bdlt::Datetime',
149 /// `bdlt::DateTz`, `bdlt::TimeTz`, `bdlt::DatetimeTz`,
150 /// `bdlb::Variant2<bdlt::Date, bdlt::DateTz>`,
151 /// `bdlb::Variant2<bdlt::Time, bdlt::TimeTz>` or
152 /// `bdlb::Variant2<bdlt::Datetime, bdlt::DatetimeTz>`.
153 template <class TYPE>
154 static int getDateAndTimeValue(TYPE *value,
155 const bsl::string_view& data);
156
157 /// Load into the specified `value` the integer value in the specified
158 /// `data`. Note that this operation follows the more permissive syntax
159 /// specified for `bdlb::NumericParseUtil`, allowing things like leading
160 /// `0` digits which the JSON spec does not permit. Return 0 on success
161 /// and a non-zero value otherwise. The behavior is undefined unless
162 /// `true == is_integral<TYPE>::value && is_signed<TYPE>::value`, e.g,
163 /// `TYPE` is expected to be a *signed* integral type. Note that
164 /// although `data` is passed by value instead of `const`-reference,
165 /// there is no effect on usage.
166 template <class TYPE>
167 static int getIntegralValue(TYPE *value, bsl::string_view data);
168
169 /// Load into the specified `value` the unsigned integer value in the
170 /// specified `data`. Note that this operation follows the more
171 /// permissive syntax specified for `bdlb::NumericParseUtil`, allowing
172 /// things like leading `0` digits which the JSON spec does not permit.
173 /// Return 0 on success and a non-zero value otherwise. The behavior is
174 /// undefined unless
175 /// `true == is_integral<TYPE>::value && !is_signed<TYPE>::value`, e.g,
176 /// `TYPE` is expected to be an *unsigned* integral type.
177 template <class TYPE>
178 static int getUnsignedIntegralValue(TYPE *value,
179 const bsl::string_view& data);
180
181 /// Load into the specified `value` the value in the specified `data`.
182 /// Note that this operation follows the more permissive syntax
183 /// specified for `bdlb::NumericParseUtil`, allowing things like leading
184 /// `0` digits which the JSON spec does not permit. Return 0 on success
185 /// and a non-zero value otherwise.
186 static int getUint64(bsls::Types::Uint64 *value,
187 const bsl::string_view& data);
188
189 public:
190 // TYPES
191
192 /// `DateOrDateTz` is a convenient alias for
193 /// `bdlb::Variant2<Date, DateTz>`.
195
196 /// `TimeOrTimeTz` is a convenient alias for
197 /// `bdlb::Variant2<Time, TimeTz>`.
199
200 /// `DatetimeOrDatetimeTz` is a convenient alias for
201 /// `bdlb::Variant2<Datetime, DatetimeTz>`.
204
205 // CLASS METHODS
206
207 /// Load into the specified `value` the string value in the specified
208 /// `data`. The string must be begin and end in `"` characters which
209 /// are not part of the resulting `value`. Return 0 on success and a
210 /// non-zero value otherwise.
211 static int getQuotedString(bsl::string *value,
212 const bsl::string_view& data);
213
214 /// Load into the specified `value` the string value in the specified
215 /// `data`. Return 0 on success and a non-zero value otherwise.
217 const bsl::string_view& data);
218
219 static int getValue(bool *value,
220 const bsl::string_view& data);
221 static int getValue(char *value,
222 const bsl::string_view& data);
223 static int getValue(unsigned char *value,
224 const bsl::string_view& data);
225 static int getValue(signed char *value,
226 const bsl::string_view& data);
227 static int getValue(short *value,
228 const bsl::string_view& data);
229 static int getValue(unsigned short *value,
230 const bsl::string_view& data);
231 static int getValue(int *value,
232 const bsl::string_view& data);
233 static int getValue(unsigned int *value,
234 const bsl::string_view& data);
235 static int getValue(bsls::Types::Int64 *value,
236 const bsl::string_view& data);
237 static int getValue(bsls::Types::Uint64 *value,
238 const bsl::string_view& data);
239 static int getValue(float *value,
240 const bsl::string_view& data);
241 static int getValue(double *value,
242 const bsl::string_view& data);
243 static int getValue(bdldfp::Decimal64 *value,
244 const bsl::string_view& data);
245 static int getValue(bdlt::Date *value,
246 const bsl::string_view& data);
247 static int getValue(bdlt::Datetime *value,
248 const bsl::string_view& data);
249 static int getValue(bdlt::DatetimeTz *value,
250 const bsl::string_view& data);
251 static int getValue(bdlt::DateTz *value,
252 const bsl::string_view& data);
253 static int getValue(bdlt::Time *value,
254 const bsl::string_view& data);
255 static int getValue(bdlt::TimeTz *value,
256 const bsl::string_view& data);
257 static int getValue(DateOrDateTz *value,
258 const bsl::string_view& data);
259 static int getValue(TimeOrTimeTz *value,
260 const bsl::string_view& data);
262 const bsl::string_view& data);
263 /// Load into the specified `value` the characters read from the
264 /// specified `data`. Return 0 on success or a non-zero value on
265 /// failure.
266 static int getValue(bsl::vector<char> *value,
267 const bsl::string_view& data);
268
269 /// Load into the specified `value` the string value in the specified
270 /// `data`. The string must be begin and end in `"` characters which
271 /// are not part of the resulting `value`. Return 0 on success and a
272 /// non-zero value otherwise.
273 static int getValue(bsl::string *value,
274 const bsl::string_view& data);
275
276 /// If the specified `*str` is at least two characters long and begins
277 /// and ends with quotation marks ("), then remove the first and last
278 /// characters; otherwise, do not modify `*str`. Return `true` if
279 /// `*str` was modified.
280 static bool stripQuotes(bsl::string_view *str);
281};
282
283// ============================================================================
284// INLINE DEFINITIONS
285// ============================================================================
286
287 // -----------------
288 // struct ParserUtil
289 // -----------------
290
291// CLASS METHODS
292inline
301
302template <class TYPE>
303int ParserUtil::getUnsignedIntegralValue(TYPE *value,
304 const bsl::string_view& data)
305{
306 BSLS_ASSERT(value);
307
308 if (0 == data.length()) {
309 return -1; // RETURN
310 }
311
313
314 int rc = getUint64(&tmp, data);
315 if (rc) {
316 return -1; // RETURN
317 }
318
319 if (tmp >
320 static_cast<bsls::Types::Uint64>((bsl::numeric_limits<TYPE>::max)())) {
321 return -1; // RETURN
322 }
323
324 *value = static_cast<TYPE>(tmp);
325 return 0;
326}
327
328template <class TYPE>
329int ParserUtil::getIntegralValue(TYPE *value, bsl::string_view data)
330{
331 // Note that we take 'data' by value because we may want to modify it.
332
333 if (0 == data.length()) {
334 return -1; // RETURN
335 }
336
337 bool isNegative;
338 if ('-' == data[0]) {
339 isNegative = true;
340 data.remove_prefix(1);
341 }
342 else {
343 isNegative = false;
344 }
345
347
348 const int rc = getUint64(&tmp, data);
349 if (rc) {
350 return -1; // RETURN
351 }
352
353 bsls::Types::Uint64 maxValue =
354 static_cast<bsls::Types::Uint64>((bsl::numeric_limits<TYPE>::max)());
355
356 if (isNegative && tmp <= maxValue + 1) {
357 *value = static_cast<TYPE>(tmp * -1);
358 }
359 else if (tmp <= maxValue) {
360 *value = static_cast<TYPE>(tmp);
361 }
362 else {
363 return -1; // RETURN
364 }
365
366 return 0;
367}
368
369template <class TYPE>
370int ParserUtil::getDateAndTimeValue(TYPE *value,
371 const bsl::string_view& data)
372{
373 enum { k_STRING_LENGTH_WITH_QUOTES = 2 };
374
375 if (data.length() < k_STRING_LENGTH_WITH_QUOTES
376 || '"' != *data.begin()
377 || '"' != *(data.end() - 1)) {
378 return -1; // RETURN
379 }
380
382 value,
383 data.data() + 1,
384 static_cast<int>(data.length() - k_STRING_LENGTH_WITH_QUOTES));
385}
386
387inline
388int ParserUtil::getValue(char *value, const bsl::string_view& data)
389{
390 signed char tmp; // Note that 'char' is unsigned on IBM.
391 const int rc = getIntegralValue(&tmp, data);
392 if (!rc) {
393 *value = tmp;
394 }
395 return rc;
396}
397
398inline
399int ParserUtil::getValue(unsigned char *value, const bsl::string_view& data)
400{
401 return getUnsignedIntegralValue(value, data);
402}
403
404inline
405int ParserUtil::getValue(signed char *value, const bsl::string_view& data)
406{
407 return getValue((char *) value, data);
408}
409
410inline
411int ParserUtil::getValue(short *value, const bsl::string_view& data)
412{
413 return getIntegralValue(value, data);
414}
415
416inline
417int ParserUtil::getValue(unsigned short *value, const bsl::string_view& data)
418{
419 return getUnsignedIntegralValue(value, data);
420}
421
422inline
423int ParserUtil::getValue(int *value, const bsl::string_view& data)
424{
425 return getIntegralValue(value, data);
426}
427
428inline
429int ParserUtil::getValue(unsigned int *value, const bsl::string_view& data)
430{
431 return getUnsignedIntegralValue(value, data);
432}
433
434inline
436 const bsl::string_view& data)
437{
438 return getIntegralValue(value, data);
439}
440
441inline
443 const bsl::string_view& data)
444{
445 return getUnsignedIntegralValue(value, data);
446}
447
448inline
449int ParserUtil::getValue(float *value, const bsl::string_view& data)
450{
451 double tmp;
452 const int rc = getValue(&tmp, data);
453 if (!rc) {
454 *value = static_cast<float>(tmp);
455 }
456 return rc;
457}
458
459inline
467
468inline
470{
471 return getDateAndTimeValue(value, data);
472}
473
474inline
476{
477 return getDateAndTimeValue(value, data);
478}
479
480inline
482{
483 return getDateAndTimeValue(value, data);
484}
485
486inline
488{
489 return getDateAndTimeValue(value, data);
490}
491
492inline
494{
495 return getDateAndTimeValue(value, data);
496}
497
498inline
500{
501 return getDateAndTimeValue(value, data);
502}
503
504inline
506{
507 return getDateAndTimeValue(value, data);
508}
509
510inline
511int ParserUtil::getValue(TimeOrTimeTz *value, const bsl::string_view& data)
512{
513 return getDateAndTimeValue(value, data);
514}
515
516inline
517int ParserUtil::getValue(DatetimeOrDatetimeTz *value,
518 const bsl::string_view& data)
519{
520 return getDateAndTimeValue(value, data);
521}
522} // close package namespace
523
524
525
526#endif
527
528// ----------------------------------------------------------------------------
529// Copyright 2018 Bloomberg Finance L.P.
530//
531// Licensed under the Apache License, Version 2.0 (the "License");
532// you may not use this file except in compliance with the License.
533// You may obtain a copy of the License at
534//
535// http://www.apache.org/licenses/LICENSE-2.0
536//
537// Unless required by applicable law or agreed to in writing, software
538// distributed under the License is distributed on an "AS IS" BASIS,
539// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
540// See the License for the specific language governing permissions and
541// limitations under the License.
542// ----------------------------- END-OF-FILE ----------------------------------
543
544/** @} */
545/** @} */
546/** @} */
Definition bdlb_variant.h:2514
Definition bdldfp_decimal.h:1834
Definition bdlt_datetz.h:162
Definition bdlt_date.h:294
Definition bdlt_datetimetz.h:308
Definition bdlt_datetime.h:331
Definition bdlt_timetz.h:190
Definition bdlt_time.h:196
Definition bslstl_stringview.h:441
Definition bslstl_string.h:1281
Definition bslstl_vector.h:1025
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition baljsn_datumdecoderoptions.h:113
BSLS_KEYWORD_CONSTEXPR CONTAINER::value_type * data(CONTAINER &container)
Definition bslstl_iterator.h:1231
Definition baljsn_parserutil.h:140
static int getValue(bool *value, const bsl::string_view &data)
static int getValue(bdldfp::Decimal64 *value, const bsl::string_view &data)
bdlb::Variant2< bdlt::Date, bdlt::DateTz > DateOrDateTz
Definition baljsn_parserutil.h:194
static int getValue(TimeOrTimeTz *value, const bsl::string_view &data)
static int getValue(DatetimeOrDatetimeTz *value, const bsl::string_view &data)
static int getValue(bsl::vector< char > *value, const bsl::string_view &data)
static int getQuotedString(bsl::string *value, const bsl::string_view &data)
Definition baljsn_parserutil.h:293
static int getValue(double *value, const bsl::string_view &data)
static bool stripQuotes(bsl::string_view *str)
bdlb::Variant2< bdlt::Datetime, bdlt::DatetimeTz > DatetimeOrDatetimeTz
Definition baljsn_parserutil.h:203
static int getUnquotedString(bsl::string *value, const bsl::string_view &data)
bdlb::Variant2< bdlt::Time, bdlt::TimeTz > TimeOrTimeTz
Definition baljsn_parserutil.h:198
@ e_ACCEPT_CAPITAL_UNICODE_ESCAPE
Definition bdljsn_stringutil.h:241
static int readString(bsl::string *value, const bsl::string_view &string, int flags=e_NONE)
Definition bdljsn_stringutil.h:285
static int parse(bsls::TimeInterval *result, const char *string, ssize_t length)
unsigned long long Uint64
Definition bsls_types.h:137
long long Int64
Definition bsls_types.h:132