BDE 4.39.x 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 `bdlat`
42/// Simple type. The primary method is `getValue`, which decodes into a
43/// specified object and is overloaded for all `bdlat` 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_json.h>
110#include <bdljsn_stringutil.h>
111
112#include <bdlb_variant.h>
113
114#include <bdldfp_decimal.h>
115
116#include <bdlt_iso8601util.h>
117
118#include <bsla_unreachable.h>
119
120#include <bsls_assert.h>
121#include <bsls_libraryfeatures.h>
122#include <bsls_types.h>
123
124#include <bsl_limits.h>
125#include <bsl_cstring.h> // `bsl::strncmp`
126#include <bsl_string.h>
127#include <bsl_string_view.h>
128#include <bsl_vector.h>
129
130#include <string>
131
132
133namespace baljsn {
134
135 // =================
136 // struct ParserUtil
137 // =================
138
139///This class provides utility functions for decoding data in the JSON
140///format into a `bdlat` Simple type. The primary method is `getValue`,
141///which decodes into a specified object and is overloaded for all `bdlat`
142///Simple types.
143///
144/// See @ref baljsn_parserutil
146
147 private:
148 // PRIVATE CLASS METHODS
149
150 /// Load into the specified `value` the date or time value represented
151 /// as a string in the ISO 8601 format in the specified `data`. Return 0 on success and a non-zero value otherwise.
152 ///
153 /// \note Note that `TYPE` is
154 /// expected to be one of `bdlt::Date`, `bdlt::Time`, bdlt::Datetime',
155 /// `bdlt::DateTz`, `bdlt::TimeTz`, `bdlt::DatetimeTz`,
156 /// `bdlb::Variant2<bdlt::Date, bdlt::DateTz>`,
157 /// `bdlb::Variant2<bdlt::Time, bdlt::TimeTz>` or
158 /// `bdlb::Variant2<bdlt::Datetime, bdlt::DatetimeTz>`.
159 template <class TYPE>
160 static int getDateAndTimeValue(TYPE *value,
161 const bsl::string_view& data);
162
163 /// Load into the specified `value` the integer value in the specified `data`.
164 ///
165 /// \note Note that this operation follows the more permissive syntax
166 /// specified for `bdlb::NumericParseUtil`, allowing things like leading
167 /// `0` digits which the JSON spec does not permit. Return 0 on success and a non-zero value otherwise.
168 ///
169 /// \pre The behavior is undefined unless
170 /// `true == is_integral<TYPE>::value && is_signed<TYPE>::value`, e.g,
171 /// `TYPE` is expected to be a *signed* integral type.
172 ///
173 /// \note Note that although `data` is passed by value instead of `const`-reference,
174 /// there is no effect on usage.
175 template <class TYPE>
176 static int getIntegralValue(TYPE *value, bsl::string_view data);
177
178 /// Load into the specified `value` the unsigned integer value in the specified `data`.
179 ///
180 /// \note Note that this operation follows the more
181 /// permissive syntax specified for `bdlb::NumericParseUtil`, allowing
182 /// things like leading `0` digits which the JSON spec does not permit.
183 /// Return 0 on success and a non-zero value otherwise.
184 ///
185 /// \pre The behavior is undefined unless
186 /// `true == is_integral<TYPE>::value && !is_signed<TYPE>::value`, e.g,
187 /// `TYPE` is expected to be an *unsigned* integral type.
188 template <class TYPE>
189 static int getUnsignedIntegralValue(TYPE *value,
190 const bsl::string_view& data);
191
192 /// Load into the specified `value` the value in the specified `data`.
193 ///
194 /// \note Note that this operation follows the more permissive syntax
195 /// specified for `bdlb::NumericParseUtil`, allowing things like leading
196 /// `0` digits which the JSON spec does not permit. Return 0 on success
197 /// and a non-zero value otherwise.
198 static int getUint64(bsls::Types::Uint64 *value,
199 const bsl::string_view& data);
200
201 public:
202 // TYPES
203
204 /// `DateOrDateTz` is a convenient alias for
205 /// `bdlb::Variant2<Date, DateTz>`.
207
208 /// `TimeOrTimeTz` is a convenient alias for
209 /// `bdlb::Variant2<Time, TimeTz>`.
211
212 /// `DatetimeOrDatetimeTz` is a convenient alias for
213 /// `bdlb::Variant2<Datetime, DatetimeTz>`.
216
217 // CLASS METHODS
218
219 /// Load into the specified `value` the string value in the specified
220 /// `data`. The string must be begin and end in `"` characters which
221 /// are not part of the resulting `value`. Return 0 on success and a
222 /// non-zero value otherwise.
223 static int getQuotedString(bsl::string *value,
224 const bsl::string_view& data);
225 static int getQuotedString(std::string *value,
226 const bsl::string_view& data);
227#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
228 static int getQuotedString(std::pmr::string *value,
229 const bsl::string_view& data);
230#endif
231
232 /// Load into the specified `value` the string value in the specified
233 /// `data`. Return 0 on success and a non-zero value otherwise.
235 const bsl::string_view& data);
236 static int getUnquotedString(std::string *value,
237 const bsl::string_view& data);
238#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
239 static int getUnquotedString(std::pmr::string *value,
240 const bsl::string_view& data);
241#endif
242
243 // Overloads for `const bsl::string_view&`
244
245 /// Load into the specified `value` the characters read from the
246 /// specified `data`. Return 0 on success or a non-zero value on
247 /// failure.
248 static int getValue(bool *value,
249 const bsl::string_view& data);
250 static int getValue(char *value,
251 const bsl::string_view& data);
252 static int getValue(unsigned char *value,
253 const bsl::string_view& data);
254 static int getValue(signed char *value,
255 const bsl::string_view& data);
256 static int getValue(short *value,
257 const bsl::string_view& data);
258 static int getValue(unsigned short *value,
259 const bsl::string_view& data);
260 static int getValue(int *value,
261 const bsl::string_view& data);
262 static int getValue(unsigned int *value,
263 const bsl::string_view& data);
264 static int getValue(long *value,
265 const bsl::string_view& data);
266 static int getValue(unsigned long *value,
267 const bsl::string_view& data);
268 static int getValue(long long *value,
269 const bsl::string_view& data);
270 static int getValue(unsigned long long *value,
271 const bsl::string_view& data);
272 static int getValue(float *value,
273 const bsl::string_view& data);
274 static int getValue(double *value,
275 const bsl::string_view& data);
276 static int getValue(bdldfp::Decimal64 *value,
277 const bsl::string_view& data);
278 static int getValue(bdlt::Date *value,
279 const bsl::string_view& data);
280 static int getValue(bdlt::Datetime *value,
281 const bsl::string_view& data);
282 static int getValue(bdlt::DatetimeTz *value,
283 const bsl::string_view& data);
284 static int getValue(bdlt::DateTz *value,
285 const bsl::string_view& data);
286 static int getValue(bdlt::Time *value,
287 const bsl::string_view& data);
288 static int getValue(bdlt::TimeTz *value,
289 const bsl::string_view& data);
290 static int getValue(DateOrDateTz *value,
291 const bsl::string_view& data);
292 static int getValue(TimeOrTimeTz *value,
293 const bsl::string_view& data);
295 const bsl::string_view& data);
296 static int getValue(bsl::vector<char> *value,
297 const bsl::string_view& data);
298
299 /// Load into the specified `value` the string value in the specified
300 /// `data`. The string must be begin and end in `"` characters which
301 /// are not part of the resulting `value`. Return 0 on success and a
302 /// non-zero value otherwise.
303 static int getValue(bsl::string *value,
304 const bsl::string_view& data);
305 static int getValue(std::string *value,
306 const bsl::string_view& data);
307#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
308 static int getValue(std::pmr::string *value,
309 const bsl::string_view& data);
310#endif
311
312 /// If the specified `*str` is at least two characters long and begins
313 /// and ends with quotation marks ("), then remove the first and last
314 /// characters; otherwise, do not modify `*str`. Return `true` if
315 /// `*str` was modified.
316 static bool stripQuotes(bsl::string_view *str);
317};
318
319// ============================================================================
320// INLINE DEFINITIONS
321// ============================================================================
322
323 // -----------------
324 // struct ParserUtil
325 // -----------------
326
327// CLASS METHODS
328inline
337
338inline
339int ParserUtil::getQuotedString(std::string *value,
340 const bsl::string_view& data)
341{
343 value,
344 data,
346}
347
348#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
349inline
350int ParserUtil::getQuotedString(std::pmr::string *value,
351 const bsl::string_view& data)
352{
354 value,
355 data,
357}
358#endif
359
360template <class TYPE>
361int ParserUtil::getUnsignedIntegralValue(TYPE *value,
362 const bsl::string_view& data)
363{
364 BSLS_ASSERT(value);
365
366 if (0 == data.length()) {
367 return -1; // RETURN
368 }
369
371
372 int rc = getUint64(&tmp, data);
373 if (rc) {
374 return -1; // RETURN
375 }
376
377 if (tmp >
378 static_cast<bsls::Types::Uint64>((bsl::numeric_limits<TYPE>::max)())) {
379 return -1; // RETURN
380 }
381
382 *value = static_cast<TYPE>(tmp);
383 return 0;
384}
385
386template <class TYPE>
387int ParserUtil::getIntegralValue(TYPE *value, bsl::string_view data)
388{
389 // Note that we take 'data' by value because we may want to modify it.
390
391 if (0 == data.length()) {
392 return -1; // RETURN
393 }
394
395 bool isNegative;
396 if ('-' == data[0]) {
397 isNegative = true;
398 data.remove_prefix(1);
399 }
400 else {
401 isNegative = false;
402 }
403
405
406 const int rc = getUint64(&tmp, data);
407 if (rc) {
408 return -1; // RETURN
409 }
410
411 bsls::Types::Uint64 maxValue =
412 static_cast<bsls::Types::Uint64>((bsl::numeric_limits<TYPE>::max)());
413
414 if (isNegative && tmp <= maxValue + 1) {
415 *value = static_cast<TYPE>(tmp * -1);
416 }
417 else if (tmp <= maxValue) {
418 *value = static_cast<TYPE>(tmp);
419 }
420 else {
421 return -1; // RETURN
422 }
423
424 return 0;
425}
426
427template <class TYPE>
428int ParserUtil::getDateAndTimeValue(TYPE *value,
429 const bsl::string_view& data)
430{
431 enum { k_STRING_LENGTH_WITH_QUOTES = 2 };
432
433 if (data.length() < k_STRING_LENGTH_WITH_QUOTES
434 || '"' != *data.begin()
435 || '"' != *(data.end() - 1)) {
436 return -1; // RETURN
437 }
438
440 value,
441 data.data() + 1,
442 static_cast<int>(data.length() - k_STRING_LENGTH_WITH_QUOTES));
443 return rc;
444}
445
446inline
447int ParserUtil::getValue(char *value, const bsl::string_view& data)
448{
449 signed char tmp; // Note that 'char' is unsigned on IBM.
450 const int rc = getIntegralValue(&tmp, data);
451 if (!rc) {
452 *value = tmp;
453 }
454 return rc;
455}
456
457inline
458int ParserUtil::getValue(unsigned char *value, const bsl::string_view& data)
459{
460 return getUnsignedIntegralValue(value, data);
461}
462
463inline
464int ParserUtil::getValue(signed char *value, const bsl::string_view& data)
465{
466 return getValue((char *) value, data);
467}
468
469inline
470int ParserUtil::getValue(short *value, const bsl::string_view& data)
471{
472 return getIntegralValue(value, data);
473}
474
475inline
476int ParserUtil::getValue(unsigned short *value, const bsl::string_view& data)
477{
478 return getUnsignedIntegralValue(value, data);
479}
480
481inline
482int ParserUtil::getValue(int *value, const bsl::string_view& data)
483{
484 return getIntegralValue(value, data);
485}
486
487inline
488int ParserUtil::getValue(unsigned int *value, const bsl::string_view& data)
489{
490 return getUnsignedIntegralValue(value, data);
491}
492
493inline
494int ParserUtil::getValue(long *value,
495 const bsl::string_view& data)
496{
497 return getIntegralValue(value, data);
498}
499
500inline
501int ParserUtil::getValue(unsigned long *value,
502 const bsl::string_view& data)
503{
504 return getUnsignedIntegralValue(value, data);
505}
506
507inline
508int ParserUtil::getValue(long long *value,
509 const bsl::string_view& data)
510{
511 return getIntegralValue(value, data);
512}
513
514inline
515int ParserUtil::getValue(unsigned long long *value,
516 const bsl::string_view& data)
517{
518 return getUnsignedIntegralValue(value, data);
519}
520
521inline
522int ParserUtil::getValue(float *value, const bsl::string_view& data)
523{
524 double tmp;
525 const int rc = getValue(&tmp, data);
526 if (!rc) {
527 *value = static_cast<float>(tmp);
528 }
529 return rc;
530}
531
532inline
540
541inline
542int ParserUtil::getValue(std::string *value, const bsl::string_view& data)
543{
545 value,
546 data,
548}
549
550#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
551inline
552int ParserUtil::getValue(std::pmr::string *value, const bsl::string_view& data)
553{
555 value,
556 data,
558}
559#endif
560
561inline
563{
564 return getDateAndTimeValue(value, data);
565}
566
567inline
569{
570 return getDateAndTimeValue(value, data);
571}
572
573inline
575{
576 return getDateAndTimeValue(value, data);
577}
578
579inline
581{
582 return getDateAndTimeValue(value, data);
583}
584
585inline
587{
588 return getDateAndTimeValue(value, data);
589}
590
591inline
593{
594 return getDateAndTimeValue(value, data);
595}
596
597inline
599{
600 return getDateAndTimeValue(value, data);
601}
602
603inline
604int ParserUtil::getValue(TimeOrTimeTz *value, const bsl::string_view& data)
605{
606 return getDateAndTimeValue(value, data);
607}
608
609inline
610int ParserUtil::getValue(DatetimeOrDatetimeTz *value,
611 const bsl::string_view& data)
612{
613 return getDateAndTimeValue(value, data);
614}
615
616} // close package namespace
617
618
619#endif
620
621// ----------------------------------------------------------------------------
622// Copyright 2018 Bloomberg Finance L.P.
623//
624// Licensed under the Apache License, Version 2.0 (the "License");
625// you may not use this file except in compliance with the License.
626// You may obtain a copy of the License at
627//
628// http://www.apache.org/licenses/LICENSE-2.0
629//
630// Unless required by applicable law or agreed to in writing, software
631// distributed under the License is distributed on an "AS IS" BASIS,
632// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
633// See the License for the specific language governing permissions and
634// limitations under the License.
635// ----------------------------- END-OF-FILE ----------------------------------
636
637/** @} */
638/** @} */
639/** @} */
Definition bdlb_variant.h:2592
Definition bdldfp_decimal.h:1890
Definition bdlt_datetz.h:161
Definition bdlt_date.h:294
Definition bdlt_datetimetz.h:308
Definition bdlt_datetime.h:330
Definition bdlt_timetz.h:190
Definition bdlt_time.h:195
Definition bslstl_stringview.h:471
Definition bslstl_string.h:1252
Definition bslstl_vector.h:1120
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition baljsn_convertfromjsonoptions.h:112
BSLS_KEYWORD_CONSTEXPR CONTAINER::value_type * data(CONTAINER &container)
Definition bslstl_iterator.h:1325
Definition baljsn_parserutil.h:145
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:206
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 getUnquotedString(std::string *value, const bsl::string_view &data)
static int getQuotedString(bsl::string *value, const bsl::string_view &data)
Definition baljsn_parserutil.h:329
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:215
static int getUnquotedString(bsl::string *value, const bsl::string_view &data)
bdlb::Variant2< bdlt::Time, bdlt::TimeTz > TimeOrTimeTz
Definition baljsn_parserutil.h:210
@ e_ACCEPT_CAPITAL_UNICODE_ESCAPE
Definition bdljsn_stringutil.h:243
static int readString(bsl::string *value, const bsl::string_view &string, int flags=e_NONE)
Definition bdljsn_stringutil.h:341
static int parse(bsls::TimeInterval *result, const char *string, ssize_t length)
unsigned long long Uint64
Definition bsls_types.h:139