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
265400d6
Commit
265400d6
authored
Jun 03, 2017
by
Kenton Varda
Committed by
GitHub
Jun 03, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #492 from sandstorm-io/tweaks
Tweaks and bugfixes
parents
e92255a0
3e0aae88
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
84 additions
and
41 deletions
+84
-41
array-test.c++
c++/src/kj/array-test.c++
+7
-0
array.h
c++/src/kj/array.h
+23
-0
async-io.h
c++/src/kj/async-io.h
+3
-2
http.c++
c++/src/kj/compat/http.c++
+2
-2
url.c++
c++/src/kj/compat/url.c++
+25
-33
url.h
c++/src/kj/compat/url.h
+11
-4
vector.h
c++/src/kj/vector.h
+13
-0
No files found.
c++/src/kj/array-test.c++
View file @
265400d6
...
@@ -378,5 +378,12 @@ TEST(Array, ReleaseAsBytesOrChars) {
...
@@ -378,5 +378,12 @@ TEST(Array, ReleaseAsBytesOrChars) {
}
}
}
}
#if __cplusplus > 201402L
KJ_TEST
(
"kj::arr()"
)
{
kj
::
Array
<
kj
::
String
>
array
=
kj
::
arr
(
kj
::
str
(
"foo"
),
kj
::
str
(
123
));
KJ_EXPECT
(
array
==
kj
::
ArrayPtr
<
const
kj
::
StringPtr
>
({
"foo"
,
"123"
}));
}
#endif
}
// namespace
}
// namespace
}
// namespace kj
}
// namespace kj
c++/src/kj/array.h
View file @
265400d6
...
@@ -177,6 +177,11 @@ public:
...
@@ -177,6 +177,11 @@ public:
inline
T
&
front
()
{
return
*
ptr
;
}
inline
T
&
front
()
{
return
*
ptr
;
}
inline
T
&
back
()
{
return
*
(
ptr
+
size_
-
1
);
}
inline
T
&
back
()
{
return
*
(
ptr
+
size_
-
1
);
}
template
<
typename
U
>
inline
bool
operator
==
(
const
U
&
other
)
const
{
return
asPtr
()
==
other
;
}
template
<
typename
U
>
inline
bool
operator
!=
(
const
U
&
other
)
const
{
return
asPtr
()
!=
other
;
}
inline
ArrayPtr
<
T
>
slice
(
size_t
start
,
size_t
end
)
{
inline
ArrayPtr
<
T
>
slice
(
size_t
start
,
size_t
end
)
{
KJ_IREQUIRE
(
start
<=
end
&&
end
<=
size_
,
"Out-of-bounds Array::slice()."
);
KJ_IREQUIRE
(
start
<=
end
&&
end
<=
size_
,
"Out-of-bounds Array::slice()."
);
return
ArrayPtr
<
T
>
(
ptr
+
start
,
end
-
start
);
return
ArrayPtr
<
T
>
(
ptr
+
start
,
end
-
start
);
...
@@ -249,6 +254,8 @@ private:
...
@@ -249,6 +254,8 @@ private:
template
<
typename
U
>
template
<
typename
U
>
friend
class
Array
;
friend
class
Array
;
template
<
typename
U
>
friend
class
ArrayBuilder
;
};
};
static_assert
(
!
canMemcpy
<
Array
<
char
>>
(),
"canMemcpy<>() is broken"
);
static_assert
(
!
canMemcpy
<
Array
<
char
>>
(),
"canMemcpy<>() is broken"
);
...
@@ -321,6 +328,13 @@ public:
...
@@ -321,6 +328,13 @@ public:
other
.
pos
=
nullptr
;
other
.
pos
=
nullptr
;
other
.
endPtr
=
nullptr
;
other
.
endPtr
=
nullptr
;
}
}
ArrayBuilder
(
Array
<
T
>&&
other
)
:
ptr
(
other
.
ptr
),
pos
(
other
.
ptr
+
other
.
size_
),
endPtr
(
pos
),
disposer
(
other
.
disposer
)
{
// Create an already-full ArrayBuilder from an Array of the same type. This constructor
// primarily exists to enable Vector<T> to be constructed from Array<T>.
other
.
ptr
=
nullptr
;
other
.
size_
=
0
;
}
KJ_DISALLOW_COPY
(
ArrayBuilder
);
KJ_DISALLOW_COPY
(
ArrayBuilder
);
inline
~
ArrayBuilder
()
noexcept
(
false
)
{
dispose
();
}
inline
~
ArrayBuilder
()
noexcept
(
false
)
{
dispose
();
}
...
@@ -808,6 +822,15 @@ inline Array<T> heapArray(std::initializer_list<T> init) {
...
@@ -808,6 +822,15 @@ inline Array<T> heapArray(std::initializer_list<T> init) {
return
heapArray
<
T
>
(
init
.
begin
(),
init
.
end
());
return
heapArray
<
T
>
(
init
.
begin
(),
init
.
end
());
}
}
#if __cplusplus > 201402L
template
<
typename
T
,
typename
...
Params
>
inline
Array
<
Decay
<
T
>>
arr
(
T
&&
param1
,
Params
&&
...
params
)
{
ArrayBuilder
<
Decay
<
T
>>
builder
=
heapArrayBuilder
<
Decay
<
T
>>
(
sizeof
...(
params
)
+
1
);
(
builder
.
add
(
kj
::
fwd
<
T
>
(
param1
)),
...
,
builder
.
add
(
kj
::
fwd
<
Params
>
(
params
)));
return
builder
.
finish
();
}
#endif
}
// namespace kj
}
// namespace kj
#endif // KJ_ARRAY_H_
#endif // KJ_ARRAY_H_
c++/src/kj/async-io.h
View file @
265400d6
...
@@ -86,8 +86,9 @@ class AsyncOutputStream {
...
@@ -86,8 +86,9 @@ class AsyncOutputStream {
// Asynchronous equivalent of OutputStream (from io.h).
// Asynchronous equivalent of OutputStream (from io.h).
public
:
public
:
virtual
Promise
<
void
>
write
(
const
void
*
buffer
,
size_t
size
)
=
0
;
virtual
Promise
<
void
>
write
(
const
void
*
buffer
,
size_t
size
)
KJ_WARN_UNUSED_RESULT
=
0
;
virtual
Promise
<
void
>
write
(
ArrayPtr
<
const
ArrayPtr
<
const
byte
>>
pieces
)
=
0
;
virtual
Promise
<
void
>
write
(
ArrayPtr
<
const
ArrayPtr
<
const
byte
>>
pieces
)
KJ_WARN_UNUSED_RESULT
=
0
;
virtual
Maybe
<
Promise
<
uint64_t
>>
tryPumpFrom
(
virtual
Maybe
<
Promise
<
uint64_t
>>
tryPumpFrom
(
AsyncInputStream
&
input
,
uint64_t
amount
=
kj
::
maxValue
);
AsyncInputStream
&
input
,
uint64_t
amount
=
kj
::
maxValue
);
...
...
c++/src/kj/compat/http.c++
View file @
265400d6
...
@@ -1297,7 +1297,7 @@ public:
...
@@ -1297,7 +1297,7 @@ public:
KJ_REQUIRE
(
inBody
)
{
return
kj
::
READY_NOW
;
}
KJ_REQUIRE
(
inBody
)
{
return
kj
::
READY_NOW
;
}
auto
fork
=
writeQueue
.
then
([
this
,
buffer
,
size
]()
{
auto
fork
=
writeQueue
.
then
([
this
,
buffer
,
size
]()
{
inner
.
write
(
buffer
,
size
);
return
inner
.
write
(
buffer
,
size
);
}).
fork
();
}).
fork
();
writeQueue
=
fork
.
addBranch
();
writeQueue
=
fork
.
addBranch
();
...
@@ -1308,7 +1308,7 @@ public:
...
@@ -1308,7 +1308,7 @@ public:
KJ_REQUIRE
(
inBody
)
{
return
kj
::
READY_NOW
;
}
KJ_REQUIRE
(
inBody
)
{
return
kj
::
READY_NOW
;
}
auto
fork
=
writeQueue
.
then
([
this
,
pieces
]()
{
auto
fork
=
writeQueue
.
then
([
this
,
pieces
]()
{
inner
.
write
(
pieces
);
return
inner
.
write
(
pieces
);
}).
fork
();
}).
fork
();
writeQueue
=
fork
.
addBranch
();
writeQueue
=
fork
.
addBranch
();
...
...
c++/src/kj/compat/url.c++
View file @
265400d6
...
@@ -171,42 +171,36 @@ Maybe<Url> Url::tryParse(StringPtr text, Context context) {
...
@@ -171,42 +171,36 @@ Maybe<Url> Url::tryParse(StringPtr text, Context context) {
}
}
}
}
{
while
(
text
.
startsWith
(
"/"
))
{
Vector
<
String
>
path
;
text
=
text
.
slice
(
1
);
while
(
text
.
startsWith
(
"/"
))
{
auto
part
=
split
(
text
,
END_PATH_PART
);
text
=
text
.
slice
(
1
);
if
(
part
.
size
()
==
2
&&
part
[
0
]
==
'.'
&&
part
[
1
]
==
'.'
)
{
auto
part
=
split
(
text
,
END_PATH_PART
);
if
(
result
.
path
.
size
()
!=
0
)
{
if
(
part
.
size
()
==
2
&&
part
[
0
]
==
'.'
&&
part
[
1
]
==
'.'
)
{
result
.
path
.
removeLast
();
if
(
path
.
size
()
!=
0
)
{
path
.
removeLast
();
}
result
.
hasTrailingSlash
=
true
;
}
else
if
(
part
.
size
()
==
0
||
(
part
.
size
()
==
1
&&
part
[
0
]
==
'.'
))
{
// Collapse consecutive slashes and "/./".
result
.
hasTrailingSlash
=
true
;
}
else
{
path
.
add
(
percentDecode
(
part
,
err
));
result
.
hasTrailingSlash
=
false
;
}
}
result
.
hasTrailingSlash
=
true
;
}
else
if
(
part
.
size
()
==
0
||
(
part
.
size
()
==
1
&&
part
[
0
]
==
'.'
))
{
// Collapse consecutive slashes and "/./".
result
.
hasTrailingSlash
=
true
;
}
else
{
result
.
path
.
add
(
percentDecode
(
part
,
err
));
result
.
hasTrailingSlash
=
false
;
}
}
result
.
path
=
path
.
releaseAsArray
();
}
}
if
(
text
.
startsWith
(
"?"
))
{
if
(
text
.
startsWith
(
"?"
))
{
Vector
<
QueryParam
>
params
;
do
{
do
{
text
=
text
.
slice
(
1
);
text
=
text
.
slice
(
1
);
auto
part
=
split
(
text
,
END_QUERY_PART
);
auto
part
=
split
(
text
,
END_QUERY_PART
);
if
(
part
.
size
()
>
0
)
{
if
(
part
.
size
()
>
0
)
{
KJ_IF_MAYBE
(
key
,
trySplit
(
part
,
'='
))
{
KJ_IF_MAYBE
(
key
,
trySplit
(
part
,
'='
))
{
params
.
add
(
QueryParam
{
percentDecode
(
*
key
,
err
),
percentDecode
(
part
,
err
)
});
result
.
query
.
add
(
QueryParam
{
percentDecode
(
*
key
,
err
),
percentDecode
(
part
,
err
)
});
}
else
{
}
else
{
params
.
add
(
QueryParam
{
percentDecode
(
part
,
err
),
nullptr
});
result
.
query
.
add
(
QueryParam
{
percentDecode
(
part
,
err
),
nullptr
});
}
}
}
}
}
while
(
text
.
startsWith
(
"&"
));
}
while
(
text
.
startsWith
(
"&"
));
result
.
query
=
params
.
releaseAsArray
();
}
}
if
(
text
.
startsWith
(
"#"
))
{
if
(
text
.
startsWith
(
"#"
))
{
...
@@ -293,7 +287,6 @@ Maybe<Url> Url::tryParseRelative(StringPtr text) const {
...
@@ -293,7 +287,6 @@ Maybe<Url> Url::tryParseRelative(StringPtr text) const {
bool
hadNewPath
=
text
.
size
()
>
0
&&
text
[
0
]
!=
'?'
&&
text
[
0
]
!=
'#'
;
bool
hadNewPath
=
text
.
size
()
>
0
&&
text
[
0
]
!=
'?'
&&
text
[
0
]
!=
'#'
;
if
(
hadNewPath
)
{
if
(
hadNewPath
)
{
// There's a new path.
// There's a new path.
Vector
<
String
>
path
(
this
->
path
.
size
());
if
(
text
[
0
]
==
'/'
)
{
if
(
text
[
0
]
==
'/'
)
{
// New path is absolute, so don't copy the old path.
// New path is absolute, so don't copy the old path.
...
@@ -303,9 +296,7 @@ Maybe<Url> Url::tryParseRelative(StringPtr text) const {
...
@@ -303,9 +296,7 @@ Maybe<Url> Url::tryParseRelative(StringPtr text) const {
// New path is relative, so start from the old path, dropping everything after the last
// New path is relative, so start from the old path, dropping everything after the last
// slash.
// slash.
auto
slice
=
this
->
path
.
slice
(
0
,
this
->
path
.
size
()
-
(
this
->
hasTrailingSlash
?
0
:
1
));
auto
slice
=
this
->
path
.
slice
(
0
,
this
->
path
.
size
()
-
(
this
->
hasTrailingSlash
?
0
:
1
));
for
(
auto
&
part
:
slice
)
{
result
.
path
=
KJ_MAP
(
part
,
slice
)
{
return
kj
::
str
(
part
);
};
path
.
add
(
kj
::
str
(
part
));
}
result
.
hasTrailingSlash
=
true
;
result
.
hasTrailingSlash
=
true
;
}
}
...
@@ -313,22 +304,20 @@ Maybe<Url> Url::tryParseRelative(StringPtr text) const {
...
@@ -313,22 +304,20 @@ Maybe<Url> Url::tryParseRelative(StringPtr text) const {
auto
part
=
split
(
text
,
END_PATH_PART
);
auto
part
=
split
(
text
,
END_PATH_PART
);
if
(
part
.
size
()
==
2
&&
part
[
0
]
==
'.'
&&
part
[
1
]
==
'.'
)
{
if
(
part
.
size
()
==
2
&&
part
[
0
]
==
'.'
&&
part
[
1
]
==
'.'
)
{
if
(
path
.
size
()
!=
0
)
{
if
(
path
.
size
()
!=
0
)
{
path
.
removeLast
();
result
.
path
.
removeLast
();
}
}
result
.
hasTrailingSlash
=
true
;
result
.
hasTrailingSlash
=
true
;
}
else
if
(
part
.
size
()
==
0
||
(
part
.
size
()
==
1
&&
part
[
0
]
==
'.'
))
{
}
else
if
(
part
.
size
()
==
0
||
(
part
.
size
()
==
1
&&
part
[
0
]
==
'.'
))
{
// Collapse consecutive slashes and "/./".
// Collapse consecutive slashes and "/./".
result
.
hasTrailingSlash
=
true
;
result
.
hasTrailingSlash
=
true
;
}
else
{
}
else
{
path
.
add
(
percentDecode
(
part
,
err
));
result
.
path
.
add
(
percentDecode
(
part
,
err
));
result
.
hasTrailingSlash
=
false
;
result
.
hasTrailingSlash
=
false
;
}
}
if
(
!
text
.
startsWith
(
"/"
))
break
;
if
(
!
text
.
startsWith
(
"/"
))
break
;
text
=
text
.
slice
(
1
);
text
=
text
.
slice
(
1
);
}
}
result
.
path
=
path
.
releaseAsArray
();
}
else
if
(
!
hadNewAuthority
)
{
}
else
if
(
!
hadNewAuthority
)
{
// copy path
// copy path
result
.
path
=
KJ_MAP
(
part
,
this
->
path
)
{
return
kj
::
str
(
part
);
};
result
.
path
=
KJ_MAP
(
part
,
this
->
path
)
{
return
kj
::
str
(
part
);
};
...
@@ -336,20 +325,18 @@ Maybe<Url> Url::tryParseRelative(StringPtr text) const {
...
@@ -336,20 +325,18 @@ Maybe<Url> Url::tryParseRelative(StringPtr text) const {
}
}
if
(
text
.
startsWith
(
"?"
))
{
if
(
text
.
startsWith
(
"?"
))
{
Vector
<
QueryParam
>
params
;
do
{
do
{
text
=
text
.
slice
(
1
);
text
=
text
.
slice
(
1
);
auto
part
=
split
(
text
,
END_QUERY_PART
);
auto
part
=
split
(
text
,
END_QUERY_PART
);
if
(
part
.
size
()
>
0
)
{
if
(
part
.
size
()
>
0
)
{
KJ_IF_MAYBE
(
key
,
trySplit
(
part
,
'='
))
{
KJ_IF_MAYBE
(
key
,
trySplit
(
part
,
'='
))
{
params
.
add
(
QueryParam
{
percentDecode
(
*
key
,
err
),
percentDecode
(
part
,
err
)
});
result
.
query
.
add
(
QueryParam
{
percentDecode
(
*
key
,
err
),
percentDecode
(
part
,
err
)
});
}
else
{
}
else
{
params
.
add
(
QueryParam
{
percentDecode
(
part
,
err
),
nullptr
});
result
.
query
.
add
(
QueryParam
{
percentDecode
(
part
,
err
),
nullptr
});
}
}
}
}
}
while
(
text
.
startsWith
(
"&"
));
}
while
(
text
.
startsWith
(
"&"
));
result
.
query
=
params
.
releaseAsArray
();
}
else
if
(
!
hadNewAuthority
&&
!
hadNewPath
)
{
}
else
if
(
!
hadNewAuthority
&&
!
hadNewPath
)
{
// copy query
// copy query
result
.
query
=
KJ_MAP
(
param
,
this
->
query
)
{
result
.
query
=
KJ_MAP
(
param
,
this
->
query
)
{
...
@@ -404,6 +391,11 @@ String Url::toString(Context context) const {
...
@@ -404,6 +391,11 @@ String Url::toString(Context context) const {
}
}
for
(
auto
&
pathPart
:
path
)
{
for
(
auto
&
pathPart
:
path
)
{
// Protect against path injection.
KJ_REQUIRE
(
pathPart
!=
""
&&
pathPart
!=
"."
&&
pathPart
!=
".."
,
"invalid name in URL path"
,
*
this
)
{
continue
;
}
chars
.
add
(
'/'
);
chars
.
add
(
'/'
);
chars
.
addAll
(
encodeUriComponent
(
pathPart
));
chars
.
addAll
(
encodeUriComponent
(
pathPart
));
}
}
...
...
c++/src/kj/compat/url.h
View file @
265400d6
...
@@ -23,6 +23,7 @@
...
@@ -23,6 +23,7 @@
#define KJ_COMPAT_URL_H_
#define KJ_COMPAT_URL_H_
#include <kj/string.h>
#include <kj/string.h>
#include <kj/vector.h>
#include <inttypes.h>
#include <inttypes.h>
namespace
kj
{
namespace
kj
{
...
@@ -48,16 +49,20 @@ struct Url {
...
@@ -48,16 +49,20 @@ struct Url {
// network address parsing functions already accept addresses containing port numbers, and
// network address parsing functions already accept addresses containing port numbers, and
// because most web standards don't actually want to separate host and port.
// because most web standards don't actually want to separate host and port.
Array
<
String
>
path
;
Vector
<
String
>
path
;
bool
hasTrailingSlash
=
false
;
bool
hasTrailingSlash
=
false
;
// Path, split on '/' characters. Note that the individual components of `path` could contain
// Path, split on '/' characters. Note that the individual components of `path` could contain
// '/' characters if they were percent-encoded in the original URL.
// '/' characters if they were percent-encoded in the original URL.
//
// No component of the path is allowed to be "", ".", nor ".."; if such components are present,
// toString() will throw. Note that parse() and parseRelative() automatically resolve such
// components.
struct
QueryParam
{
struct
QueryParam
{
String
name
;
String
name
;
String
value
;
String
value
;
};
};
Array
<
QueryParam
>
query
;
Vector
<
QueryParam
>
query
;
// Query, e.g. from "?key=value&key2=value2". If a component of the query contains no '=' sign,
// Query, e.g. from "?key=value&key2=value2". If a component of the query contains no '=' sign,
// it will be parsed as a key with an empty value.
// it will be parsed as a key with an empty value.
...
@@ -71,12 +76,14 @@ struct Url {
...
@@ -71,12 +76,14 @@ struct Url {
~
Url
()
noexcept
(
false
);
~
Url
()
noexcept
(
false
);
Url
&
operator
=
(
Url
&&
)
=
default
;
Url
&
operator
=
(
Url
&&
)
=
default
;
inline
Url
(
String
&&
scheme
,
Maybe
<
UserInfo
>&&
userInfo
,
String
&&
host
,
Array
<
String
>&&
path
,
#if __cplusplus < 201402L
bool
hasTrailingSlash
,
Array
<
QueryParam
>&&
query
,
Maybe
<
String
>&&
fragment
)
inline
Url
(
String
&&
scheme
,
Maybe
<
UserInfo
>&&
userInfo
,
String
&&
host
,
Vector
<
String
>&&
path
,
bool
hasTrailingSlash
,
Vector
<
QueryParam
>&&
query
,
Maybe
<
String
>&&
fragment
)
:
scheme
(
kj
::
mv
(
scheme
)),
userInfo
(
kj
::
mv
(
userInfo
)),
host
(
kj
::
mv
(
host
)),
path
(
kj
::
mv
(
path
)),
:
scheme
(
kj
::
mv
(
scheme
)),
userInfo
(
kj
::
mv
(
userInfo
)),
host
(
kj
::
mv
(
host
)),
path
(
kj
::
mv
(
path
)),
hasTrailingSlash
(
hasTrailingSlash
),
query
(
kj
::
mv
(
query
)),
fragment
(
kj
::
mv
(
fragment
))
{}
hasTrailingSlash
(
hasTrailingSlash
),
query
(
kj
::
mv
(
query
)),
fragment
(
kj
::
mv
(
fragment
))
{}
// TODO(cleanup): This constructor is only here to support brace initialization in C++11. It
// TODO(cleanup): This constructor is only here to support brace initialization in C++11. It
// should be removed once we upgrade to C++14.
// should be removed once we upgrade to C++14.
#endif
Url
clone
()
const
;
Url
clone
()
const
;
...
...
c++/src/kj/vector.h
View file @
265400d6
...
@@ -43,6 +43,7 @@ class Vector {
...
@@ -43,6 +43,7 @@ class Vector {
public
:
public
:
inline
Vector
()
=
default
;
inline
Vector
()
=
default
;
inline
explicit
Vector
(
size_t
capacity
)
:
builder
(
heapArrayBuilder
<
T
>
(
capacity
))
{}
inline
explicit
Vector
(
size_t
capacity
)
:
builder
(
heapArrayBuilder
<
T
>
(
capacity
))
{}
inline
Vector
(
Array
<
T
>&&
array
)
:
builder
(
kj
::
mv
(
array
))
{}
inline
operator
ArrayPtr
<
T
>
()
{
return
builder
;
}
inline
operator
ArrayPtr
<
T
>
()
{
return
builder
;
}
inline
operator
ArrayPtr
<
const
T
>
()
const
{
return
builder
;
}
inline
operator
ArrayPtr
<
const
T
>
()
const
{
return
builder
;
}
...
@@ -71,6 +72,18 @@ public:
...
@@ -71,6 +72,18 @@ public:
return
builder
.
finish
();
return
builder
.
finish
();
}
}
template
<
typename
U
>
inline
bool
operator
==
(
const
U
&
other
)
const
{
return
asPtr
()
==
other
;
}
template
<
typename
U
>
inline
bool
operator
!=
(
const
U
&
other
)
const
{
return
asPtr
()
!=
other
;
}
inline
ArrayPtr
<
T
>
slice
(
size_t
start
,
size_t
end
)
{
return
asPtr
().
slice
(
start
,
end
);
}
inline
ArrayPtr
<
const
T
>
slice
(
size_t
start
,
size_t
end
)
const
{
return
asPtr
().
slice
(
start
,
end
);
}
template
<
typename
...
Params
>
template
<
typename
...
Params
>
inline
T
&
add
(
Params
&&
...
params
)
{
inline
T
&
add
(
Params
&&
...
params
)
{
if
(
builder
.
isFull
())
grow
();
if
(
builder
.
isFull
())
grow
();
...
...
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