Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
Actor Framework
Commits
8933b78f
Commit
8933b78f
authored
Aug 08, 2018
by
Matthias Vallentin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make container streambuffer more flexible
parent
7d7b6d23
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
124 additions
and
58 deletions
+124
-58
libcaf_core/caf/streambuf.hpp
libcaf_core/caf/streambuf.hpp
+107
-58
libcaf_core/test/streambuf.cpp
libcaf_core/test/streambuf.cpp
+17
-0
No files found.
libcaf_core/caf/streambuf.hpp
View file @
8933b78f
...
...
@@ -34,6 +34,11 @@ namespace caf {
/// The base class for all stream buffer implementations.
template
<
class
CharT
=
char
,
class
Traits
=
std
::
char_traits
<
CharT
>
>
class
stream_buffer
:
public
std
::
basic_streambuf
<
CharT
,
Traits
>
{
public:
using
base
=
std
::
basic_streambuf
<
CharT
,
Traits
>
;
using
pos_type
=
typename
base
::
pos_type
;
using
off_type
=
typename
base
::
off_type
;
protected:
/// The standard only defines pbump(int), which can overflow on 64-bit
/// architectures. All stream buffer implementations should therefore use
...
...
@@ -71,6 +76,65 @@ protected:
safe_gbump
(
std
::
streamsize
n
)
{
this
->
gbump
(
static_cast
<
int
>
(
n
));
}
pos_type
default_seekoff
(
off_type
off
,
std
::
ios_base
::
seekdir
dir
,
std
::
ios_base
::
openmode
which
)
{
auto
new_off
=
pos_type
(
off_type
(
-
1
));
auto
get
=
(
which
&
std
::
ios_base
::
in
)
==
std
::
ios_base
::
in
;
auto
put
=
(
which
&
std
::
ios_base
::
out
)
==
std
::
ios_base
::
out
;
if
(
!
(
get
||
put
))
return
new_off
;
// nothing to do
if
(
get
)
{
switch
(
dir
)
{
default:
return
pos_type
(
off_type
(
-
1
));
case
std
:
:
ios_base
::
beg
:
new_off
=
0
;
break
;
case
std
:
:
ios_base
::
cur
:
new_off
=
this
->
gptr
()
-
this
->
eback
();
break
;
case
std
:
:
ios_base
::
end
:
new_off
=
this
->
egptr
()
-
this
->
eback
();
break
;
}
new_off
+=
off
;
this
->
setg
(
this
->
eback
(),
this
->
eback
()
+
new_off
,
this
->
egptr
());
}
if
(
put
)
{
switch
(
dir
)
{
default:
return
pos_type
(
off_type
(
-
1
));
case
std
:
:
ios_base
::
beg
:
new_off
=
0
;
break
;
case
std
:
:
ios_base
::
cur
:
new_off
=
this
->
pptr
()
-
this
->
pbase
();
break
;
case
std
:
:
ios_base
::
end
:
new_off
=
this
->
egptr
()
-
this
->
pbase
();
break
;
}
new_off
+=
off
;
this
->
setp
(
this
->
pbase
(),
this
->
epptr
());
safe_pbump
(
new_off
);
}
return
new_off
;
}
pos_type
default_seekpos
(
pos_type
pos
,
std
::
ios_base
::
openmode
which
)
{
auto
get
=
(
which
&
std
::
ios_base
::
in
)
==
std
::
ios_base
::
in
;
auto
put
=
(
which
&
std
::
ios_base
::
out
)
==
std
::
ios_base
::
out
;
if
(
!
(
get
||
put
))
return
pos_type
(
off_type
(
-
1
));
// nothing to do
if
(
get
)
this
->
setg
(
this
->
eback
(),
this
->
eback
()
+
pos
,
this
->
egptr
());
if
(
put
)
{
this
->
setp
(
this
->
pbase
(),
this
->
epptr
());
safe_pbump
(
pos
);
}
return
pos
;
}
};
/// A streambuffer abstraction over a fixed array of bytes. This streambuffer
...
...
@@ -142,63 +206,12 @@ protected:
pos_type
seekpos
(
pos_type
pos
,
std
::
ios_base
::
openmode
which
=
std
::
ios_base
::
in
|
std
::
ios_base
::
out
)
override
{
auto
get
=
(
which
&
std
::
ios_base
::
in
)
==
std
::
ios_base
::
in
;
auto
put
=
(
which
&
std
::
ios_base
::
out
)
==
std
::
ios_base
::
out
;
if
(
!
(
get
||
put
))
return
pos_type
(
off_type
(
-
1
));
// nothing to do
if
(
get
)
this
->
setg
(
this
->
eback
(),
this
->
eback
()
+
pos
,
this
->
egptr
());
if
(
put
)
{
this
->
setp
(
this
->
pbase
(),
this
->
epptr
());
this
->
safe_pbump
(
pos
);
}
return
pos
;
return
this
->
default_seekpos
(
pos
,
which
);
}
pos_type
seekoff
(
off_type
off
,
std
::
ios_base
::
seekdir
dir
,
pos_type
seekoff
(
off_type
off
,
std
::
ios_base
::
seekdir
dir
,
std
::
ios_base
::
openmode
which
)
override
{
auto
new_off
=
pos_type
(
off_type
(
-
1
));
auto
get
=
(
which
&
std
::
ios_base
::
in
)
==
std
::
ios_base
::
in
;
auto
put
=
(
which
&
std
::
ios_base
::
out
)
==
std
::
ios_base
::
out
;
if
(
!
(
get
||
put
))
return
new_off
;
// nothing to do
if
(
get
)
{
switch
(
dir
)
{
default:
return
pos_type
(
off_type
(
-
1
));
case
std
:
:
ios_base
::
beg
:
new_off
=
0
;
break
;
case
std
:
:
ios_base
::
cur
:
new_off
=
this
->
gptr
()
-
this
->
eback
();
break
;
case
std
:
:
ios_base
::
end
:
new_off
=
this
->
egptr
()
-
this
->
eback
();
break
;
}
new_off
+=
off
;
this
->
setg
(
this
->
eback
(),
this
->
eback
()
+
new_off
,
this
->
egptr
());
}
if
(
put
)
{
switch
(
dir
)
{
default:
return
pos_type
(
off_type
(
-
1
));
case
std
:
:
ios_base
::
beg
:
new_off
=
0
;
break
;
case
std
:
:
ios_base
::
cur
:
new_off
=
this
->
pptr
()
-
this
->
pbase
();
break
;
case
std
:
:
ios_base
::
end
:
new_off
=
this
->
egptr
()
-
this
->
pbase
();
break
;
}
new_off
+=
off
;
this
->
setp
(
this
->
pbase
(),
this
->
epptr
());
this
->
safe_pbump
(
new_off
);
}
return
new_off
;
return
this
->
default_seekoff
(
off
,
dir
,
which
);
}
// -- put area -------------------------------------------------------------
...
...
@@ -252,9 +265,10 @@ public:
>::
type
>
containerbuf
(
Container
&
c
)
:
container_
(
c
)
{
this
->
setg
(
const_cast
<
char_type
*>
(
c
.
data
()),
const_cast
<
char_type
*>
(
c
.
data
()),
const_cast
<
char_type
*>
(
c
.
data
())
+
c
.
size
());
// We use a const_cast because C++11 doesn't provide a non-const data()
// overload. Using std::data(c) would be the right way to write this.
auto
data
=
const_cast
<
char_type
*>
(
c
.
data
());
setbuf
(
data
,
static_cast
<
std
::
streamsize
>
(
c
.
size
()));
}
// See note in arraybuf(arraybuf&&).
...
...
@@ -279,13 +293,46 @@ public:
return
traits_type
::
to_int_type
(
*
this
->
gptr
());
}
// Hides base-class implementation to simplify single-character insert.
// Hides base-class implementation to simplify single-character insert
// without a put area.
int_type
sputc
(
char_type
c
)
{
container_
.
push_back
(
c
);
return
c
;
}
// Hides base-class implementation to simplify multi-character insert without
// a put area.
std
::
streamsize
sputn
(
const
char_type
*
s
,
std
::
streamsize
n
)
{
return
xsputn
(
s
,
n
);
}
protected:
// -- positioning ----------------------------------------------------------
base
*
setbuf
(
char_type
*
s
,
std
::
streamsize
n
)
override
{
this
->
setg
(
s
,
s
,
s
+
n
);
return
this
;
}
pos_type
seekpos
(
pos_type
pos
,
std
::
ios_base
::
openmode
which
=
std
::
ios_base
::
in
|
std
::
ios_base
::
out
)
override
{
// We only have a get area, so no put area (= out) operations.
if
((
which
&
std
::
ios_base
::
out
)
==
std
::
ios_base
::
out
)
return
pos_type
(
off_type
(
-
1
));
return
this
->
default_seekpos
(
pos
,
which
);
}
pos_type
seekoff
(
off_type
off
,
std
::
ios_base
::
seekdir
dir
,
std
::
ios_base
::
openmode
which
)
override
{
// We only have a get area, so no put area (= out) operations.
if
((
which
&
std
::
ios_base
::
out
)
==
std
::
ios_base
::
out
)
return
pos_type
(
off_type
(
-
1
));
return
this
->
default_seekoff
(
off
,
dir
,
which
);
}
// -- get area -------------------------------------------------------------
// We can't get obtain more characters on underflow, so we only optimize
// multi-character sequential reads.
std
::
streamsize
xsgetn
(
char_type
*
s
,
std
::
streamsize
n
)
override
{
...
...
@@ -297,6 +344,8 @@ protected:
return
actual
;
}
// -- put area -------------------------------------------------------------
// Should never get called, because there is always space in the buffer.
// (But just in case, it does the same thing as sputc.)
int_type
overflow
(
int_type
c
=
traits_type
::
eof
())
final
{
...
...
libcaf_core/test/streambuf.cpp
View file @
8933b78f
...
...
@@ -125,3 +125,20 @@ CAF_TEST(containerbuf) {
CAF_CHECK_EQUAL
(
buf
.
size
(),
data
.
size
());
CAF_CHECK
(
std
::
equal
(
buf
.
begin
(),
buf
.
end
(),
data
.
begin
()
/*, data.end() */
));
}
CAF_TEST
(
containerbuf_reset_get_area
)
{
std
::
string
str
{
"foobar"
};
std
::
vector
<
char
>
buf
;
vectorbuf
vb
{
buf
};
// We can always write to the underlying buffer; no put area needed.
auto
n
=
vb
.
sputn
(
str
.
data
(),
str
.
size
());
CAF_REQUIRE_EQUAL
(
n
,
6
);
// Readjust the get area.
CAF_REQUIRE_EQUAL
(
buf
.
size
(),
6u
);
vb
.
pubsetbuf
(
buf
.
data
()
+
3
,
buf
.
size
()
-
3
);
// Now read from a new get area into a buffer.
char
bar
[
3
];
n
=
vb
.
sgetn
(
bar
,
3
);
CAF_CHECK_EQUAL
(
n
,
3
);
CAF_CHECK_EQUAL
(
std
::
string
(
bar
,
3
),
"bar"
);
}
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