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
ad611c13
Commit
ad611c13
authored
May 31, 2013
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Improve String.
parent
4958d3a4
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
310 additions
and
117 deletions
+310
-117
stringify.c++
c++/src/capnproto/stringify.c++
+1
-1
array-test.c++
c++/src/kj/array-test.c++
+19
-0
array.h
c++/src/kj/array.h
+34
-8
common.h
c++/src/kj/common.h
+9
-1
exception.c++
c++/src/kj/exception.c++
+8
-9
exception.h
c++/src/kj/exception.h
+8
-7
logging-test.c++
c++/src/kj/logging-test.c++
+1
-2
logging.c++
c++/src/kj/logging.c++
+24
-28
logging.h
c++/src/kj/logging.h
+15
-15
memory.h
c++/src/kj/memory.h
+11
-0
string.c++
c++/src/kj/string.c++
+9
-5
string.h
c++/src/kj/string.h
+155
-13
util-test.c++
c++/src/kj/util-test.c++
+4
-9
util.c++
c++/src/kj/util.c++
+0
-1
util.h
c++/src/kj/util.h
+12
-18
No files found.
c++/src/capnproto/stringify.c++
View file @
ad611c13
...
...
@@ -176,7 +176,7 @@ kj::String stringify(DynamicValue::Reader value) {
std
::
stringstream
out
;
print
(
out
,
value
,
schema
::
Type
::
Body
::
STRUCT_TYPE
);
auto
content
=
out
.
str
();
return
kj
::
String
(
content
.
data
(),
content
.
size
());
return
kj
::
heap
String
(
content
.
data
(),
content
.
size
());
}
namespace
internal
{
...
...
c++/src/kj/array-test.c++
View file @
ad611c13
...
...
@@ -283,5 +283,24 @@ TEST(Array, AraryBuilderAddAll) {
EXPECT_EQ
(
0
,
TestObject
::
copiedCount
);
}
TEST
(
Array
,
HeapCopy
)
{
{
Array
<
char
>
copy
=
heapArray
(
"foo"
,
3
);
EXPECT_EQ
(
3u
,
copy
.
size
());
EXPECT_EQ
(
"foo"
,
std
::
string
(
copy
.
begin
(),
3
));
}
{
Array
<
char
>
copy
=
heapArray
(
ArrayPtr
<
const
char
>
(
"bar"
,
3
));
EXPECT_EQ
(
3u
,
copy
.
size
());
EXPECT_EQ
(
"bar"
,
std
::
string
(
copy
.
begin
(),
3
));
}
{
const
char
*
ptr
=
"baz"
;
Array
<
char
>
copy
=
heapArray
<
char
>
(
ptr
,
ptr
+
3
);
EXPECT_EQ
(
3u
,
copy
.
size
());
EXPECT_EQ
(
"baz"
,
std
::
string
(
copy
.
begin
(),
3
));
}
}
}
// namespace
}
// namespace kj
c++/src/kj/array.h
View file @
ad611c13
...
...
@@ -156,14 +156,6 @@ namespace internal {
class
HeapArrayDisposer
final
:
public
ArrayDisposer
{
public
:
static
void
*
allocateImpl
(
size_t
elementSize
,
size_t
elementCount
,
size_t
capacity
,
void
(
*
constructElement
)(
void
*
),
void
(
*
destroyElement
)(
void
*
));
// Allocates and constructs the array. Both function pointers are null if the constructor is
// trivial, otherwise destroyElement is null if the constructor doesn't throw.
virtual
void
disposeImpl
(
void
*
firstElement
,
size_t
elementSize
,
size_t
elementCount
,
size_t
capacity
,
void
(
*
destroyElement
)(
void
*
))
const
override
;
template
<
typename
T
>
static
T
*
allocate
(
size_t
count
);
template
<
typename
T
>
...
...
@@ -172,6 +164,14 @@ public:
static
const
HeapArrayDisposer
instance
;
private
:
static
void
*
allocateImpl
(
size_t
elementSize
,
size_t
elementCount
,
size_t
capacity
,
void
(
*
constructElement
)(
void
*
),
void
(
*
destroyElement
)(
void
*
));
// Allocates and constructs the array. Both function pointers are null if the constructor is
// trivial, otherwise destroyElement is null if the constructor doesn't throw.
virtual
void
disposeImpl
(
void
*
firstElement
,
size_t
elementSize
,
size_t
elementCount
,
size_t
capacity
,
void
(
*
destroyElement
)(
void
*
))
const
override
;
template
<
typename
T
,
bool
hasTrivialConstructor
=
__has_trivial_constructor
(
T
),
bool
hasNothrowConstructor
=
__has_nothrow_constructor
(
T
)
>
struct
Allocate_
;
...
...
@@ -189,6 +189,11 @@ inline Array<T> heapArray(size_t size) {
internal
::
HeapArrayDisposer
::
instance
);
}
template
<
typename
T
>
Array
<
T
>
heapArray
(
const
T
*
content
,
size_t
size
);
template
<
typename
T
>
Array
<
T
>
heapArray
(
ArrayPtr
<
const
T
>
content
);
template
<
typename
T
,
typename
Iterator
>
Array
<
T
>
heapArray
(
Iterator
begin
,
Iterator
end
);
// Allocate a heap arary containing a copy of the given content.
// =======================================================================================
// ArrayBuilder
...
...
@@ -462,6 +467,27 @@ void ArrayBuilder<T>::addAll(Iterator start, Iterator end) {
pos
=
internal
::
copyConstructArray
(
pos
,
start
,
end
);
}
template
<
typename
T
>
Array
<
T
>
heapArray
(
const
T
*
content
,
size_t
size
)
{
ArrayBuilder
<
T
>
builder
=
heapArrayBuilder
<
T
>
(
size
);
builder
.
addAll
(
content
,
content
+
size
);
return
builder
.
finish
();
}
template
<
typename
T
>
Array
<
T
>
heapArray
(
ArrayPtr
<
const
T
>
content
)
{
ArrayBuilder
<
T
>
builder
=
heapArrayBuilder
<
T
>
(
content
.
size
());
builder
.
addAll
(
content
);
return
builder
.
finish
();
}
template
<
typename
T
,
typename
Iterator
>
Array
<
T
>
heapArray
(
Iterator
begin
,
Iterator
end
)
{
ArrayBuilder
<
T
>
builder
=
heapArrayBuilder
<
T
>
(
end
-
begin
);
builder
.
addAll
(
begin
,
end
);
return
builder
.
finish
();
}
}
// namespace kj
#endif // KJ_ARRAY_H_
c++/src/kj/common.h
View file @
ad611c13
...
...
@@ -181,6 +181,14 @@ template <typename T> struct IsLvalueReference_<T&> { static constexpr bool valu
template
<
typename
T
>
inline
constexpr
bool
isLvalueReference
()
{
return
IsLvalueReference_
<
T
>::
value
;
}
template
<
typename
T
>
struct
Decay_
{
typedef
T
Type
;
};
template
<
typename
T
>
struct
Decay_
<
T
&>
{
typedef
typename
Decay_
<
T
>::
Type
Type
;
};
template
<
typename
T
>
struct
Decay_
<
T
&&>
{
typedef
typename
Decay_
<
T
>::
Type
Type
;
};
template
<
typename
T
>
struct
Decay_
<
T
[]
>
{
typedef
typename
Decay_
<
T
*>::
Type
Type
;
};
template
<
typename
T
>
struct
Decay_
<
const
T
>
{
typedef
typename
Decay_
<
T
>::
Type
Type
;
};
template
<
typename
T
>
struct
Decay_
<
volatile
T
>
{
typedef
typename
Decay_
<
T
>::
Type
Type
;
};
template
<
typename
T
>
using
Decay
=
typename
Decay_
<
T
>::
Type
;
template
<
typename
T
>
T
instance
()
noexcept
;
// Like std::declval, but doesn't transform T into an rvalue reference. If you want that, specify
...
...
@@ -494,7 +502,7 @@ public:
inline
T
&
front
()
const
{
return
*
ptr
;
}
inline
T
&
back
()
const
{
return
*
(
ptr
+
size_
-
1
);
}
inline
ArrayPtr
slice
(
size_t
start
,
size_t
end
)
{
inline
ArrayPtr
slice
(
size_t
start
,
size_t
end
)
const
{
KJ_INLINE_DPRECOND
(
start
<=
end
&&
end
<=
size_
,
"Out-of-bounds ArrayPtr::slice()."
);
return
ArrayPtr
(
ptr
+
start
,
end
-
start
);
}
...
...
c++/src/kj/exception.c++
View file @
ad611c13
...
...
@@ -21,7 +21,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define KJ_PRIVATE
#include "exception.h"
#include "util.h"
#include "logging.h"
...
...
@@ -56,7 +55,7 @@ ArrayPtr<const char> operator*(const Stringifier&, Exception::Durability durabil
}
Exception
::
Exception
(
Nature
nature
,
Durability
durability
,
const
char
*
file
,
int
line
,
Array
<
char
>
description
)
noexcept
String
description
)
noexcept
:
file
(
file
),
line
(
line
),
nature
(
nature
),
durability
(
durability
),
description
(
mv
(
description
))
{
traceCount
=
backtrace
(
trace
,
16
);
...
...
@@ -68,7 +67,7 @@ Exception::Exception(const Exception& other) noexcept
memcpy
(
trace
,
other
.
trace
,
sizeof
(
trace
[
0
])
*
traceCount
);
KJ_IF_MAYBE
(
c
,
other
.
context
)
{
context
=
heap
<
Context
>
(
**
c
);
context
=
heap
(
**
c
);
}
}
...
...
@@ -77,11 +76,11 @@ Exception::~Exception() noexcept {}
Exception
::
Context
::
Context
(
const
Context
&
other
)
noexcept
:
file
(
other
.
file
),
line
(
other
.
line
),
description
(
str
(
other
.
description
))
{
KJ_IF_MAYBE
(
n
,
other
.
next
)
{
next
=
heap
<
Context
>
(
**
n
);
next
=
heap
(
**
n
);
}
}
void
Exception
::
wrapContext
(
const
char
*
file
,
int
line
,
Array
<
char
>
&&
description
)
{
void
Exception
::
wrapContext
(
const
char
*
file
,
int
line
,
String
&&
description
)
{
context
=
heap
<
Context
>
(
file
,
line
,
mv
(
description
),
mv
(
context
));
}
...
...
@@ -98,7 +97,7 @@ const char* Exception::what() const noexcept {
}
}
Array
<
Array
<
char
>>
contextText
=
heapArray
<
Array
<
char
>
>
(
contextDepth
);
Array
<
String
>
contextText
=
heapArray
<
String
>
(
contextDepth
);
contextDepth
=
0
;
contextPtr
=
&
context
;
...
...
@@ -118,7 +117,7 @@ const char* Exception::what() const noexcept {
file
,
":"
,
line
,
": "
,
nature
,
durability
==
Durability
::
TEMPORARY
?
" (temporary)"
:
""
,
this
->
description
==
nullptr
?
""
:
": "
,
this
->
description
,
"
\n
stack: "
,
strArray
(
arrayPtr
(
trace
,
traceCount
),
" "
)
,
'\0'
);
"
\n
stack: "
,
strArray
(
arrayPtr
(
trace
,
traceCount
),
" "
));
return
whatBuffer
.
begin
();
}
...
...
@@ -163,14 +162,14 @@ void ExceptionCallback::onFatalException(Exception&& exception) {
#endif
}
void
ExceptionCallback
::
logMessage
(
ArrayPtr
<
const
char
>
text
)
{
void
ExceptionCallback
::
logMessage
(
StringPtr
text
)
{
while
(
text
!=
nullptr
)
{
ssize_t
n
=
write
(
STDERR_FILENO
,
text
.
begin
(),
text
.
size
());
if
(
n
<=
0
)
{
// stderr is broken. Give up.
return
;
}
text
=
text
.
slice
(
n
,
text
.
size
()
);
text
=
text
.
slice
(
n
);
}
}
...
...
c++/src/kj/exception.h
View file @
ad611c13
...
...
@@ -27,6 +27,7 @@
#include <exception>
#include "memory.h"
#include "array.h"
#include "string.h"
namespace
kj
{
...
...
@@ -64,7 +65,7 @@ public:
};
Exception
(
Nature
nature
,
Durability
durability
,
const
char
*
file
,
int
line
,
Array
<
char
>
description
=
nullptr
)
noexcept
;
String
description
=
nullptr
)
noexcept
;
Exception
(
const
Exception
&
other
)
noexcept
;
Exception
(
Exception
&&
other
)
=
default
;
~
Exception
()
noexcept
;
...
...
@@ -80,10 +81,10 @@ public:
const
char
*
file
;
int
line
;
Array
<
char
>
description
;
String
description
;
Maybe
<
Own
<
Context
>>
next
;
Context
(
const
char
*
file
,
int
line
,
Array
<
char
>
&&
description
,
Maybe
<
Own
<
Context
>>&&
next
)
Context
(
const
char
*
file
,
int
line
,
String
&&
description
,
Maybe
<
Own
<
Context
>>&&
next
)
:
file
(
file
),
line
(
line
),
description
(
mv
(
description
)),
next
(
mv
(
next
))
{}
Context
(
const
Context
&
other
)
noexcept
;
};
...
...
@@ -96,7 +97,7 @@ public:
}
}
void
wrapContext
(
const
char
*
file
,
int
line
,
Array
<
char
>
&&
description
);
void
wrapContext
(
const
char
*
file
,
int
line
,
String
&&
description
);
// Wraps the context in a new node. This becomes the head node returned by getContext() -- it
// is expected that contexts will be added in reverse order as the exception passes up the
// callback stack.
...
...
@@ -108,11 +109,11 @@ private:
int
line
;
Nature
nature
;
Durability
durability
;
Array
<
char
>
description
;
String
description
;
Maybe
<
Own
<
Context
>>
context
;
void
*
trace
[
16
];
uint
traceCount
;
mutable
Array
<
char
>
whatBuffer
;
mutable
String
whatBuffer
;
};
struct
Stringifier
;
...
...
@@ -143,7 +144,7 @@ public:
// aborting. The default implementation throws an exception unless the library was compiled with
// -fno-exceptions, in which case it logs an error and returns.
virtual
void
logMessage
(
ArrayPtr
<
const
char
>
text
);
virtual
void
logMessage
(
StringPtr
text
);
// Called when something wants to log some debug text. The text always ends in a newline if
// it is non-empty. The default implementation writes the text to stderr.
...
...
c++/src/kj/logging-test.c++
View file @
ad611c13
...
...
@@ -21,7 +21,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define KJ_PRIVATE
#include "logging.h"
#include "exception.h"
#include <gtest/gtest.h>
...
...
@@ -70,7 +69,7 @@ public:
throw
MockException
();
}
void
logMessage
(
ArrayPtr
<
const
char
>
text
)
override
{
void
logMessage
(
StringPtr
text
)
override
{
this
->
text
+=
"log message: "
;
this
->
text
.
append
(
text
.
begin
(),
text
.
end
());
}
...
...
c++/src/kj/logging.c++
View file @
ad611c13
...
...
@@ -21,7 +21,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define KJ_PRIVATE
#include "logging.h"
#include <stdlib.h>
#include <ctype.h>
...
...
@@ -52,8 +51,8 @@ enum DescriptionStyle {
SYSCALL
};
static
Array
<
char
>
makeDescription
(
DescriptionStyle
style
,
const
char
*
code
,
int
errorNumber
,
const
char
*
macroArgs
,
ArrayPtr
<
Array
<
char
>
>
argValues
)
{
static
String
makeDescription
(
DescriptionStyle
style
,
const
char
*
code
,
int
errorNumber
,
const
char
*
macroArgs
,
ArrayPtr
<
String
>
argValues
)
{
KJ_STACK_ARRAY
(
ArrayPtr
<
const
char
>
,
argNames
,
argValues
.
size
(),
8
,
64
);
if
(
argValues
.
size
()
>
0
)
{
...
...
@@ -112,22 +111,22 @@ static Array<char> makeDescription(DescriptionStyle style, const char* code, int
}
{
ArrayPtr
<
const
char
>
expected
=
stringPtr
(
"expected "
)
;
ArrayPtr
<
const
char
>
codeArray
=
style
==
LOG
?
nullptr
:
s
tringPtr
(
code
);
ArrayPtr
<
const
char
>
sep
=
stringPtr
(
" = "
)
;
ArrayPtr
<
const
char
>
delim
=
stringPtr
(
"; "
)
;
ArrayPtr
<
const
char
>
colon
=
stringPtr
(
": "
)
;
StringPtr
expected
=
"expected "
;
StringPtr
codeArray
=
style
==
LOG
?
nullptr
:
S
tringPtr
(
code
);
StringPtr
sep
=
" = "
;
StringPtr
delim
=
"; "
;
StringPtr
colon
=
": "
;
if
(
style
==
ASSERTION
&&
strcmp
(
code
,
"false"
)
==
0
)
{
// Don't print "expected false", that's silly.
style
=
LOG
;
}
ArrayPtr
<
const
char
>
sysErrorArray
;
StringPtr
sysErrorArray
;
#if __USE_GNU
char
buffer
[
256
];
if
(
style
==
SYSCALL
)
{
sysErrorArray
=
str
ingPtr
(
strerror_r
(
errorNumber
,
buffer
,
sizeof
(
buffer
)
));
sysErrorArray
=
str
error_r
(
errorNumber
,
buffer
,
sizeof
(
buffer
));
}
#else
// TODO(port): Other unixes should have strerror_r but it may have a different signature.
...
...
@@ -157,40 +156,37 @@ static Array<char> makeDescription(DescriptionStyle style, const char* code, int
totalSize
+=
argValues
[
i
].
size
();
}
ArrayBuilder
<
char
>
result
=
heapArrayBuilder
<
char
>
(
totalSize
);
String
result
=
heapString
(
totalSize
);
char
*
pos
=
result
.
begin
();
switch
(
style
)
{
case
LOG
:
break
;
case
ASSERTION
:
result
.
addAll
(
expected
);
result
.
addAll
(
codeArray
);
pos
=
fill
(
pos
,
expected
,
codeArray
);
break
;
case
SYSCALL
:
result
.
addAll
(
codeArray
);
result
.
addAll
(
colon
);
result
.
addAll
(
sysErrorArray
);
pos
=
fill
(
pos
,
codeArray
,
colon
,
sysErrorArray
);
break
;
}
for
(
size_t
i
=
0
;
i
<
argValues
.
size
();
i
++
)
{
if
(
i
>
0
||
style
!=
LOG
)
{
result
.
addAll
(
delim
);
pos
=
fill
(
pos
,
delim
);
}
if
(
argNames
[
i
].
size
()
>
0
&&
argNames
[
i
][
0
]
!=
'\"'
)
{
result
.
addAll
(
argNames
[
i
]);
result
.
addAll
(
sep
);
pos
=
fill
(
pos
,
argNames
[
i
],
sep
);
}
result
.
addAll
(
argValues
[
i
]);
pos
=
fill
(
pos
,
argValues
[
i
]);
}
return
result
.
finish
()
;
return
result
;
}
}
}
// namespace
void
Log
::
logInternal
(
const
char
*
file
,
int
line
,
Severity
severity
,
const
char
*
macroArgs
,
ArrayPtr
<
Array
<
char
>
>
argValues
)
{
ArrayPtr
<
String
>
argValues
)
{
getExceptionCallback
().
logMessage
(
str
(
severity
,
": "
,
file
,
":"
,
line
,
": "
,
makeDescription
(
LOG
,
nullptr
,
0
,
macroArgs
,
argValues
),
'\n'
));
...
...
@@ -198,7 +194,7 @@ void Log::logInternal(const char* file, int line, Severity severity, const char*
void
Log
::
recoverableFaultInternal
(
const
char
*
file
,
int
line
,
Exception
::
Nature
nature
,
const
char
*
condition
,
const
char
*
macroArgs
,
ArrayPtr
<
Array
<
char
>
>
argValues
)
{
const
char
*
condition
,
const
char
*
macroArgs
,
ArrayPtr
<
String
>
argValues
)
{
getExceptionCallback
().
onRecoverableException
(
Exception
(
nature
,
Exception
::
Durability
::
PERMANENT
,
file
,
line
,
makeDescription
(
ASSERTION
,
condition
,
0
,
macroArgs
,
argValues
)));
...
...
@@ -206,7 +202,7 @@ void Log::recoverableFaultInternal(
void
Log
::
fatalFaultInternal
(
const
char
*
file
,
int
line
,
Exception
::
Nature
nature
,
const
char
*
condition
,
const
char
*
macroArgs
,
ArrayPtr
<
Array
<
char
>
>
argValues
)
{
const
char
*
condition
,
const
char
*
macroArgs
,
ArrayPtr
<
String
>
argValues
)
{
getExceptionCallback
().
onFatalException
(
Exception
(
nature
,
Exception
::
Durability
::
PERMANENT
,
file
,
line
,
makeDescription
(
ASSERTION
,
condition
,
0
,
macroArgs
,
argValues
)));
...
...
@@ -215,7 +211,7 @@ void Log::fatalFaultInternal(
void
Log
::
recoverableFailedSyscallInternal
(
const
char
*
file
,
int
line
,
const
char
*
call
,
int
errorNumber
,
const
char
*
macroArgs
,
ArrayPtr
<
Array
<
char
>
>
argValues
)
{
int
errorNumber
,
const
char
*
macroArgs
,
ArrayPtr
<
String
>
argValues
)
{
getExceptionCallback
().
onRecoverableException
(
Exception
(
Exception
::
Nature
::
OS_ERROR
,
Exception
::
Durability
::
PERMANENT
,
file
,
line
,
makeDescription
(
SYSCALL
,
call
,
errorNumber
,
macroArgs
,
argValues
)));
...
...
@@ -223,7 +219,7 @@ void Log::recoverableFailedSyscallInternal(
void
Log
::
fatalFailedSyscallInternal
(
const
char
*
file
,
int
line
,
const
char
*
call
,
int
errorNumber
,
const
char
*
macroArgs
,
ArrayPtr
<
Array
<
char
>
>
argValues
)
{
int
errorNumber
,
const
char
*
macroArgs
,
ArrayPtr
<
String
>
argValues
)
{
getExceptionCallback
().
onFatalException
(
Exception
(
Exception
::
Nature
::
OS_ERROR
,
Exception
::
Durability
::
PERMANENT
,
file
,
line
,
makeDescription
(
SYSCALL
,
call
,
errorNumber
,
macroArgs
,
argValues
)));
...
...
@@ -231,7 +227,7 @@ void Log::fatalFailedSyscallInternal(
}
void
Log
::
addContextToInternal
(
Exception
&
exception
,
const
char
*
file
,
int
line
,
const
char
*
macroArgs
,
ArrayPtr
<
Array
<
char
>
>
argValues
)
{
const
char
*
macroArgs
,
ArrayPtr
<
String
>
argValues
)
{
exception
.
wrapContext
(
file
,
line
,
makeDescription
(
LOG
,
nullptr
,
0
,
macroArgs
,
argValues
));
}
...
...
@@ -251,7 +247,7 @@ void Log::Context::onFatalException(Exception&& exception) {
addTo
(
exception
);
next
.
onFatalException
(
kj
::
mv
(
exception
));
}
void
Log
::
Context
::
logMessage
(
ArrayPtr
<
const
char
>
text
)
{
void
Log
::
Context
::
logMessage
(
StringPtr
text
)
{
// TODO(someday): We could do something like log the context and then indent all log messages
// written until the end of the context.
next
.
logMessage
(
text
);
...
...
c++/src/kj/logging.h
View file @
ad611c13
...
...
@@ -158,7 +158,7 @@ public:
virtual
void
onRecoverableException
(
Exception
&&
exception
)
override
;
virtual
void
onFatalException
(
Exception
&&
exception
)
override
;
virtual
void
logMessage
(
ArrayPtr
<
const
char
>
text
)
override
;
virtual
void
logMessage
(
StringPtr
text
)
override
;
private
:
ExceptionCallback
&
next
;
...
...
@@ -186,23 +186,23 @@ private:
static
Severity
minSeverity
;
static
void
logInternal
(
const
char
*
file
,
int
line
,
Severity
severity
,
const
char
*
macroArgs
,
ArrayPtr
<
Array
<
char
>
>
argValues
);
ArrayPtr
<
String
>
argValues
);
static
void
recoverableFaultInternal
(
const
char
*
file
,
int
line
,
Exception
::
Nature
nature
,
const
char
*
condition
,
const
char
*
macroArgs
,
ArrayPtr
<
Array
<
char
>
>
argValues
);
const
char
*
condition
,
const
char
*
macroArgs
,
ArrayPtr
<
String
>
argValues
);
static
void
fatalFaultInternal
(
const
char
*
file
,
int
line
,
Exception
::
Nature
nature
,
const
char
*
condition
,
const
char
*
macroArgs
,
ArrayPtr
<
Array
<
char
>
>
argValues
)
const
char
*
condition
,
const
char
*
macroArgs
,
ArrayPtr
<
String
>
argValues
)
KJ_NORETURN
;
static
void
recoverableFailedSyscallInternal
(
const
char
*
file
,
int
line
,
const
char
*
call
,
int
errorNumber
,
const
char
*
macroArgs
,
ArrayPtr
<
Array
<
char
>
>
argValues
);
int
errorNumber
,
const
char
*
macroArgs
,
ArrayPtr
<
String
>
argValues
);
static
void
fatalFailedSyscallInternal
(
const
char
*
file
,
int
line
,
const
char
*
call
,
int
errorNumber
,
const
char
*
macroArgs
,
ArrayPtr
<
Array
<
char
>
>
argValues
)
int
errorNumber
,
const
char
*
macroArgs
,
ArrayPtr
<
String
>
argValues
)
KJ_NORETURN
;
static
void
addContextToInternal
(
Exception
&
exception
,
const
char
*
file
,
int
line
,
const
char
*
macroArgs
,
ArrayPtr
<
Array
<
char
>
>
argValues
);
const
char
*
macroArgs
,
ArrayPtr
<
String
>
argValues
);
static
int
getOsErrorNumber
();
// Get the error code of the last error (e.g. from errno). Returns -1 on EINTR.
...
...
@@ -287,14 +287,14 @@ ArrayPtr<const char> operator*(const Stringifier&, Log::Severity severity);
template
<
typename
...
Params
>
void
Log
::
log
(
const
char
*
file
,
int
line
,
Severity
severity
,
const
char
*
macroArgs
,
Params
&&
...
params
)
{
Array
<
char
>
argValues
[
sizeof
...(
Params
)]
=
{
str
(
params
)...};
String
argValues
[
sizeof
...(
Params
)]
=
{
str
(
params
)...};
logInternal
(
file
,
line
,
severity
,
macroArgs
,
arrayPtr
(
argValues
,
sizeof
...(
Params
)));
}
template
<
typename
...
Params
>
void
Log
::
recoverableFault
(
const
char
*
file
,
int
line
,
Exception
::
Nature
nature
,
const
char
*
condition
,
const
char
*
macroArgs
,
Params
&&
...
params
)
{
Array
<
char
>
argValues
[
sizeof
...(
Params
)]
=
{
str
(
params
)...};
String
argValues
[
sizeof
...(
Params
)]
=
{
str
(
params
)...};
recoverableFaultInternal
(
file
,
line
,
nature
,
condition
,
macroArgs
,
arrayPtr
(
argValues
,
sizeof
...(
Params
)));
}
...
...
@@ -302,7 +302,7 @@ void Log::recoverableFault(const char* file, int line, Exception::Nature nature,
template
<
typename
...
Params
>
void
Log
::
fatalFault
(
const
char
*
file
,
int
line
,
Exception
::
Nature
nature
,
const
char
*
condition
,
const
char
*
macroArgs
,
Params
&&
...
params
)
{
Array
<
char
>
argValues
[
sizeof
...(
Params
)]
=
{
str
(
params
)...};
String
argValues
[
sizeof
...(
Params
)]
=
{
str
(
params
)...};
fatalFaultInternal
(
file
,
line
,
nature
,
condition
,
macroArgs
,
arrayPtr
(
argValues
,
sizeof
...(
Params
)));
}
...
...
@@ -315,7 +315,7 @@ bool Log::recoverableSyscall(Call&& call, const char* file, int line, const char
int
errorNum
=
getOsErrorNumber
();
// getOsErrorNumber() returns -1 to indicate EINTR
if
(
errorNum
!=
-
1
)
{
Array
<
char
>
argValues
[
sizeof
...(
Params
)]
=
{
str
(
params
)...};
String
argValues
[
sizeof
...(
Params
)]
=
{
str
(
params
)...};
recoverableFailedSyscallInternal
(
file
,
line
,
callText
,
errorNum
,
macroArgs
,
arrayPtr
(
argValues
,
sizeof
...(
Params
)));
return
false
;
...
...
@@ -333,7 +333,7 @@ auto Log::syscall(Call&& call, const char* file, int line, const char* callText,
int
errorNum
=
getOsErrorNumber
();
// getOsErrorNumber() returns -1 to indicate EINTR
if
(
errorNum
!=
-
1
)
{
Array
<
char
>
argValues
[
sizeof
...(
Params
)]
=
{
str
(
params
)...};
String
argValues
[
sizeof
...(
Params
)]
=
{
str
(
params
)...};
fatalFailedSyscallInternal
(
file
,
line
,
callText
,
errorNum
,
macroArgs
,
arrayPtr
(
argValues
,
sizeof
...(
Params
)));
}
...
...
@@ -346,7 +346,7 @@ template <typename... Params>
void
Log
::
reportFailedRecoverableSyscall
(
int
errorNumber
,
const
char
*
file
,
int
line
,
const
char
*
callText
,
const
char
*
macroArgs
,
Params
&&
...
params
)
{
Array
<
char
>
argValues
[
sizeof
...(
Params
)]
=
{
str
(
params
)...};
String
argValues
[
sizeof
...(
Params
)]
=
{
str
(
params
)...};
recoverableFailedSyscallInternal
(
file
,
line
,
callText
,
errorNumber
,
macroArgs
,
arrayPtr
(
argValues
,
sizeof
...(
Params
)));
}
...
...
@@ -355,7 +355,7 @@ template <typename... Params>
void
Log
::
reportFailedSyscall
(
int
errorNumber
,
const
char
*
file
,
int
line
,
const
char
*
callText
,
const
char
*
macroArgs
,
Params
&&
...
params
)
{
Array
<
char
>
argValues
[
sizeof
...(
Params
)]
=
{
str
(
params
)...};
String
argValues
[
sizeof
...(
Params
)]
=
{
str
(
params
)...};
fatalFailedSyscallInternal
(
file
,
line
,
callText
,
errorNumber
,
macroArgs
,
arrayPtr
(
argValues
,
sizeof
...(
Params
)));
}
...
...
@@ -363,7 +363,7 @@ void Log::reportFailedSyscall(
template
<
typename
...
Params
>
void
Log
::
addContextTo
(
Exception
&
exception
,
const
char
*
file
,
int
line
,
const
char
*
macroArgs
,
Params
&&
...
params
)
{
Array
<
char
>
argValues
[
sizeof
...(
Params
)]
=
{
str
(
params
)...};
String
argValues
[
sizeof
...(
Params
)]
=
{
str
(
params
)...};
addContextToInternal
(
exception
,
file
,
line
,
macroArgs
,
arrayPtr
(
argValues
,
sizeof
...(
Params
)));
}
...
...
c++/src/kj/memory.h
View file @
ad611c13
...
...
@@ -156,6 +156,17 @@ Own<T> heap(Params&&... params) {
return
Own
<
T
>
(
new
T
(
kj
::
fwd
<
Params
>
(
params
)...),
internal
::
HeapDisposer
<
T
>::
instance
);
}
template
<
typename
T
>
Own
<
Decay
<
T
>>
heap
(
T
&&
orig
)
{
// Allocate a copy (or move) of the argument on the heap.
//
// The purpose of this overload is to allow you to omit the template parameter as there is only
// one argument and the purpose is to copy it.
typedef
Decay
<
T
>
T2
;
return
Own
<
T2
>
(
new
T2
(
kj
::
fwd
<
T
>
(
orig
)),
internal
::
HeapDisposer
<
T2
>::
instance
);
}
// =======================================================================================
// Inline implementation details
...
...
c++/src/kj/string.c++
View file @
ad611c13
...
...
@@ -22,16 +22,20 @@
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "string.h"
#include "logging.h"
namespace
kj
{
String
::
String
(
const
char
*
value
)
:
content
(
heapArray
<
char
>
(
strlen
(
value
)
+
1
))
{
strcpy
(
content
.
begin
(),
value
);
String
heapString
(
size_t
size
)
{
char
*
buffer
=
internal
::
HeapArrayDisposer
::
allocate
<
char
>
(
size
+
1
);
buffer
[
size
]
=
'\0'
;
return
String
(
buffer
,
size
,
internal
::
HeapArrayDisposer
::
instance
);
}
String
::
String
(
const
char
*
value
,
size_t
length
)
:
content
(
heapArray
<
char
>
(
length
+
1
))
{
memcpy
(
content
.
begin
(),
value
,
length
);
content
[
length
]
=
'\0'
;
String
heapString
(
const
char
*
value
,
size_t
size
)
{
char
*
buffer
=
internal
::
HeapArrayDisposer
::
allocate
<
char
>
(
size
+
1
);
memcpy
(
buffer
,
value
,
size
+
1
);
return
String
(
buffer
,
size
,
internal
::
HeapArrayDisposer
::
instance
);
}
}
// namespace kj
c++/src/kj/string.h
View file @
ad611c13
...
...
@@ -29,39 +29,181 @@
namespace
kj
{
inline
ArrayPtr
<
const
char
>
stringPtr
(
const
char
*
text
)
{
return
arrayPtr
(
text
,
strlen
(
text
));
}
class
StringPtr
;
class
String
;
// =======================================================================================
// StringPtr -- A NUL-terminated ArrayPtr<const char> containing UTF-8 text.
//
// NUL bytes are allowed to appear before the end of the string. The only requirement is that
// a NUL byte appear immediately after the last byte of the content. This terminator byte is not
// counted in the string's size.
class
StringPtr
{
public
:
inline
StringPtr
()
:
content
(
""
,
1
)
{}
inline
StringPtr
(
decltype
(
nullptr
))
:
content
(
""
,
1
)
{}
inline
StringPtr
(
const
char
*
value
)
:
content
(
value
,
strlen
(
value
)
+
1
)
{}
inline
StringPtr
(
const
String
&
value
);
inline
operator
ArrayPtr
<
const
char
>
()
const
;
inline
ArrayPtr
<
const
char
>
asArray
()
const
;
// Result does not include NUL terminator.
inline
const
char
*
cStr
()
const
{
return
content
.
begin
();
}
// Returns NUL-terminated string.
inline
size_t
size
()
const
{
return
content
.
size
()
-
1
;
}
// Result does not include NUL terminator.
inline
char
operator
[](
size_t
index
)
const
{
return
content
[
index
];
}
inline
const
char
*
begin
()
const
{
return
content
.
begin
();
}
inline
const
char
*
end
()
const
{
return
content
.
end
()
-
1
;
}
inline
bool
operator
==
(
decltype
(
nullptr
))
const
{
return
content
.
size
()
<=
1
;
}
inline
bool
operator
!=
(
decltype
(
nullptr
))
const
{
return
content
.
size
()
>
1
;
}
inline
bool
operator
==
(
StringPtr
other
)
const
;
inline
bool
operator
!=
(
StringPtr
other
)
const
{
return
!
(
*
this
==
other
);
}
inline
StringPtr
slice
(
size_t
start
)
const
;
inline
ArrayPtr
<
const
char
>
slice
(
size_t
start
,
size_t
end
)
const
;
// A string slice is only NUL-terminated if it is a suffix, so slice() has a one-parameter
// version that assumes end = size().
private
:
inline
StringPtr
(
ArrayPtr
<
const
char
>
content
)
:
content
(
content
)
{}
ArrayPtr
<
const
char
>
content
;
};
inline
bool
operator
==
(
const
char
*
a
,
const
StringPtr
&
b
)
{
return
b
==
a
;
}
inline
bool
operator
!=
(
const
char
*
a
,
const
StringPtr
&
b
)
{
return
b
!=
a
;
}
// =======================================================================================
// String -- Just a NUL-terminated Array<char>.
// String -- A NUL-terminated Array<char> containing UTF-8 text.
//
// NUL bytes are allowed to appear before the end of the string. The only requirement is that
// a NUL byte appear immediately after the last byte of the content. This terminator byte is not
// counted in the string's size.
//
// To allocate a String, you must call kj::heapString(). We do not implement implicit copying to
// the heap because this hides potential inefficiency from the developer.
class
String
{
public
:
String
()
=
default
;
String
(
const
char
*
value
);
String
(
const
char
*
value
,
size_t
length
);
inline
String
(
decltype
(
nullptr
))
:
content
(
nullptr
)
{}
inline
String
(
char
*
value
,
size_t
size
,
const
ArrayDisposer
&
disposer
);
// Does not copy. `size` does not include NUL terminator, but `value` must be NUL-terminated.
inline
operator
ArrayPtr
<
char
>
();
inline
operator
ArrayPtr
<
const
char
>
()
const
;
inline
ArrayPtr
<
char
>
asArray
();
inline
ArrayPtr
<
const
char
>
asArray
()
const
;
inline
const
char
*
cStr
()
const
{
return
content
==
nullptr
?
""
:
content
.
begin
();
}
// Result does not include NUL terminator.
inline
const
char
*
cStr
()
const
;
inline
size_t
size
()
const
;
// Result does not include NUL terminator.
inline
char
operator
[](
size_t
index
)
const
;
inline
char
&
operator
[](
size_t
index
);
inline
size_t
size
()
const
{
return
content
==
nullptr
?
0
:
content
.
size
()
-
1
;
}
inline
char
*
begin
();
inline
char
*
end
();
inline
const
char
*
begin
()
const
;
inline
const
char
*
end
()
const
;
inline
char
*
begin
()
{
return
content
==
nullptr
?
nullptr
:
content
.
begin
();
}
inline
char
*
end
()
{
return
content
==
nullptr
?
nullptr
:
content
.
end
()
-
1
;
}
inline
const
char
*
begin
()
const
{
return
content
==
nullptr
?
nullptr
:
content
.
begin
();
}
inline
const
char
*
end
()
const
{
return
content
==
nullptr
?
nullptr
:
content
.
end
()
-
1
;
}
inline
bool
operator
==
(
decltype
(
nullptr
))
const
{
return
content
.
size
()
<=
1
;
}
inline
bool
operator
!=
(
decltype
(
nullptr
))
const
{
return
content
.
size
()
>
1
;
}
inline
bool
operator
==
(
StringPtr
other
)
const
{
return
StringPtr
(
*
this
)
==
other
;
}
inline
bool
operator
!=
(
StringPtr
other
)
const
{
return
!
(
*
this
==
other
);
}
private
:
Array
<
char
>
content
;
};
inline
bool
operator
==
(
const
char
*
a
,
const
String
&
b
)
{
return
b
==
a
;
}
inline
bool
operator
!=
(
const
char
*
a
,
const
String
&
b
)
{
return
b
!=
a
;
}
String
heapString
(
size_t
size
);
// Allocate a String of the given size on the heap, not including NUL terminator. The NUL
// terminator will be initialized automatically but the rest of the content is not initialized.
String
heapString
(
const
char
*
value
);
String
heapString
(
const
char
*
value
,
size_t
size
);
String
heapString
(
StringPtr
value
);
String
heapString
(
ArrayPtr
<
const
char
>
value
);
// Allocates a copy of the given value on the heap.
// =======================================================================================
// Inline implementation details.
inline
StringPtr
::
StringPtr
(
const
String
&
value
)
:
content
(
value
.
begin
(),
value
.
size
()
+
1
)
{}
inline
StringPtr
::
operator
ArrayPtr
<
const
char
>
()
const
{
return
content
.
slice
(
0
,
content
.
size
()
-
1
);
}
inline
ArrayPtr
<
const
char
>
StringPtr
::
asArray
()
const
{
return
content
.
slice
(
0
,
content
.
size
()
-
1
);
}
inline
bool
StringPtr
::
operator
==
(
StringPtr
other
)
const
{
return
content
.
size
()
==
other
.
content
.
size
()
&&
memcmp
(
content
.
begin
(),
other
.
content
.
begin
(),
content
.
size
()
-
1
)
==
0
;
}
inline
StringPtr
StringPtr
::
slice
(
size_t
start
)
const
{
return
StringPtr
(
content
.
slice
(
start
,
content
.
size
()));
}
inline
ArrayPtr
<
const
char
>
StringPtr
::
slice
(
size_t
start
,
size_t
end
)
const
{
return
content
.
slice
(
start
,
end
);
}
inline
String
::
operator
ArrayPtr
<
char
>
()
{
return
content
==
nullptr
?
ArrayPtr
<
char
>
(
nullptr
)
:
content
.
slice
(
0
,
content
.
size
()
-
1
);
}
inline
String
::
operator
ArrayPtr
<
const
char
>
()
const
{
return
content
==
nullptr
?
ArrayPtr
<
const
char
>
(
nullptr
)
:
content
.
slice
(
0
,
content
.
size
()
-
1
);
}
inline
ArrayPtr
<
char
>
String
::
asArray
()
{
return
content
==
nullptr
?
ArrayPtr
<
char
>
(
nullptr
)
:
content
.
slice
(
0
,
content
.
size
()
-
1
);
}
inline
ArrayPtr
<
const
char
>
String
::
asArray
()
const
{
return
content
==
nullptr
?
ArrayPtr
<
char
>
(
nullptr
)
:
content
.
slice
(
0
,
content
.
size
()
-
1
);
return
content
==
nullptr
?
ArrayPtr
<
const
char
>
(
nullptr
)
:
content
.
slice
(
0
,
content
.
size
()
-
1
);
}
inline
const
char
*
String
::
cStr
()
const
{
return
content
==
nullptr
?
""
:
content
.
begin
();
}
inline
size_t
String
::
size
()
const
{
return
content
==
nullptr
?
0
:
content
.
size
()
-
1
;
}
inline
char
String
::
operator
[](
size_t
index
)
const
{
return
content
[
index
];
}
inline
char
&
String
::
operator
[](
size_t
index
)
{
return
content
[
index
];
}
inline
char
*
String
::
begin
()
{
return
content
==
nullptr
?
nullptr
:
content
.
begin
();
}
inline
char
*
String
::
end
()
{
return
content
==
nullptr
?
nullptr
:
content
.
end
()
-
1
;
}
inline
const
char
*
String
::
begin
()
const
{
return
content
==
nullptr
?
nullptr
:
content
.
begin
();
}
inline
const
char
*
String
::
end
()
const
{
return
content
==
nullptr
?
nullptr
:
content
.
end
()
-
1
;
}
inline
String
::
String
(
char
*
value
,
size_t
size
,
const
ArrayDisposer
&
disposer
)
:
content
(
value
,
size
+
1
,
disposer
)
{
KJ_INLINE_DPRECOND
(
value
[
size
]
==
'\0'
,
"String must be NUL-terminated."
);
}
inline
String
heapString
(
const
char
*
value
)
{
return
heapString
(
value
,
strlen
(
value
));
}
inline
String
heapString
(
StringPtr
value
)
{
return
heapString
(
value
.
begin
(),
value
.
size
());
}
inline
String
heapString
(
ArrayPtr
<
const
char
>
value
)
{
return
heapString
(
value
.
begin
(),
value
.
size
());
}
}
// namespace kj
...
...
c++/src/kj/util-test.c++
View file @
ad611c13
...
...
@@ -21,7 +21,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define KJ_PRIVATE
#include "util.h"
#include <gtest/gtest.h>
#include <string>
...
...
@@ -30,15 +29,11 @@ namespace kj {
namespace
internal
{
namespace
{
std
::
string
arrayToStr
(
Array
<
char
>
arr
)
{
return
std
::
string
(
arr
.
begin
(),
arr
.
size
());
}
TEST
(
Util
,
Foo
)
{
EXPECT_EQ
(
"foobar"
,
arrayToStr
(
str
(
"foo"
,
"bar"
)
));
EXPECT_EQ
(
"1 2 3 4"
,
arrayToStr
(
str
(
1
,
" "
,
2u
,
" "
,
3l
,
" "
,
4ll
)
));
EXPECT_EQ
(
"1.5 foo 1e15 bar -3"
,
arrayToStr
(
str
(
1.5
f
,
" foo "
,
1e15
,
" bar "
,
-
3
)
));
EXPECT_EQ
(
"foo"
,
arrayToStr
(
str
(
'f'
,
'o'
,
'o'
)
));
EXPECT_EQ
(
"foobar"
,
str
(
"foo"
,
"bar"
));
EXPECT_EQ
(
"1 2 3 4"
,
str
(
1
,
" "
,
2u
,
" "
,
3l
,
" "
,
4ll
));
EXPECT_EQ
(
"1.5 foo 1e15 bar -3"
,
str
(
1.5
f
,
" foo "
,
1e15
,
" bar "
,
-
3
));
EXPECT_EQ
(
"foo"
,
str
(
'f'
,
'o'
,
'o'
));
}
}
// namespace
...
...
c++/src/kj/util.c++
View file @
ad611c13
...
...
@@ -21,7 +21,6 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define KJ_PRIVATE
#include "util.h"
#include "logging.h"
#include <stdio.h>
...
...
c++/src/kj/util.h
View file @
ad611c13
...
...
@@ -124,11 +124,10 @@ inline size_t sum(std::initializer_list<size_t> nums) {
return
result
;
}
template
<
typename
Element
>
Element
*
fill
(
Element
*
ptr
)
{
return
ptr
;
}
inline
char
*
fill
(
char
*
ptr
)
{
return
ptr
;
}
template
<
typename
Element
,
typename
First
,
typename
...
Rest
>
Element
*
fill
(
Element
*
__restrict__
target
,
const
First
&
first
,
Rest
&&
...
rest
)
{
template
<
typename
First
,
typename
...
Rest
>
char
*
fill
(
char
*
__restrict__
target
,
const
First
&
first
,
Rest
&&
...
rest
)
{
auto
i
=
first
.
begin
();
auto
end
=
first
.
end
();
while
(
i
!=
end
)
{
...
...
@@ -137,23 +136,17 @@ Element* fill(Element* __restrict__ target, const First& first, Rest&&... rest)
return
fill
(
target
,
std
::
forward
<
Rest
>
(
rest
)...);
}
template
<
typename
Element
,
typename
...
Params
>
Array
<
Element
>
concat
(
Params
&&
...
params
)
{
template
<
typename
...
Params
>
String
concat
(
Params
&&
...
params
)
{
// Concatenate a bunch of containers into a single Array. The containers can be anything that
// is iterable and whose elements can be converted to `Element`.
#ifdef __CDT_PARSER__
// Eclipse reports a bogus error on `size()`.
Array
<
Element
>
result
;
#else
Array
<
Element
>
result
=
heapArray
<
Element
>
(
sum
({
params
.
size
()...}));
#endif
String
result
=
heapString
(
sum
({
params
.
size
()...}));
fill
(
result
.
begin
(),
std
::
forward
<
Params
>
(
params
)...);
return
result
;
}
template
<
typename
Element
>
Array
<
Element
>
concat
(
Array
<
Element
>&&
arr
)
{
inline
String
concat
(
String
&&
arr
)
{
return
std
::
move
(
arr
);
}
...
...
@@ -177,6 +170,7 @@ struct Stringifier {
inline
ArrayPtr
<
const
char
>
operator
*
(
const
CappedArray
<
char
,
n
>&
s
)
const
{
return
s
;
}
inline
ArrayPtr
<
const
char
>
operator
*
(
const
char
*
s
)
const
{
return
arrayPtr
(
s
,
strlen
(
s
));
}
inline
ArrayPtr
<
const
char
>
operator
*
(
const
String
&
s
)
const
{
return
s
.
asArray
();
}
inline
ArrayPtr
<
const
char
>
operator
*
(
const
StringPtr
&
s
)
const
{
return
s
.
asArray
();
}
inline
FixedArray
<
char
,
1
>
operator
*
(
char
c
)
const
{
FixedArray
<
char
,
1
>
result
;
...
...
@@ -209,18 +203,18 @@ CappedArray<char, sizeof(unsigned long) * 4> hex(unsigned long i);
CappedArray
<
char
,
sizeof
(
unsigned
long
long
)
*
4
>
hex
(
unsigned
long
long
i
);
template
<
typename
...
Params
>
Array
<
char
>
str
(
Params
&&
...
params
)
{
String
str
(
Params
&&
...
params
)
{
// Magic function which builds a string from a bunch of arbitrary values. Example:
// str(1, " / ", 2, " = ", 0.5)
// returns:
// "1 / 2 = 0.5"
// To teach `str` how to stringify a type, see `Stringifier`.
return
concat
<
char
>
(
STR
*
std
::
forward
<
Params
>
(
params
)...);
return
concat
(
STR
*
std
::
forward
<
Params
>
(
params
)...);
}
template
<
typename
T
>
Array
<
char
>
strArray
(
T
&&
arr
,
const
char
*
delim
)
{
String
strArray
(
T
&&
arr
,
const
char
*
delim
)
{
size_t
delimLen
=
strlen
(
delim
);
KJ_STACK_ARRAY
(
decltype
(
STR
*
arr
[
0
]),
pieces
,
arr
.
size
(),
8
,
32
);
size_t
size
=
0
;
...
...
@@ -230,7 +224,7 @@ Array<char> strArray(T&& arr, const char* delim) {
size
+=
pieces
[
i
].
size
();
}
Array
<
char
>
result
=
heapArray
<
char
>
(
size
);
String
result
=
heapString
(
size
);
char
*
pos
=
result
.
begin
();
for
(
size_t
i
=
0
;
i
<
arr
.
size
();
i
++
)
{
if
(
i
>
0
)
{
...
...
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