BDE 4.39.x Production Release
Loading...
Searching...
No Matches
baljsn_printutil.h
Go to the documentation of this file.
1/// @file baljsn_printutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// baljsn_printutil.h -*-C++-*-
8#ifndef INCLUDED_BALJSN_PRINTUTIL
9#define INCLUDED_BALJSN_PRINTUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup baljsn_printutil baljsn_printutil
15/// @brief Provide a utility for encoding simple types in the JSON format.
16/// @addtogroup bal
17/// @{
18/// @addtogroup baljsn
19/// @{
20/// @addtogroup baljsn_printutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#baljsn_printutil-purpose"> Purpose</a>
25/// * <a href="#baljsn_printutil-classes"> Classes </a>
26/// * <a href="#baljsn_printutil-description"> Description </a>
27/// * <a href="#baljsn_printutil-usage"> Usage </a>
28/// * <a href="#baljsn_printutil-example-1-encoding-a-simple-struct-into-json"> Example 1: Encoding a Simple struct into JSON </a>
29///
30/// # Purpose {#baljsn_printutil-purpose}
31/// Provide a utility for encoding simple types in the JSON format.
32///
33/// # Classes {#baljsn_printutil-classes}
34///
35/// - baljsn::PrintUtil: utility for printing simple types in JSON
36///
37/// @see baljsn_encoder, baljsn_parserutil
38///
39/// # Description {#baljsn_printutil-description}
40/// This component provides a `struct` of utility functions,
41/// `baljsn::PrintUtil`, for encoding a `bdeat` Simple type in the JSON format.
42/// The primary method is `printValue`, which encodes a specified object and is
43/// overloaded for all `bdeat` Simple types. The following table describes the
44/// format in which various Simple types are encoded.
45///
46/// Refer to the details of the JSON encoding format supported by this utility
47/// in the package documentation file (doc/baljsn.txt).
48///
49/// ## Usage {#baljsn_printutil-usage}
50///
51///
52/// This section illustrates intended use of this component.
53///
54/// ## Example 1: Encoding a Simple struct into JSON {#baljsn_printutil-example-1-encoding-a-simple-struct-into-json}
55///
56///
57/// Suppose we want to serialize some data into JSON.
58///
59/// First, we define a struct, `Employee`, to contain the data:
60/// @code
61/// struct Employee {
62/// const char *d_firstName;
63/// const char *d_lastName;
64/// int d_age;
65/// };
66/// @endcode
67/// Then, we create an `Employee` object and populate it with data:
68/// @code
69/// Employee john;
70/// john.d_firstName = "John";
71/// john.d_lastName = "Doe";
72/// john.d_age = 20;
73/// @endcode
74/// Now, we create an output stream and manually construct the JSON string
75/// using `baljsn::PrintUtil`:
76/// @code
77/// bsl::ostringstream oss;
78/// oss << '{' << '\n';
79/// baljsn::PrintUtil::printValue(oss, "firstName");
80/// oss << ':';
81/// baljsn::PrintUtil::printValue(oss, john.d_firstName);
82/// oss << ',' << '\n';
83/// baljsn::PrintUtil::printValue(oss, "lastName");
84/// oss << ':';
85/// baljsn::PrintUtil::printValue(oss, john.d_lastName);
86/// oss << ',' << '\n';
87/// baljsn::PrintUtil::printValue(oss, "age");
88/// oss << ':';
89/// baljsn::PrintUtil::printValue(oss, john.d_age);
90/// oss << '\n' << '}';
91/// @endcode
92/// Finally, we print out the JSON string:
93/// @code
94/// if (verbose) {
95/// bsl::cout << oss.str();
96/// }
97/// @endcode
98/// The output should look like:
99/// @code
100/// {
101/// "firstName":"John",
102/// "lastName":"Doe",
103/// "age":20
104/// }
105/// @endcode
106/// @}
107/** @} */
108/** @} */
109
110/** @addtogroup bal
111 * @{
112 */
113/** @addtogroup baljsn
114 * @{
115 */
116/** @addtogroup baljsn_printutil
117 * @{
118 */
119
120#include <balscm_version.h>
121
123
124#include <bdlb_float.h>
125#include <bdlb_variant.h>
126
127#include <bdldfp_decimal.h>
129#include <bdldfp_decimalutil.h>
130#include <bdljsn_stringutil.h>
132#include <bdlt_iso8601util.h>
133
135
136#include <bsla_fallthrough.h>
137
138#include <bsls_platform.h>
139#include <bsls_types.h>
140
141#include <bsl_c_stdio.h>
142#include <bsl_cmath.h>
143#include <bsl_iomanip.h>
144#include <bsl_ios.h>
145#include <bsl_limits.h>
146#include <bsl_ostream.h>
147#include <bsl_string.h>
148#include <bsl_string_view.h>
149
150
151namespace baljsn {
152
153 // ===============
154 // class PrintUtil
155 // ===============
156
157/// This `struct` provides functions for printing objects to output streams
158/// in JSON format.
159///
160/// See @ref baljsn_printutil
161struct PrintUtil {
162
163 private:
164 // PRIVATE CLASS METHODS
165
166 /// If the specified `options` is 0, return 0, otherwise return either
167 /// `options->maxFloatPrecision()` if the template parameter `TYPE` is
168 /// `float`, and `options->maxDoublePrecision()` is `double`. The
169 /// supplied `TYPE` must be either `float` or `double`.
170 template <class TYPE>
171 static int maxStreamPrecision(const baljsn::EncoderOptions *options);
172
173 public:
174 // TYPES
175
176 /// `DateOrDateTz` is a convenient alias for
177 /// `bdlb::Variant2<Date, DateTz>`.
179
180 /// `TimeOrTimeTz` is a convenient alias for
181 /// `bdlb::Variant2<Time, TimeTz>`.
183
184 /// `DatetimeOrDatetimeTz` is a convenient alias for
185 /// `bdlb::Variant2<Datetime, DatetimeTz>`.
188
189 // CLASS METHODS
190
191 /// Encode the specified `value` into JSON using ISO 8601 format and output
192 /// the result to the specified `stream` using the specified `options`.
193 template <class TYPE>
194 static int printDateAndTime(bsl::ostream& stream,
195 const TYPE& value,
196 const EncoderOptions *options);
197
198 /// Return the string representation of special floating point values if
199 /// the specified `classification` is:
200 /// * `bdlb::Float::k_POSITIVE_INFINITY`
201 /// * `bdlb::Float::k_NEGATIVE_INFINITY`
202 /// * `bdlb::Float::k_QNAN`
203 /// * `bdlb::Float::k_SNAN`
204 /// and 0 otherwise. This representation does *not* include the delimiting
205 /// double quotes of JSON strings.
206 static const char *floatingPointSpecialAsString(
207 bdlb::Float::FineClassification classification);
208
209 /// Encode the specified floating point `value` into JSON and output the
210 /// result to the specified `stream`. Use the optionally-specified
211 /// `options` to decide how `value` is encoded.
212 template <class TYPE>
213 static int printFloatingPoint(bsl::ostream& stream,
214 TYPE value,
215 const EncoderOptions *options);
216
217 /// Encode the specified string `value` into JSON format and output the
218 /// result to the specified `stream`.
219 static int printString(bsl::ostream& stream,
220 const bsl::string_view& value,
221 const EncoderOptions *options = 0);
222
223 /// Encode the specified `value` into JSON format and output the result
224 /// to the specified `stream` using the optionally specified `options`.
225 /// Return 0 on success and a non-zero value otherwise.
226 static int printValue(bsl::ostream& stream,
227 bool value,
228 const EncoderOptions *options = 0);
229 static int printValue(bsl::ostream& stream,
230 char value,
231 const EncoderOptions *options = 0);
232 static int printValue(bsl::ostream& stream,
233 signed char value,
234 const EncoderOptions *options = 0);
235 static int printValue(bsl::ostream& stream,
236 unsigned char value,
237 const EncoderOptions *options = 0);
238 static int printValue(bsl::ostream& stream,
239 short value,
240 const EncoderOptions *options = 0);
241 static int printValue(bsl::ostream& stream,
242 unsigned short value,
243 const EncoderOptions *options = 0);
244 static int printValue(bsl::ostream& stream,
245 int value,
246 const EncoderOptions *options = 0);
247 static int printValue(bsl::ostream& stream,
248 unsigned int value,
249 const EncoderOptions *options = 0);
250 static int printValue(bsl::ostream& stream,
251 long value,
252 const EncoderOptions *options = 0);
253 static int printValue(bsl::ostream& stream,
254 unsigned long value,
255 const EncoderOptions *options = 0);
256 static int printValue(bsl::ostream& stream,
257 long long value,
258 const EncoderOptions *options = 0);
259 static int printValue(bsl::ostream& stream,
260 unsigned long long value,
261 const EncoderOptions *options = 0);
262 static int printValue(bsl::ostream& stream,
263 float value,
264 const EncoderOptions *options = 0);
265 static int printValue(bsl::ostream& stream,
266 double value,
267 const EncoderOptions *options = 0);
268 static int printValue(bsl::ostream& stream,
269 bdldfp::Decimal64 value,
270 const EncoderOptions *options = 0);
271 static int printValue(bsl::ostream& stream,
272 const char *value,
273 const EncoderOptions *options = 0);
274 static int printValue(bsl::ostream& stream,
275 const bsl::string_view& value,
276 const EncoderOptions *options = 0);
277 static int printValue(bsl::ostream& stream,
278 const bdlt::Time& value,
279 const EncoderOptions *options = 0);
280 static int printValue(bsl::ostream& stream,
281 const bdlt::Date& value,
282 const EncoderOptions *options = 0);
283 static int printValue(bsl::ostream& stream,
284 const bdlt::Datetime& value,
285 const EncoderOptions *options = 0);
286 static int printValue(bsl::ostream& stream,
287 const bdlt::DatetimeInterval& value,
288 const EncoderOptions *options = 0);
289 static int printValue(bsl::ostream& stream,
290 const bdlt::TimeTz& value,
291 const EncoderOptions *options = 0);
292 static int printValue(bsl::ostream& stream,
293 const bdlt::DateTz& value,
294 const EncoderOptions *options = 0);
295 static int printValue(bsl::ostream& stream,
296 const bdlt::DatetimeTz& value,
297 const EncoderOptions *options = 0);
298 static int printValue(bsl::ostream& stream,
299 const TimeOrTimeTz& value,
300 const EncoderOptions *options = 0);
301 static int printValue(bsl::ostream& stream,
302 const DateOrDateTz& value,
303 const EncoderOptions *options = 0);
304 static int printValue(bsl::ostream& stream,
305 const DatetimeOrDatetimeTz& value,
306 const EncoderOptions *options = 0);
307};
308
309// ============================================================================
310// INLINE DEFINITIONS
311// ============================================================================
312
313 // ----------------
314 // struct PrintUtil
315 // ----------------
316
317// PRIVATE CLASS METHODS
318template <>
319inline
320int
321PrintUtil::maxStreamPrecision<float>(const baljsn::EncoderOptions *options)
322{
323 return options ? options->maxFloatPrecision() : 0;
324}
325
326template <>
327inline
328int
329PrintUtil::maxStreamPrecision<double>(const baljsn::EncoderOptions *options)
330{
331 return options ? options->maxDoublePrecision() : 0;
332}
333
334// CLASS METHODS
335template <class TYPE>
336inline
337int PrintUtil::printDateAndTime(bsl::ostream& stream,
338 const TYPE& value,
339 const EncoderOptions *options)
340{
341 char buffer[bdlt::Iso8601Util::k_MAX_STRLEN + 1];
343
344 if (options) {
347 }
348 else {
350 }
351
352 bdlt::Iso8601Util::generate(buffer, sizeof buffer, value, config);
353 return printValue(stream, buffer);
354}
355
356inline
358 bdlb::Float::FineClassification classification)
359{
360 const char *specialAsString =
361 bdlb::Float::k_POSITIVE_INFINITY == classification ? "+inf" :
362 bdlb::Float::k_NEGATIVE_INFINITY == classification ? "-inf" :
363 bdlb::Float::k_QNAN == classification ? "nan" :
364 bdlb::Float::k_SNAN == classification ? "nan" :
365 /* default */ 0 ;
366 return specialAsString;
367}
368
369template <class TYPE>
370int PrintUtil::printFloatingPoint(bsl::ostream& stream,
371 TYPE value,
372 const baljsn::EncoderOptions *options)
373{
374 bdlb::Float::FineClassification classification =
376 switch (classification) {
380 case bdlb::Float::k_SNAN: {
381 if (options && options->encodeInfAndNaNAsStrings()) {
382 stream << '"'
383 << floatingPointSpecialAsString(classification)
384 << '"';
385 }
386 else {
387 return -1; // RETURN
388 }
389 } break;
390 default: {
391 const int precision = maxStreamPrecision<TYPE>(options);
392
393 if (0 == precision) {
394 typedef bslalg::NumericFormatterUtil NumFmt;
395 char buffer[NumFmt::ToCharsMaxLength<TYPE>::k_VALUE];
396
397 const char * const endPtr = NumFmt::toChars(buffer,
398 buffer + sizeof buffer,
399 value);
400 BSLS_ASSERT(0 != endPtr);
401
402 const size_t len = endPtr - buffer;
403
404 stream.write(buffer, len);
405 }
406 else {
407 const int k_SIZE = 32;
408 char buffer[k_SIZE];
409#if defined(BSLS_PLATFORM_CMP_MSVC)
410#define snprintf _snprintf
411#endif
412 const int len = snprintf(buffer,
413 k_SIZE,
414 "%-1.*g",
415 precision,
416 value);
417#if defined(BSLS_PLATFORM_CMP_MSVC)
418#undef snprintf
419#endif
420 stream.write(buffer, len);
421 }
422 }
423 }
424 return 0;
425}
426
427inline
428int PrintUtil::printString(bsl::ostream& stream,
429 const bsl::string_view& value,
430 const EncoderOptions *options)
431{
433
434 if (options && !options->escapeForwardSlash()) {
436 }
437
438 return bdljsn::StringUtil::writeString(stream, value, stringWriteMode);
439}
440
441inline
442int PrintUtil::printValue(bsl::ostream& stream,
443 bool value,
444 const EncoderOptions *)
445{
446 stream << (value ? "true" : "false");
447 return 0;
448}
449
450inline
451int PrintUtil::printValue(bsl::ostream& stream,
452 short value,
453 const EncoderOptions *)
454{
455 stream << value;
456 return 0;
457}
458
459inline
460int PrintUtil::printValue(bsl::ostream& stream,
461 int value,
462 const EncoderOptions *)
463{
464 stream << value;
465 return 0;
466}
467
468inline
469int PrintUtil::printValue(bsl::ostream& stream,
470 long value,
471 const EncoderOptions *)
472{
473 stream << value;
474 return 0;
475}
476
477inline
478int PrintUtil::printValue(bsl::ostream& stream,
479 long long value,
480 const EncoderOptions *)
481{
482 stream << value;
483 return 0;
484}
485
486inline
487int PrintUtil::printValue(bsl::ostream& stream,
488 unsigned char value,
489 const EncoderOptions *)
490{
491 stream << static_cast<int>(value);
492 return 0;
493}
494
495inline
496int PrintUtil::printValue(bsl::ostream& stream,
497 unsigned short value,
498 const EncoderOptions *)
499{
500 stream << value;
501 return 0;
502}
503
504inline
505int PrintUtil::printValue(bsl::ostream& stream,
506 unsigned int value,
507 const EncoderOptions *)
508{
509 stream << value;
510 return 0;
511}
512
513inline
514int PrintUtil::printValue(bsl::ostream& stream,
515 unsigned long value,
516 const EncoderOptions *)
517{
518 stream << value;
519 return 0;
520}
521
522inline
523int PrintUtil::printValue(bsl::ostream& stream,
524 unsigned long long value,
525 const EncoderOptions *)
526{
527 stream << value;
528 return 0;
529}
530
531inline
532int PrintUtil::printValue(bsl::ostream& stream,
533 float value,
534 const EncoderOptions *options)
535{
536 return printFloatingPoint(stream, value, options);
537}
538
539inline
540int PrintUtil::printValue(bsl::ostream& stream,
541 double value,
542 const EncoderOptions *options)
543{
544 return printFloatingPoint(stream, value, options);
545}
546
547inline
548int PrintUtil::printValue(bsl::ostream& stream,
549 const char *value,
550 const EncoderOptions *options)
551{
552 return printString(stream, value, options);
553}
554
555inline
556int PrintUtil::printValue(bsl::ostream& stream,
557 char value,
558 const EncoderOptions *)
559{
560 signed char tmp(value); // Note that 'char' is unsigned on IBM.
561
562 stream << static_cast<int>(tmp);
563 return 0;
564}
565
566inline
567int PrintUtil::printValue(bsl::ostream& stream,
568 signed char value,
569 const EncoderOptions *)
570{
571 stream << static_cast<int>(value);
572 return 0;
573}
574
575inline
576int PrintUtil::printValue(bsl::ostream& stream,
577 const bsl::string_view& value,
578 const EncoderOptions *options)
579{
580 return printString(stream, value, options);
581}
582
583inline
584int PrintUtil::printValue(bsl::ostream& stream,
585 const bdlt::Time& value,
586 const EncoderOptions *options)
587{
588 return printDateAndTime(stream, value, options);
589}
590
591inline
592int PrintUtil::printValue(bsl::ostream& stream,
593 const bdlt::Date& value,
594 const EncoderOptions *options)
595{
596 return printDateAndTime(stream, value, options);
597}
598
599inline
600int PrintUtil::printValue(bsl::ostream& stream,
601 const bdlt::Datetime& value,
602 const EncoderOptions *options)
603{
604 return printDateAndTime(stream, value, options);
605}
606
607inline
608int PrintUtil::printValue(bsl::ostream& stream,
609 const bdlt::DatetimeInterval& value,
610 const EncoderOptions *)
611{
612 stream << '"' << value << '"';
613 return 0;
614}
615
616inline
617int PrintUtil::printValue(bsl::ostream& stream,
618 const bdlt::TimeTz& value,
619 const EncoderOptions *options)
620{
621 return printDateAndTime(stream, value, options);
622}
623
624inline
625int PrintUtil::printValue(bsl::ostream& stream,
626 const bdlt::DateTz& value,
627 const EncoderOptions *options)
628{
629 return printDateAndTime(stream, value, options);
630}
631
632inline
633int PrintUtil::printValue(bsl::ostream& stream,
634 const bdlt::DatetimeTz& value,
635 const EncoderOptions *options)
636{
637 return printDateAndTime(stream, value, options);
638}
639
640inline
641int PrintUtil::printValue(bsl::ostream& stream,
642 const TimeOrTimeTz& value,
643 const EncoderOptions *options)
644{
645 return printDateAndTime(stream, value, options);
646}
647
648inline
649int PrintUtil::printValue(bsl::ostream& stream,
650 const DateOrDateTz& value,
651 const EncoderOptions *options)
652{
653 return printDateAndTime(stream, value, options);
654}
655
656inline
657int PrintUtil::printValue(bsl::ostream& stream,
658 const DatetimeOrDatetimeTz& value,
659 const EncoderOptions *options)
660{
661 return printDateAndTime(stream, value, options);
662}
663
664} // close package namespace
665
666
667
668#endif
669
670// ----------------------------------------------------------------------------
671// Copyright 2015 Bloomberg Finance L.P.
672//
673// Licensed under the Apache License, Version 2.0 (the "License");
674// you may not use this file except in compliance with the License.
675// You may obtain a copy of the License at
676//
677// http://www.apache.org/licenses/LICENSE-2.0
678//
679// Unless required by applicable law or agreed to in writing, software
680// distributed under the License is distributed on an "AS IS" BASIS,
681// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
682// See the License for the specific language governing permissions and
683// limitations under the License.
684// ----------------------------- END-OF-FILE ----------------------------------
685
686/** @} */
687/** @} */
688/** @} */
Definition baljsn_encoderoptions.h:290
bool encodeInfAndNaNAsStrings() const
Definition baljsn_encoderoptions.h:1061
int maxFloatPrecision() const
Definition baljsn_encoderoptions.h:1073
int maxDoublePrecision() const
Definition baljsn_encoderoptions.h:1079
int datetimeFractionalSecondPrecision() const
Definition baljsn_encoderoptions.h:1067
bool escapeForwardSlash() const
Return the value of the "EscapeForwardSlash" attribute of this object.
Definition baljsn_encoderoptions.h:1091
Definition bdlb_variant.h:2592
Definition bdldfp_decimal.h:1890
Definition bdlt_datetz.h:161
Definition bdlt_date.h:294
Definition bdlt_datetimeinterval.h:201
Definition bdlt_datetimetz.h:308
Definition bdlt_datetime.h:330
Definition bdlt_iso8601utilconfiguration.h:224
void setFractionalSecondPrecision(int value)
Definition bdlt_timetz.h:190
Definition bdlt_time.h:195
Definition bslstl_stringview.h:471
#define BSLA_FALLTHROUGH
Definition bsla_fallthrough.h:188
#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
Definition baljsn_printutil.h:161
bdlb::Variant2< bdlt::Time, bdlt::TimeTz > TimeOrTimeTz
Definition baljsn_printutil.h:182
static int printString(bsl::ostream &stream, const bsl::string_view &value, const EncoderOptions *options=0)
Definition baljsn_printutil.h:428
static int printDateAndTime(bsl::ostream &stream, const TYPE &value, const EncoderOptions *options)
Definition baljsn_printutil.h:337
bdlb::Variant2< bdlt::Datetime, bdlt::DatetimeTz > DatetimeOrDatetimeTz
Definition baljsn_printutil.h:187
static int printValue(bsl::ostream &stream, bdldfp::Decimal64 value, const EncoderOptions *options=0)
static int printFloatingPoint(bsl::ostream &stream, TYPE value, const EncoderOptions *options)
Definition baljsn_printutil.h:370
static int printValue(bsl::ostream &stream, const DatetimeOrDatetimeTz &value, const EncoderOptions *options=0)
bdlb::Variant2< bdlt::Date, bdlt::DateTz > DateOrDateTz
Definition baljsn_printutil.h:178
static const char * floatingPointSpecialAsString(bdlb::Float::FineClassification classification)
Definition baljsn_printutil.h:357
static int printValue(bsl::ostream &stream, bool value, const EncoderOptions *options=0)
Definition baljsn_printutil.h:442
static int printValue(bsl::ostream &stream, const DateOrDateTz &value, const EncoderOptions *options=0)
static FineClassification classifyFine(float number)
FineClassification
Definition bdlb_float.h:244
@ k_SNAN
Definition bdlb_float.h:251
@ k_NEGATIVE_INFINITY
Definition bdlb_float.h:249
@ k_QNAN
Definition bdlb_float.h:250
@ k_POSITIVE_INFINITY
Definition bdlb_float.h:248
static int writeString(bsl::ostream &stream, const bsl::string_view &string, int flags=e_NONE)
Flags
Definition bdljsn_stringutil.h:241
@ e_NONE
Definition bdljsn_stringutil.h:242
@ e_NO_ESCAPING_FORWARD_SLASH
Definition bdljsn_stringutil.h:244
@ k_MAX_STRLEN
Definition bdlt_iso8601util.h:779
static int generate(char *buffer, ssize_t bufferLength, const bsls::TimeInterval &object)
Definition bdlt_iso8601util.h:2017
Definition bslalg_numericformatterutil.h:400