Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
C
capnproto
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
capnproto
Commits
2d291f8d
Commit
2d291f8d
authored
Jul 16, 2018
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Ensure primitive stringifiers are signal-safe.
Alas, this means we can't use sprintf() anymore. Ugh.
parent
0d851985
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
90 additions
and
34 deletions
+90
-34
string-test.c++
c++/src/kj/string-test.c++
+6
-0
string.c++
c++/src/kj/string.c++
+73
-24
string.h
c++/src/kj/string.h
+11
-10
No files found.
c++/src/kj/string-test.c++
View file @
2d291f8d
...
...
@@ -35,6 +35,12 @@ TEST(String, Str) {
EXPECT_EQ
(
"foo"
,
str
(
'f'
,
'o'
,
'o'
));
EXPECT_EQ
(
"123 234 -123 e7"
,
str
((
int8_t
)
123
,
" "
,
(
uint8_t
)
234
,
" "
,
(
int8_t
)
-
123
,
" "
,
hex
((
uint8_t
)
0xe7
)));
EXPECT_EQ
(
"-128 -32768 -2147483648 -9223372036854775808"
,
str
((
signed
char
)
-
128
,
' '
,
(
signed
short
)
-
32768
,
' '
,
((
int
)
-
2147483647
)
-
1
,
' '
,
((
long
long
)
-
9223372036854775807ll
)
-
1
))
EXPECT_EQ
(
"ff ffff ffffffff ffffffffffffffff"
,
str
(
hex
((
uint8_t
)
0xff
),
' '
,
hex
((
uint16_t
)
0xffff
),
' '
,
hex
((
uint32_t
)
0xffffffffu
),
' '
,
hex
((
uint64_t
)
0xffffffffffffffffull
)));
char
buf
[
3
]
=
{
'f'
,
'o'
,
'o'
};
ArrayPtr
<
char
>
a
=
buf
;
...
...
c++/src/kj/string.c++
View file @
2d291f8d
...
...
@@ -25,6 +25,7 @@
#include <float.h>
#include <errno.h>
#include <stdlib.h>
#include <stdint.h>
namespace
kj
{
...
...
@@ -118,18 +119,39 @@ String heapString(const char* value, size_t size) {
return
String
(
buffer
,
size
,
_
::
HeapArrayDisposer
::
instance
);
}
#define HEXIFY_INT(type, format) \
template
<
typename
T
>
static
CappedArray
<
char
,
sizeof
(
T
)
*
2
+
1
>
hexImpl
(
T
i
)
{
// We don't use sprintf() because it's not async-signal-safe (for strPreallocated()).
CappedArray
<
char
,
sizeof
(
T
)
*
2
+
1
>
result
;
char
reverse
[
sizeof
(
T
)
*
2
];
char
*
p
=
reverse
;
if
(
i
==
0
)
{
*
p
++
=
0
;
}
else
{
while
(
i
>
0
)
{
*
p
++
=
i
%
16
;
i
/=
16
;
}
}
char
*
p2
=
result
.
begin
();
while
(
p
>
reverse
)
{
*
p2
++
=
"0123456789abcdef"
[
*--
p
];
}
result
.
setSize
(
p2
-
result
.
begin
());
return
result
;
}
#define HEXIFY_INT(type) \
CappedArray<char, sizeof(type) * 2 + 1> hex(type i) { \
CappedArray<char, sizeof(type) * 2 + 1> result; \
result.setSize(sprintf(result.begin(), format, i)); \
return result; \
return hexImpl<type>(i); \
}
HEXIFY_INT
(
unsigned
char
,
"%x"
);
HEXIFY_INT
(
unsigned
short
,
"%x"
);
HEXIFY_INT
(
unsigned
int
,
"%x"
);
HEXIFY_INT
(
unsigned
long
,
"%lx"
);
HEXIFY_INT
(
unsigned
long
long
,
"%llx"
);
HEXIFY_INT
(
unsigned
char
);
HEXIFY_INT
(
unsigned
short
);
HEXIFY_INT
(
unsigned
int
);
HEXIFY_INT
(
unsigned
long
);
HEXIFY_INT
(
unsigned
long
long
);
#undef HEXIFY_INT
...
...
@@ -143,27 +165,54 @@ StringPtr Stringifier::operator*(bool b) const {
return
b
?
StringPtr
(
"true"
)
:
StringPtr
(
"false"
);
}
#define STRINGIFY_INT(type, format) \
template
<
typename
T
,
typename
Unsigned
>
static
CappedArray
<
char
,
sizeof
(
T
)
*
3
+
2
>
stringifyImpl
(
T
i
)
{
// We don't use sprintf() because it's not async-signal-safe (for strPreallocated()).
CappedArray
<
char
,
sizeof
(
T
)
*
3
+
2
>
result
;
bool
negative
=
i
<
0
;
Unsigned
u
=
negative
?
-
i
:
i
;
char
reverse
[
sizeof
(
T
)
*
3
+
1
];
char
*
p
=
reverse
;
if
(
u
==
0
)
{
*
p
++
=
0
;
}
else
{
while
(
u
>
0
)
{
*
p
++
=
u
%
10
;
u
/=
10
;
}
}
char
*
p2
=
result
.
begin
();
if
(
negative
)
*
p2
++
=
'-'
;
while
(
p
>
reverse
)
{
*
p2
++
=
'0'
+
*--
p
;
}
result
.
setSize
(
p2
-
result
.
begin
());
return
result
;
}
#define STRINGIFY_INT(type, unsigned) \
CappedArray<char, sizeof(type) * 3 + 2> Stringifier::operator*(type i) const { \
CappedArray<char, sizeof(type) * 3 + 2> result; \
result.setSize(sprintf(result.begin(), format, i)); \
return result; \
return stringifyImpl<type, unsigned>(i); \
}
STRINGIFY_INT
(
signed
char
,
"%d"
);
STRINGIFY_INT
(
unsigned
char
,
"%u"
);
STRINGIFY_INT
(
short
,
"%d"
);
STRINGIFY_INT
(
unsigned
short
,
"%u"
);
STRINGIFY_INT
(
int
,
"%d"
);
STRINGIFY_INT
(
unsigned
int
,
"%u"
);
STRINGIFY_INT
(
long
,
"%ld"
);
STRINGIFY_INT
(
unsigned
long
,
"%lu"
);
STRINGIFY_INT
(
long
long
,
"%lld"
);
STRINGIFY_INT
(
unsigned
long
long
,
"%llu"
);
STRINGIFY_INT
(
const
void
*
,
"%p"
);
STRINGIFY_INT
(
signed
char
,
uint
);
STRINGIFY_INT
(
unsigned
char
,
uint
);
STRINGIFY_INT
(
short
,
uint
);
STRINGIFY_INT
(
unsigned
short
,
uint
);
STRINGIFY_INT
(
int
,
uint
);
STRINGIFY_INT
(
unsigned
int
,
uint
);
STRINGIFY_INT
(
long
,
unsigned
long
);
STRINGIFY_INT
(
unsigned
long
,
unsigned
long
);
STRINGIFY_INT
(
long
long
,
unsigned
long
long
);
STRINGIFY_INT
(
unsigned
long
long
,
unsigned
long
long
);
#undef STRINGIFY_INT
CappedArray
<
char
,
sizeof
(
const
void
*
)
*
2
+
1
>
Stringifier
::
operator
*
(
const
void
*
i
)
const
{
\
return
hexImpl
<
uintptr_t
>
(
reinterpret_cast
<
uintptr_t
>
(
i
));
}
namespace
{
// ----------------------------------------------------------------------
...
...
c++/src/kj/string.h
View file @
2d291f8d
...
...
@@ -368,12 +368,12 @@ struct Stringifier {
CappedArray
<
char
,
sizeof
(
unsigned
long
long
)
*
3
+
2
>
operator
*
(
unsigned
long
long
i
)
const
;
CappedArray
<
char
,
24
>
operator
*
(
float
f
)
const
;
CappedArray
<
char
,
32
>
operator
*
(
double
f
)
const
;
CappedArray
<
char
,
sizeof
(
const
void
*
)
*
3
+
2
>
operator
*
(
const
void
*
s
)
const
;
CappedArray
<
char
,
sizeof
(
const
void
*
)
*
2
+
1
>
operator
*
(
const
void
*
s
)
const
;
template
<
typename
T
>
String
operator
*
(
ArrayPtr
<
T
>
arr
)
const
;
_
::
Delimited
<
ArrayPtr
<
T
>>
operator
*
(
ArrayPtr
<
T
>
arr
)
const
;
template
<
typename
T
>
String
operator
*
(
const
Array
<
T
>&
arr
)
const
;
_
::
Delimited
<
ArrayPtr
<
const
T
>>
operator
*
(
const
Array
<
T
>&
arr
)
const
;
#if KJ_COMPILER_SUPPORTS_STL_STRING_INTEROP // supports expression SFINAE?
template
<
typename
T
,
typename
Result
=
decltype
(
instance
<
T
>
().
toString
())
>
...
...
@@ -457,9 +457,10 @@ StringPtr strPreallocated(ArrayPtr<char> buffer, Params&&... params) {
// This is useful for optimization. It can also potentially be used safely in async signal
// handlers. HOWEVER, to use in an async signal handler, all of the stringifiers for the inputs
// must also be signal-safe. KJ guarantees signal safety when stringifying any built-in integer
// type, basic char/byte sequences (ArrayPtr<byte>, String, etc.), as well as Array<T> as long
// as T can also be stringified safely. To safely stringify a delimited array, you must use
// kj::delimited(arr, delim) rather than the deprecated kj::strArray(arr, delim).
// type (but NOT floating-points), basic char/byte sequences (ArrayPtr<byte>, String, etc.), as
// well as Array<T> as long as T can also be stringified safely. To safely stringify a delimited
// array, you must use kj::delimited(arr, delim) rather than the deprecated
// kj::strArray(arr, delim).
char
*
end
=
_
::
fillLimited
(
buffer
.
begin
(),
buffer
.
end
()
-
1
,
toCharSequence
(
kj
::
fwd
<
Params
>
(
params
))...);
...
...
@@ -470,13 +471,13 @@ StringPtr strPreallocated(ArrayPtr<char> buffer, Params&&... params) {
namespace
_
{
// private
template
<
typename
T
>
inline
String
Stringifier
::
operator
*
(
ArrayPtr
<
T
>
arr
)
const
{
return
strArray
(
arr
,
", "
);
inline
_
::
Delimited
<
ArrayPtr
<
T
>>
Stringifier
::
operator
*
(
ArrayPtr
<
T
>
arr
)
const
{
return
_
::
Delimited
<
ArrayPtr
<
T
>>
(
arr
,
", "
);
}
template
<
typename
T
>
inline
String
Stringifier
::
operator
*
(
const
Array
<
T
>&
arr
)
const
{
return
strArray
(
arr
,
", "
);
inline
_
::
Delimited
<
ArrayPtr
<
const
T
>>
Stringifier
::
operator
*
(
const
Array
<
T
>&
arr
)
const
{
return
_
::
Delimited
<
ArrayPtr
<
const
T
>>
(
arr
,
", "
);
}
}
// namespace _ (private)
...
...
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