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
178b5fdd
Commit
178b5fdd
authored
Mar 22, 2013
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Snappy serialization.
parent
2bcb6e69
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
658 additions
and
15 deletions
+658
-15
Makefile.ekam
c++/Makefile.ekam
+2
-2
benchmark-capnproto.c++
c++/src/capnproto/benchmark/benchmark-capnproto.c++
+0
-0
benchmark-protobuf.c++
c++/src/capnproto/benchmark/benchmark-protobuf.c++
+0
-0
message-test.c++
c++/src/capnproto/message-test.c++
+52
-0
serialize-snappy-test.c++
c++/src/capnproto/serialize-snappy-test.c++
+194
-0
serialize-snappy.c++
c++/src/capnproto/serialize-snappy.c++
+305
-0
serialize-snappy.h
c++/src/capnproto/serialize-snappy.h
+82
-0
serialize.c++
c++/src/capnproto/serialize.c++
+19
-5
serialize.h
c++/src/capnproto/serialize.h
+3
-7
type-safety.h
c++/src/capnproto/type-safety.h
+1
-1
No files found.
c++/Makefile.ekam
View file @
178b5fdd
...
...
@@ -4,13 +4,13 @@ all:
echo
"You probably accidentally told Eclipse to build. Stopping."
once
:
CXX
=
g++-4.7
CXXFLAGS
=
'-std=gnu++0x -O2 -Wall'
LIBS
=
'-lz -pthread'
ekam
-j6
CXX
=
g++-4.7
CXXFLAGS
=
'-std=gnu++0x -O2 -
DNDEBUG -
Wall'
LIBS
=
'-lz -pthread'
ekam
-j6
continuous
:
CXX
=
g++-4.7
CXXFLAGS
=
'-std=gnu++0x -g -Wall'
LIBS
=
'-lz -pthread'
ekam
-j6
-c
-n
:51315
continuous-opt
:
CXX
=
g++-4.7
CXXFLAGS
=
'-std=gnu++0x -O2 -Wall'
LIBS
=
'-lz -pthread'
ekam
-j6
-c
-n
:51315
CXX
=
g++-4.7
CXXFLAGS
=
'-std=gnu++0x -O2 -
DNDEBUG -
Wall'
LIBS
=
'-lz -pthread'
ekam
-j6
-c
-n
:51315
clean
:
rm
-rf
bin lib tmp
...
...
c++/src/capnproto/benchmark/benchmark-capnproto.c++
View file @
178b5fdd
This diff is collapsed.
Click to expand it.
c++/src/capnproto/benchmark/benchmark-protobuf.c++
View file @
178b5fdd
This diff is collapsed.
Click to expand it.
c++/src/capnproto/message-test.c++
0 → 100644
View file @
178b5fdd
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "message.h"
#include <gtest/gtest.h>
namespace
capnproto
{
namespace
internal
{
namespace
{
TEST
(
Message
,
MallocBuilderWithFirstSegment
)
{
word
scratch
[
16
];
MallocMessageBuilder
builder
(
arrayPtr
(
scratch
,
16
),
AllocationStrategy
::
FIXED_SIZE
);
ArrayPtr
<
word
>
segment
=
builder
.
allocateSegment
(
1
);
EXPECT_EQ
(
scratch
,
segment
.
begin
());
EXPECT_EQ
(
16u
,
segment
.
size
());
segment
=
builder
.
allocateSegment
(
1
);
EXPECT_NE
(
scratch
,
segment
.
begin
());
EXPECT_EQ
(
16u
,
segment
.
size
());
segment
=
builder
.
allocateSegment
(
1
);
EXPECT_NE
(
scratch
,
segment
.
begin
());
EXPECT_EQ
(
16u
,
segment
.
size
());
}
// TODO: More tests.
}
// namespace
}
// namespace internal
}
// namespace capnproto
c++/src/capnproto/serialize-snappy-test.c++
0 → 100644
View file @
178b5fdd
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "test.capnp.h"
#include "serialize-snappy.h"
#include <gtest/gtest.h>
#include <string>
#include <stdlib.h>
#include "test-util.h"
namespace
capnproto
{
namespace
internal
{
namespace
{
class
TestMessageBuilder
:
public
MallocMessageBuilder
{
// A MessageBuilder that tries to allocate an exact number of total segments, by allocating
// minimum-size segments until it reaches the number, then allocating one large segment to
// finish.
public
:
explicit
TestMessageBuilder
(
uint
desiredSegmentCount
)
:
MallocMessageBuilder
(
0
,
AllocationStrategy
::
FIXED_SIZE
),
desiredSegmentCount
(
desiredSegmentCount
)
{}
~
TestMessageBuilder
()
{
EXPECT_EQ
(
0u
,
desiredSegmentCount
);
}
ArrayPtr
<
word
>
allocateSegment
(
uint
minimumSize
)
override
{
if
(
desiredSegmentCount
<=
1
)
{
if
(
desiredSegmentCount
<
1
)
{
ADD_FAILURE
()
<<
"Allocated more segments than desired."
;
}
else
{
--
desiredSegmentCount
;
}
return
MallocMessageBuilder
::
allocateSegment
(
SUGGESTED_FIRST_SEGMENT_WORDS
);
}
else
{
--
desiredSegmentCount
;
return
MallocMessageBuilder
::
allocateSegment
(
minimumSize
);
}
}
private
:
uint
desiredSegmentCount
;
};
class
TestPipe
:
public
InputStream
,
public
OutputStream
{
public
:
TestPipe
(
bool
lazy
)
:
lazy
(
lazy
),
readPos
(
0
)
{}
~
TestPipe
()
{}
void
write
(
const
void
*
buffer
,
size_t
size
)
override
{
data
.
append
(
reinterpret_cast
<
const
char
*>
(
buffer
),
size
);
}
size_t
read
(
void
*
buffer
,
size_t
minBytes
,
size_t
maxBytes
)
override
{
CAPNPROTO_ASSERT
(
maxBytes
<=
data
.
size
()
-
readPos
,
"Overran end of stream."
);
size_t
amount
=
lazy
?
minBytes
:
maxBytes
;
memcpy
(
buffer
,
data
.
data
()
+
readPos
,
amount
);
readPos
+=
amount
;
return
amount
;
}
private
:
bool
lazy
;
std
::
string
data
;
std
::
string
::
size_type
readPos
;
};
TEST
(
Snappy
,
RoundTrip
)
{
TestMessageBuilder
builder
(
1
);
initTestMessage
(
builder
.
initRoot
<
TestAllTypes
>
());
TestPipe
pipe
(
false
);
writeSnappyMessage
(
pipe
,
builder
);
SnappyMessageReader
reader
(
pipe
);
checkTestMessage
(
reader
.
getRoot
<
TestAllTypes
>
());
}
TEST
(
Snappy
,
RoundTripScratchSpace
)
{
TestMessageBuilder
builder
(
1
);
initTestMessage
(
builder
.
initRoot
<
TestAllTypes
>
());
TestPipe
pipe
(
false
);
writeSnappyMessage
(
pipe
,
builder
);
word
scratch
[
1024
];
SnappyMessageReader
reader
(
pipe
,
ReaderOptions
(),
ArrayPtr
<
word
>
(
scratch
,
1024
));
checkTestMessage
(
reader
.
getRoot
<
TestAllTypes
>
());
}
TEST
(
Snappy
,
RoundTripLazy
)
{
TestMessageBuilder
builder
(
1
);
initTestMessage
(
builder
.
initRoot
<
TestAllTypes
>
());
TestPipe
pipe
(
true
);
writeSnappyMessage
(
pipe
,
builder
);
SnappyMessageReader
reader
(
pipe
);
checkTestMessage
(
reader
.
getRoot
<
TestAllTypes
>
());
}
TEST
(
Snappy
,
RoundTripOddSegmentCount
)
{
TestMessageBuilder
builder
(
7
);
initTestMessage
(
builder
.
initRoot
<
TestAllTypes
>
());
TestPipe
pipe
(
false
);
writeSnappyMessage
(
pipe
,
builder
);
SnappyMessageReader
reader
(
pipe
);
checkTestMessage
(
reader
.
getRoot
<
TestAllTypes
>
());
}
TEST
(
Snappy
,
RoundTripOddSegmentCountLazy
)
{
TestMessageBuilder
builder
(
7
);
initTestMessage
(
builder
.
initRoot
<
TestAllTypes
>
());
TestPipe
pipe
(
true
);
writeSnappyMessage
(
pipe
,
builder
);
SnappyMessageReader
reader
(
pipe
);
checkTestMessage
(
reader
.
getRoot
<
TestAllTypes
>
());
}
TEST
(
Snappy
,
RoundTripEvenSegmentCount
)
{
TestMessageBuilder
builder
(
10
);
initTestMessage
(
builder
.
initRoot
<
TestAllTypes
>
());
TestPipe
pipe
(
false
);
writeSnappyMessage
(
pipe
,
builder
);
SnappyMessageReader
reader
(
pipe
);
checkTestMessage
(
reader
.
getRoot
<
TestAllTypes
>
());
}
TEST
(
Snappy
,
RoundTripEvenSegmentCountLazy
)
{
TestMessageBuilder
builder
(
10
);
initTestMessage
(
builder
.
initRoot
<
TestAllTypes
>
());
TestPipe
pipe
(
true
);
writeSnappyMessage
(
pipe
,
builder
);
SnappyMessageReader
reader
(
pipe
);
checkTestMessage
(
reader
.
getRoot
<
TestAllTypes
>
());
}
TEST
(
Snappy
,
RoundTripTwoMessages
)
{
TestMessageBuilder
builder
(
1
);
initTestMessage
(
builder
.
initRoot
<
TestAllTypes
>
());
TestMessageBuilder
builder2
(
1
);
builder2
.
initRoot
<
TestAllTypes
>
().
setTextField
(
"Second message."
);
TestPipe
pipe
(
false
);
writeSnappyMessage
(
pipe
,
builder
);
writeSnappyMessage
(
pipe
,
builder2
);
{
SnappyMessageReader
reader
(
pipe
);
checkTestMessage
(
reader
.
getRoot
<
TestAllTypes
>
());
}
{
SnappyMessageReader
reader
(
pipe
);
EXPECT_EQ
(
"Second message."
,
reader
.
getRoot
<
TestAllTypes
>
().
getTextField
());
}
}
// TODO: Test error cases.
}
// namespace
}
// namespace internal
}
// namespace capnproto
c++/src/capnproto/serialize-snappy.c++
0 → 100644
View file @
178b5fdd
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "serialize-snappy.h"
#include "wire-format.h"
#include <snappy/snappy.h>
#include <snappy/snappy-sinksource.h>
#include <vector>
namespace
capnproto
{
namespace
{
class
InputStreamSource
:
public
snappy
::
Source
{
public
:
inline
InputStreamSource
(
InputStream
&
inputStream
,
size_t
available
)
:
inputStream
(
inputStream
),
available
(
available
),
pos
(
nullptr
),
end
(
nullptr
)
{
// Read at least 10 bytes (or all available bytes if less than 10), and at most the whole buffer
// (unless less is available).
size_t
firstSize
=
inputStream
.
read
(
buffer
,
std
::
min
<
size_t
>
(
available
,
10
),
std
::
min
<
size_t
>
(
available
,
sizeof
(
buffer
)));
CAPNPROTO_ASSERT
(
snappy
::
GetUncompressedLength
(
buffer
,
firstSize
,
&
uncompressedSize
),
"Invalid snappy-compressed data."
);
pos
=
buffer
;
end
=
pos
+
firstSize
;
}
inline
~
InputStreamSource
()
{};
inline
size_t
getUncompressedSize
()
{
return
uncompressedSize
;
}
// implements snappy::Source ---------------------------------------
size_t
Available
()
const
override
{
return
available
;
}
const
char
*
Peek
(
size_t
*
len
)
override
{
*
len
=
end
-
pos
;
return
pos
;
}
void
Skip
(
size_t
n
)
override
{
pos
+=
n
;
available
-=
n
;
if
(
pos
==
end
&&
available
>
0
)
{
// Read more from the input.
pos
=
buffer
;
end
=
pos
+
inputStream
.
read
(
buffer
,
1
,
std
::
min
<
size_t
>
(
available
,
sizeof
(
buffer
)));
}
}
private
:
InputStream
&
inputStream
;
size_t
available
;
size_t
uncompressedSize
;
char
*
pos
;
char
*
end
;
char
buffer
[
8192
];
};
}
// namespcae
SnappyMessageReader
::
SnappyMessageReader
(
InputStream
&
inputStream
,
ReaderOptions
options
,
ArrayPtr
<
word
>
scratchSpace
)
:
MessageReader
(
options
),
inputStream
(
inputStream
)
{
internal
::
WireValue
<
uint32_t
>
wireCompressedSize
;
inputStream
.
read
(
&
wireCompressedSize
,
sizeof
(
wireCompressedSize
));
size_t
compressedSize
=
wireCompressedSize
.
get
();
InputStreamSource
source
(
inputStream
,
compressedSize
);
CAPNPROTO_ASSERT
(
source
.
getUncompressedSize
()
%
sizeof
(
word
)
==
0
,
"Uncompressed size was not a whole number of words."
);
size_t
uncompressedWords
=
source
.
getUncompressedSize
()
/
sizeof
(
word
);
if
(
scratchSpace
.
size
()
<
uncompressedWords
)
{
space
=
newArray
<
word
>
(
uncompressedWords
);
scratchSpace
=
space
;
}
CAPNPROTO_ASSERT
(
snappy
::
RawUncompress
(
&
source
,
reinterpret_cast
<
char
*>
(
scratchSpace
.
begin
())),
"Snappy decompression failed."
);
new
(
&
underlyingReader
)
FlatArrayMessageReader
(
scratchSpace
,
options
);
}
SnappyMessageReader
::~
SnappyMessageReader
()
{
underlyingReader
.
~
FlatArrayMessageReader
();
}
ArrayPtr
<
const
word
>
SnappyMessageReader
::
getSegment
(
uint
id
)
{
return
underlyingReader
.
getSegment
(
id
);
}
SnappyFdMessageReader
::~
SnappyFdMessageReader
()
{}
// =======================================================================================
namespace
{
class
SegmentArraySource
:
public
snappy
::
Source
{
public
:
SegmentArraySource
(
ArrayPtr
<
const
ArrayPtr
<
const
byte
>>
pieces
)
:
pieces
(
pieces
),
offset
(
0
),
available
(
0
)
{
for
(
auto
&
piece
:
pieces
)
{
available
+=
piece
.
size
();
}
Skip
(
0
);
// Skip leading zero-sized pieces, if any.
}
~
SegmentArraySource
()
{}
// implements snappy::Source ---------------------------------------
size_t
Available
()
const
override
{
return
available
;
}
const
char
*
Peek
(
size_t
*
len
)
override
{
if
(
pieces
.
size
()
==
0
)
{
*
len
=
0
;
return
nullptr
;
}
else
{
*
len
=
pieces
[
0
].
size
()
-
offset
;
return
reinterpret_cast
<
const
char
*>
(
pieces
[
0
].
begin
())
+
offset
;
}
}
void
Skip
(
size_t
n
)
override
{
available
-=
n
;
while
(
pieces
.
size
()
>
0
&&
n
>=
pieces
[
0
].
size
()
-
offset
)
{
n
-=
pieces
[
0
].
size
()
-
offset
;
offset
=
0
;
pieces
=
pieces
.
slice
(
1
,
pieces
.
size
());
}
offset
+=
n
;
}
private
:
ArrayPtr
<
const
ArrayPtr
<
const
byte
>>
pieces
;
size_t
offset
;
size_t
available
;
};
class
AccumulatingSink
:
public
snappy
::
Sink
{
public
:
AccumulatingSink
()
:
pos
(
firstPiece
+
sizeof
(
compressedSize
)),
end
(
firstPiece
+
sizeof
(
firstPiece
)),
firstEnd
(
firstPiece
)
{}
~
AccumulatingSink
()
{}
void
writeTo
(
size_t
size
,
OutputStream
&
output
)
{
finalizePiece
();
compressedSize
.
set
(
size
);
ArrayPtr
<
const
byte
>
pieces
[
morePieces
.
size
()
+
1
];
pieces
[
0
]
=
arrayPtr
(
reinterpret_cast
<
byte
*>
(
firstPiece
),
reinterpret_cast
<
byte
*>
(
firstEnd
));
for
(
uint
i
=
0
;
i
<
morePieces
.
size
();
i
++
)
{
auto
&
piece
=
morePieces
[
i
];
pieces
[
i
+
1
]
=
arrayPtr
(
reinterpret_cast
<
byte
*>
(
piece
.
start
.
get
()),
reinterpret_cast
<
byte
*>
(
piece
.
end
));
}
output
.
write
(
arrayPtr
(
pieces
,
morePieces
.
size
()
+
1
));
}
// implements snappy::Sink -----------------------------------------
void
Append
(
const
char
*
bytes
,
size_t
n
)
override
{
if
(
bytes
==
pos
)
{
pos
+=
n
;
}
else
{
size_t
a
=
available
();
if
(
n
>
a
)
{
memcpy
(
pos
,
bytes
,
a
);
bytes
+=
a
;
addPiece
(
n
);
}
memcpy
(
pos
,
bytes
,
n
);
pos
+=
n
;
}
}
char
*
GetAppendBuffer
(
size_t
length
,
char
*
scratch
)
override
{
if
(
length
>
available
())
{
addPiece
(
length
);
}
return
pos
;
}
private
:
char
*
pos
;
char
*
end
;
// Stand and end point of the current available space.
char
*
firstEnd
;
// End point of the used portion of the first piece.
struct
Piece
{
std
::
unique_ptr
<
char
[]
>
start
;
// Start point of the piece.
char
*
end
;
// End point of the used portion of the piece.
Piece
()
=
default
;
Piece
(
std
::
unique_ptr
<
char
[]
>
start
,
char
*
end
)
:
start
(
std
::
move
(
start
)),
end
(
end
)
{}
};
std
::
vector
<
Piece
>
morePieces
;
union
{
internal
::
WireValue
<
uint32_t
>
compressedSize
;
char
firstPiece
[
8192
];
};
inline
size_t
available
()
{
return
end
-
pos
;
}
inline
void
finalizePiece
()
{
if
(
morePieces
.
empty
())
{
firstEnd
=
pos
;
}
else
{
morePieces
.
back
().
end
=
pos
;
}
}
void
addPiece
(
size_t
minSize
)
{
finalizePiece
();
std
::
unique_ptr
<
char
[]
>
newPiece
(
new
char
[
minSize
]);
pos
=
newPiece
.
get
();
end
=
pos
+
minSize
;
morePieces
.
emplace_back
(
std
::
move
(
newPiece
),
pos
);
}
};
class
SnappyOutputStream
:
public
OutputStream
{
public
:
SnappyOutputStream
(
OutputStream
&
output
)
:
output
(
output
),
sawWrite
(
false
)
{}
// implements OutputStream -----------------------------------------
void
write
(
const
void
*
buffer
,
size_t
size
)
override
{
CAPNPROTO_ASSERT
(
false
,
"writeMessage() was not expected to call this."
);
}
void
write
(
ArrayPtr
<
const
ArrayPtr
<
const
byte
>>
pieces
)
{
CAPNPROTO_ASSERT
(
!
sawWrite
,
"writeMessage() was expected to issue exactly one write."
);
sawWrite
=
true
;
SegmentArraySource
source
(
pieces
);
AccumulatingSink
sink
;
size_t
size
=
snappy
::
Compress
(
&
source
,
&
sink
);
sink
.
writeTo
(
size
,
output
);
}
private
:
OutputStream
&
output
;
bool
sawWrite
;
};
}
// namespace
void
writeSnappyMessage
(
OutputStream
&
output
,
ArrayPtr
<
const
ArrayPtr
<
const
word
>>
segments
)
{
SnappyOutputStream
snappyOutput
(
output
);
writeMessage
(
snappyOutput
,
segments
);
}
void
writeSnappyMessageToFd
(
int
fd
,
ArrayPtr
<
const
ArrayPtr
<
const
word
>>
segments
)
{
FdOutputStream
output
(
fd
);
writeSnappyMessage
(
output
,
segments
);
}
}
// namespace capnproto
c++/src/capnproto/serialize-snappy.h
0 → 100644
View file @
178b5fdd
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef CAPNPROTO_SERIALIZE_SNAPPY_H_
#define CAPNPROTO_SERIALIZE_SNAPPY_H_
#include "serialize.h"
namespace
capnproto
{
class
SnappyMessageReader
:
public
MessageReader
{
public
:
SnappyMessageReader
(
InputStream
&
inputStream
,
ReaderOptions
options
=
ReaderOptions
(),
ArrayPtr
<
word
>
scratchSpace
=
nullptr
);
~
SnappyMessageReader
();
ArrayPtr
<
const
word
>
getSegment
(
uint
id
)
override
;
private
:
InputStream
&
inputStream
;
Array
<
word
>
space
;
union
{
FlatArrayMessageReader
underlyingReader
;
};
};
class
SnappyFdMessageReader
:
private
FdInputStream
,
public
SnappyMessageReader
{
public
:
SnappyFdMessageReader
(
int
fd
,
ReaderOptions
options
=
ReaderOptions
(),
ArrayPtr
<
word
>
scratchSpace
=
nullptr
)
:
FdInputStream
(
fd
),
SnappyMessageReader
(
*
this
,
options
,
scratchSpace
)
{}
// Read message from a file descriptor, without taking ownership of the descriptor.
SnappyFdMessageReader
(
AutoCloseFd
fd
,
ReaderOptions
options
=
ReaderOptions
(),
ArrayPtr
<
word
>
scratchSpace
=
nullptr
)
:
FdInputStream
(
move
(
fd
)),
SnappyMessageReader
(
*
this
,
options
,
scratchSpace
)
{}
// Read a message from a file descriptor, taking ownership of the descriptor.
~
SnappyFdMessageReader
();
};
void
writeSnappyMessage
(
OutputStream
&
output
,
MessageBuilder
&
builder
);
void
writeSnappyMessage
(
OutputStream
&
output
,
ArrayPtr
<
const
ArrayPtr
<
const
word
>>
segments
);
void
writeSnappyMessageToFd
(
int
fd
,
MessageBuilder
&
builder
);
void
writeSnappyMessageToFd
(
int
fd
,
ArrayPtr
<
const
ArrayPtr
<
const
word
>>
segments
);
// =======================================================================================
// inline stuff
inline
void
writeSnappyMessage
(
OutputStream
&
output
,
MessageBuilder
&
builder
)
{
writeSnappyMessage
(
output
,
builder
.
getSegmentsForOutput
());
}
inline
void
writeSnappyMessageToFd
(
int
fd
,
MessageBuilder
&
builder
)
{
writeSnappyMessageToFd
(
fd
,
builder
.
getSegmentsForOutput
());
}
}
// namespace capnproto
#endif // CAPNPROTO_SERIALIZE_SNAPPY_H_
c++/src/capnproto/serialize.c++
View file @
178b5fdd
...
...
@@ -152,7 +152,7 @@ InputStreamMessageReader::InputStreamMessageReader(
:
MessageReader
(
options
),
inputStream
(
inputStream
),
readPos
(
nullptr
)
{
internal
::
WireValue
<
uint32_t
>
firstWord
[
2
];
inputStream
.
read
(
firstWord
,
sizeof
(
firstWord
)
,
sizeof
(
firstWord
)
);
inputStream
.
read
(
firstWord
,
sizeof
(
firstWord
));
uint
segmentCount
=
firstWord
[
0
].
get
();
uint
segment0Size
=
segmentCount
==
0
?
0
:
firstWord
[
1
].
get
();
...
...
@@ -162,7 +162,7 @@ InputStreamMessageReader::InputStreamMessageReader(
// Read sizes for all segments except the first. Include padding if necessary.
internal
::
WireValue
<
uint32_t
>
moreSizes
[
segmentCount
&
~
1
];
if
(
segmentCount
>
1
)
{
inputStream
.
read
(
moreSizes
,
sizeof
(
moreSizes
)
,
sizeof
(
moreSizes
)
);
inputStream
.
read
(
moreSizes
,
sizeof
(
moreSizes
));
for
(
uint
i
=
0
;
i
<
segmentCount
-
1
;
i
++
)
{
totalWords
+=
moreSizes
[
i
].
get
();
}
...
...
@@ -188,7 +188,7 @@ InputStreamMessageReader::InputStreamMessageReader(
}
if
(
segmentCount
==
1
)
{
inputStream
.
read
(
scratchSpace
.
begin
(),
totalWords
*
sizeof
(
word
)
,
totalWords
*
sizeof
(
word
)
);
inputStream
.
read
(
scratchSpace
.
begin
(),
totalWords
*
sizeof
(
word
));
}
else
if
(
segmentCount
>
1
)
{
readPos
=
reinterpret_cast
<
byte
*>
(
scratchSpace
.
begin
());
readPos
+=
inputStream
.
read
(
readPos
,
segment0Size
*
sizeof
(
word
),
totalWords
*
sizeof
(
word
));
...
...
@@ -200,7 +200,16 @@ InputStreamMessageReader::~InputStreamMessageReader() {
// Note that lazy reads only happen when we have multiple segments, so moreSegments.back() is
// valid.
const
byte
*
allEnd
=
reinterpret_cast
<
const
byte
*>
(
moreSegments
.
back
().
end
());
inputStream
.
skip
(
allEnd
-
readPos
);
if
(
std
::
uncaught_exception
())
{
try
{
inputStream
.
skip
(
allEnd
-
readPos
);
}
catch
(...)
{
// TODO: Devise some way to report secondary errors during unwind.
}
}
else
{
inputStream
.
skip
(
allEnd
-
readPos
);
}
}
}
...
...
@@ -328,7 +337,12 @@ void FdOutputStream::write(const void* buffer, size_t size) {
ssize_t
n
=
::
write
(
fd
,
pos
,
size
);
if
(
n
<=
0
)
{
CAPNPROTO_ASSERT
(
n
<
0
,
"write() returned zero."
);
throw
OsException
(
"write"
,
errno
);
int
error
=
errno
;
if
(
error
==
EINTR
)
{
continue
;
}
else
{
throw
OsException
(
"write"
,
error
);
}
}
pos
+=
n
;
size
-=
n
;
...
...
c++/src/capnproto/serialize.h
View file @
178b5fdd
...
...
@@ -91,6 +91,9 @@ public:
// message. If it can't even reach minBytes, it MUST throw an exception, as the caller is not
// expected to understand how to deal with partial reads.
inline
void
read
(
void
*
buffer
,
size_t
bytes
)
{
read
(
buffer
,
bytes
,
bytes
);
}
// Convenience method for reading an exact number of bytes.
virtual
void
skip
(
size_t
bytes
);
// Skips past the given number of bytes, discarding them. The default implementation read()s
// into a scratch buffer.
...
...
@@ -210,18 +213,11 @@ public:
ArrayPtr
<
word
>
scratchSpace
=
nullptr
)
:
FdInputStream
(
fd
),
InputStreamMessageReader
(
*
this
,
options
,
scratchSpace
)
{}
// Read message from a file descriptor, without taking ownership of the descriptor.
//
// Since this version implies that the caller intends to read more data from the fd later on, the
// default is to read the entire message eagerly in the constructor, so that the fd will be
// deterministically positioned just past the end of the message.
StreamFdMessageReader
(
AutoCloseFd
fd
,
ReaderOptions
options
=
ReaderOptions
(),
ArrayPtr
<
word
>
scratchSpace
=
nullptr
)
:
FdInputStream
(
move
(
fd
)),
InputStreamMessageReader
(
*
this
,
options
,
scratchSpace
)
{}
// Read a message from a file descriptor, taking ownership of the descriptor.
//
// Since this version implies that the caller does not intend to read any more data from the fd,
// the default is to read the message lazily as needed.
~
StreamFdMessageReader
();
};
...
...
c++/src/capnproto/type-safety.h
View file @
178b5fdd
...
...
@@ -116,7 +116,7 @@ class Array {
public
:
inline
Array
()
:
ptr
(
nullptr
),
size_
(
0
)
{}
inline
Array
(
std
::
nullptr_t
)
:
ptr
(
nullptr
),
size_
(
0
)
{}
inline
Array
(
Array
&&
other
)
:
ptr
(
other
.
ptr
),
size_
(
other
.
size_
)
{
inline
Array
(
Array
&&
other
)
noexcept
:
ptr
(
other
.
ptr
),
size_
(
other
.
size_
)
{
other
.
ptr
=
nullptr
;
other
.
size_
=
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