Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
R
rapidjson
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
rapidjson
Commits
1d856b27
Commit
1d856b27
authored
9 years ago
by
Milo Yip
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add Writer::SetMaxDecimalPlaces()
parent
7e383864
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
159 additions
and
9 deletions
+159
-9
dtoa.h
include/rapidjson/internal/dtoa.h
+31
-5
writer.h
include/rapidjson/writer.h
+36
-4
CMakeLists.txt
test/unittest/CMakeLists.txt
+1
-0
dtoatest.cpp
test/unittest/dtoatest.cpp
+91
-0
No files found.
include/rapidjson/internal/dtoa.h
View file @
1d856b27
...
...
@@ -145,7 +145,7 @@ inline char* WriteExponent(int K, char* buffer) {
return
buffer
;
}
inline
char
*
Prettify
(
char
*
buffer
,
int
length
,
int
k
)
{
inline
char
*
Prettify
(
char
*
buffer
,
int
length
,
int
k
,
int
maxDecimalPlaces
)
{
const
int
kk
=
length
+
k
;
// 10^(kk-1) <= v < 10^kk
if
(
length
<=
kk
&&
kk
<=
21
)
{
...
...
@@ -160,7 +160,16 @@ inline char* Prettify(char* buffer, int length, int k) {
// 1234e-2 -> 12.34
std
::
memmove
(
&
buffer
[
kk
+
1
],
&
buffer
[
kk
],
static_cast
<
size_t
>
(
length
-
kk
));
buffer
[
kk
]
=
'.'
;
return
&
buffer
[
length
+
1
];
if
(
length
>
kk
+
maxDecimalPlaces
)
{
// When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1
// Remove extra trailing zeros (at least one) after truncation.
for
(
int
i
=
kk
+
maxDecimalPlaces
;
i
>
kk
+
1
;
i
--
)
if
(
buffer
[
i
]
!=
'0'
)
return
&
buffer
[
i
+
1
];
return
&
buffer
[
kk
+
2
];
// Reserve one zero
}
else
return
&
buffer
[
length
+
1
];
}
else
if
(
-
6
<
kk
&&
kk
<=
0
)
{
// 1234e-6 -> 0.001234
...
...
@@ -170,7 +179,23 @@ inline char* Prettify(char* buffer, int length, int k) {
buffer
[
1
]
=
'.'
;
for
(
int
i
=
2
;
i
<
offset
;
i
++
)
buffer
[
i
]
=
'0'
;
return
&
buffer
[
length
+
offset
];
if
(
length
+
offset
>
maxDecimalPlaces
)
{
// When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1
// Remove extra trailing zeros (at least one) after truncation.
for
(
int
i
=
maxDecimalPlaces
+
1
;
i
>
2
;
i
--
)
if
(
buffer
[
i
]
!=
'0'
)
return
&
buffer
[
i
+
1
];
return
&
buffer
[
3
];
// Reserve one zero
}
else
return
&
buffer
[
length
+
offset
];
}
else
if
(
kk
<
-
maxDecimalPlaces
)
{
// Truncate to zero
buffer
[
0
]
=
'0'
;
buffer
[
1
]
=
'.'
;
buffer
[
2
]
=
'0'
;
return
&
buffer
[
3
];
}
else
if
(
length
==
1
)
{
// 1e30
...
...
@@ -186,7 +211,8 @@ inline char* Prettify(char* buffer, int length, int k) {
}
}
inline
char
*
dtoa
(
double
value
,
char
*
buffer
)
{
inline
char
*
dtoa
(
double
value
,
char
*
buffer
,
int
maxDecimalPlaces
=
324
)
{
RAPIDJSON_ASSERT
(
maxDecimalPlaces
>=
1
);
Double
d
(
value
);
if
(
d
.
IsZero
())
{
if
(
d
.
Sign
())
...
...
@@ -203,7 +229,7 @@ inline char* dtoa(double value, char* buffer) {
}
int
length
,
K
;
Grisu2
(
value
,
buffer
,
&
length
,
&
K
);
return
Prettify
(
buffer
,
length
,
K
);
return
Prettify
(
buffer
,
length
,
K
,
maxDecimalPlaces
);
}
}
...
...
This diff is collapsed.
Click to expand it.
include/rapidjson/writer.h
View file @
1d856b27
...
...
@@ -56,6 +56,8 @@ class Writer {
public
:
typedef
typename
SourceEncoding
::
Ch
Ch
;
static
const
int
kDefaultMaxDecimalPlaces
=
324
;
//! Constructor
/*! \param os Output stream.
\param stackAllocator User supplied allocator. If it is null, it will create a private one.
...
...
@@ -63,11 +65,11 @@ public:
*/
explicit
Writer
(
OutputStream
&
os
,
StackAllocator
*
stackAllocator
=
0
,
size_t
levelDepth
=
kDefaultLevelDepth
)
:
os_
(
&
os
),
level_stack_
(
stackAllocator
,
levelDepth
*
sizeof
(
Level
)),
hasRoot_
(
false
)
{}
os_
(
&
os
),
level_stack_
(
stackAllocator
,
levelDepth
*
sizeof
(
Level
)),
maxDecimalPlaces_
(
kDefaultMaxDecimalPlaces
),
hasRoot_
(
false
)
{}
explicit
Writer
(
StackAllocator
*
allocator
=
0
,
size_t
levelDepth
=
kDefaultLevelDepth
)
:
os_
(
0
),
level_stack_
(
allocator
,
levelDepth
*
sizeof
(
Level
)),
hasRoot_
(
false
)
{}
os_
(
0
),
level_stack_
(
allocator
,
levelDepth
*
sizeof
(
Level
)),
maxDecimalPlaces_
(
kDefaultMaxDecimalPlaces
),
hasRoot_
(
false
)
{}
//! Reset the writer with a new stream.
/*!
...
...
@@ -101,6 +103,35 @@ public:
return
hasRoot_
&&
level_stack_
.
Empty
();
}
int
GetMaxDecimalPlaces
()
const
{
return
maxDecimalPlaces_
;
}
//! Sets the maximum number of decimal places for double output.
/*!
This setting truncates the output with specified number of decimal places.
For example,
\code
writer.SetMaxDecimalPlaces(3);
writer.StartArray();
writer.Double(0.12345); // "0.123"
writer.Double(0.0001); // "0.0"
writer.Double(1.234567890123456e30); // "1.234567890123456e30" (do not truncate significand for positive exponent)
writer.Double(1.23e-4); // "0.0" (do truncate significand for negative exponent)
writer.EndArray();
\endcode
The default setting does not truncate any decimal places. You can restore to this setting by calling
\code
writer.SetMaxDecimalPlaces(Writer::kDefaultMaxDecimalPlaces);
\endcode
*/
void
SetMaxDecimalPlaces
(
int
maxDecimalPlaces
)
{
maxDecimalPlaces_
=
maxDecimalPlaces
;
}
/*!@name Implementation of Handler
\see Handler
*/
...
...
@@ -246,7 +277,7 @@ protected:
return
false
;
char
buffer
[
25
];
char
*
end
=
internal
::
dtoa
(
d
,
buffer
);
char
*
end
=
internal
::
dtoa
(
d
,
buffer
,
maxDecimalPlaces_
);
PutReserve
(
*
os_
,
static_cast
<
size_t
>
(
end
-
buffer
));
for
(
char
*
p
=
buffer
;
p
!=
end
;
++
p
)
PutUnsafe
(
*
os_
,
static_cast
<
typename
TargetEncoding
::
Ch
>
(
*
p
));
...
...
@@ -353,6 +384,7 @@ protected:
OutputStream
*
os_
;
internal
::
Stack
<
StackAllocator
>
level_stack_
;
int
maxDecimalPlaces_
;
bool
hasRoot_
;
private
:
...
...
@@ -401,7 +433,7 @@ inline bool Writer<StringBuffer>::WriteDouble(double d) {
return
false
;
char
*
buffer
=
os_
->
Push
(
25
);
char
*
end
=
internal
::
dtoa
(
d
,
buffer
);
char
*
end
=
internal
::
dtoa
(
d
,
buffer
,
maxDecimalPlaces_
);
os_
->
Pop
(
static_cast
<
size_t
>
(
25
-
(
end
-
buffer
)));
return
true
;
}
...
...
This diff is collapsed.
Click to expand it.
test/unittest/CMakeLists.txt
View file @
1d856b27
...
...
@@ -2,6 +2,7 @@ set(UNITTEST_SOURCES
allocatorstest.cpp
bigintegertest.cpp
documenttest.cpp
dtoatest.cpp
encodedstreamtest.cpp
encodingstest.cpp
fwdtest.cpp
...
...
This diff is collapsed.
Click to expand it.
test/unittest/dtoatest.cpp
0 → 100644
View file @
1d856b27
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "unittest.h"
#include "rapidjson/internal/dtoa.h"
#ifdef __GNUC__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF
(
type
-
limits
)
#endif
using
namespace
rapidjson
::
internal
;
TEST
(
dtoa
,
normal
)
{
char
buffer
[
30
];
#define TEST_DTOA(d, a)\
*dtoa(d, buffer) = '\0';\
EXPECT_STREQ(a, buffer)
TEST_DTOA
(
0.0
,
"0.0"
);
TEST_DTOA
(
-
0.0
,
"-0.0"
);
TEST_DTOA
(
1.0
,
"1.0"
);
TEST_DTOA
(
-
1.0
,
"-1.0"
);
TEST_DTOA
(
1.2345
,
"1.2345"
);
TEST_DTOA
(
1.2345678
,
"1.2345678"
);
TEST_DTOA
(
0.123456789012
,
"0.123456789012"
);
TEST_DTOA
(
1234567.8
,
"1234567.8"
);
TEST_DTOA
(
0.000001
,
"0.000001"
);
TEST_DTOA
(
0.0000001
,
"1e-7"
);
TEST_DTOA
(
1e30
,
"1e30"
);
TEST_DTOA
(
1.234567890123456e30
,
"1.234567890123456e30"
);
TEST_DTOA
(
5e-324
,
"5e-324"
);
// Min subnormal positive double
TEST_DTOA
(
2.225073858507201e-308
,
"2.225073858507201e-308"
);
// Max subnormal positive double
TEST_DTOA
(
2.2250738585072014e-308
,
"2.2250738585072014e-308"
);
// Min normal positive double
TEST_DTOA
(
1.7976931348623157e308
,
"1.7976931348623157e308"
);
// Max double
#undef TEST_DTOA
}
TEST
(
dtoa
,
maxDecimalPlaces
)
{
char
buffer
[
30
];
#define TEST_DTOA(m, d, a)\
*dtoa(d, buffer, m) = '\0';\
EXPECT_STREQ(a, buffer)
TEST_DTOA
(
3
,
0.0
,
"0.0"
);
TEST_DTOA
(
1
,
0.0
,
"0.0"
);
TEST_DTOA
(
3
,
-
0.0
,
"-0.0"
);
TEST_DTOA
(
3
,
1.0
,
"1.0"
);
TEST_DTOA
(
3
,
-
1.0
,
"-1.0"
);
TEST_DTOA
(
3
,
1.2345
,
"1.234"
);
TEST_DTOA
(
2
,
1.2345
,
"1.23"
);
TEST_DTOA
(
1
,
1.2345
,
"1.2"
);
TEST_DTOA
(
3
,
1.2345678
,
"1.234"
);
TEST_DTOA
(
3
,
1.0001
,
"1.0"
);
TEST_DTOA
(
2
,
1.0001
,
"1.0"
);
TEST_DTOA
(
1
,
1.0001
,
"1.0"
);
TEST_DTOA
(
3
,
0.123456789012
,
"0.123"
);
TEST_DTOA
(
2
,
0.123456789012
,
"0.12"
);
TEST_DTOA
(
1
,
0.123456789012
,
"0.1"
);
TEST_DTOA
(
4
,
0.0001
,
"0.0001"
);
TEST_DTOA
(
3
,
0.0001
,
"0.0"
);
TEST_DTOA
(
2
,
0.0001
,
"0.0"
);
TEST_DTOA
(
1
,
0.0001
,
"0.0"
);
TEST_DTOA
(
3
,
1234567.8
,
"1234567.8"
);
TEST_DTOA
(
3
,
1e30
,
"1e30"
);
TEST_DTOA
(
3
,
5e-324
,
"0.0"
);
// Min subnormal positive double
TEST_DTOA
(
3
,
2.225073858507201e-308
,
"0.0"
);
// Max subnormal positive double
TEST_DTOA
(
3
,
2.2250738585072014e-308
,
"0.0"
);
// Min normal positive double
TEST_DTOA
(
3
,
1.7976931348623157e308
,
"1.7976931348623157e308"
);
// Max double
#undef TEST_DTOA
}
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
#endif
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment