1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2023 Google LLC. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8 #include "upb/lex/round_trip.h"
9
10 #include <float.h>
11 #include <math.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14
15 // Must be last.
16 #include "upb/port/def.inc"
17
18 /* Miscellaneous utilities ****************************************************/
19
upb_FixLocale(char * p)20 static void upb_FixLocale(char* p) {
21 /* printf() is dependent on locales; sadly there is no easy and portable way
22 * to avoid this. This little post-processing step will translate 1,2 -> 1.2
23 * since JSON needs the latter. Arguably a hack, but it is simple and the
24 * alternatives are far more complicated, platform-dependent, and/or larger
25 * in code size. */
26 for (; *p; p++) {
27 if (*p == ',') *p = '.';
28 }
29 }
30
_upb_EncodeRoundTripDouble(double val,char * buf,size_t size)31 void _upb_EncodeRoundTripDouble(double val, char* buf, size_t size) {
32 assert(size >= kUpb_RoundTripBufferSize);
33 if (isnan(val)) {
34 snprintf(buf, size, "%s", "nan");
35 return;
36 }
37 snprintf(buf, size, "%.*g", DBL_DIG, val);
38 if (strtod(buf, NULL) != val) {
39 snprintf(buf, size, "%.*g", DBL_DIG + 2, val);
40 assert(strtod(buf, NULL) == val);
41 }
42 upb_FixLocale(buf);
43 }
44
_upb_EncodeRoundTripFloat(float val,char * buf,size_t size)45 void _upb_EncodeRoundTripFloat(float val, char* buf, size_t size) {
46 assert(size >= kUpb_RoundTripBufferSize);
47 if (isnan(val)) {
48 snprintf(buf, size, "%s", "nan");
49 return;
50 }
51 snprintf(buf, size, "%.*g", FLT_DIG, val);
52 if (strtof(buf, NULL) != val) {
53 snprintf(buf, size, "%.*g", FLT_DIG + 3, val);
54 assert(strtof(buf, NULL) == val);
55 }
56 upb_FixLocale(buf);
57 }
58