Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mpd
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
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Мажукин
mpd
Commits
f89da178
Commit
f89da178
authored
Aug 06, 2014
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
util/DynamicFifoBuffer: move code to new base class ForeignFifoBuffer
parent
ea26da0b
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
244 additions
and
115 deletions
+244
-115
Makefile.am
Makefile.am
+1
-0
DynamicFifoBuffer.hxx
src/util/DynamicFifoBuffer.hxx
+24
-115
ForeignFifoBuffer.hxx
src/util/ForeignFifoBuffer.hxx
+219
-0
No files found.
Makefile.am
View file @
f89da178
...
@@ -373,6 +373,7 @@ libutil_a_SOURCES = \
...
@@ -373,6 +373,7 @@ libutil_a_SOURCES = \
src/util/Manual.hxx
\
src/util/Manual.hxx
\
src/util/RefCount.hxx
\
src/util/RefCount.hxx
\
src/util/FifoBuffer.hxx
\
src/util/FifoBuffer.hxx
\
src/util/ForeignFifoBuffer.hxx
\
src/util/DynamicFifoBuffer.hxx
\
src/util/DynamicFifoBuffer.hxx
\
src/util/ConstBuffer.hxx
\
src/util/ConstBuffer.hxx
\
src/util/WritableBuffer.hxx
\
src/util/WritableBuffer.hxx
\
...
...
src/util/DynamicFifoBuffer.hxx
View file @
f89da178
...
@@ -30,14 +30,7 @@
...
@@ -30,14 +30,7 @@
#ifndef FIFO_BUFFER_HPP
#ifndef FIFO_BUFFER_HPP
#define FIFO_BUFFER_HPP
#define FIFO_BUFFER_HPP
#include "WritableBuffer.hxx"
#include "ForeignFifoBuffer.hxx"
#include <utility>
#include <algorithm>
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
/**
/**
* A first-in-first-out buffer: you can append data at the end, and
* A first-in-first-out buffer: you can append data at the end, and
...
@@ -45,94 +38,50 @@
...
@@ -45,94 +38,50 @@
* buffer as needed. It is not thread safe.
* buffer as needed. It is not thread safe.
*/
*/
template
<
typename
T
>
template
<
typename
T
>
class
DynamicFifoBuffer
{
class
DynamicFifoBuffer
:
protected
ForeignFifoBuffer
<
T
>
{
public
:
public
:
typedef
size_t
size_type
;
typedef
typename
ForeignFifoBuffer
<
T
>::
size_type
size_type
;
typedef
WritableBuffer
<
T
>
Range
;
typedef
typename
ForeignFifoBuffer
<
T
>::
pointer_type
pointer_type
;
typedef
typename
Range
::
pointer_type
pointer_type
;
typedef
typename
ForeignFifoBuffer
<
T
>::
const_pointer_type
const_pointer_type
;
typedef
typename
Range
::
const_pointer_type
const_pointer_type
;
protected
:
size_type
head
,
tail
,
capacity
;
T
*
data
;
public
:
explicit
DynamicFifoBuffer
(
size_type
_capacity
)
explicit
DynamicFifoBuffer
(
size_type
_capacity
)
:
head
(
0
),
tail
(
0
),
capacity
(
_capacity
),
:
ForeignFifoBuffer
<
T
>
(
new
T
[
_capacity
],
_capacity
)
{}
data
(
new
T
[
capacity
])
{}
~
DynamicFifoBuffer
()
{
~
DynamicFifoBuffer
()
{
delete
[]
data
;
delete
[]
GetBuffer
()
;
}
}
DynamicFifoBuffer
(
const
DynamicFifoBuffer
&
)
=
delete
;
DynamicFifoBuffer
(
const
DynamicFifoBuffer
&
)
=
delete
;
size_type
GetCapacity
()
{
using
ForeignFifoBuffer
<
T
>::
IsEmpty
;
return
capacity
;
using
ForeignFifoBuffer
<
T
>::
IsFull
;
}
using
ForeignFifoBuffer
<
T
>::
Read
;
using
ForeignFifoBuffer
<
T
>::
Consume
;
using
ForeignFifoBuffer
<
T
>::
Write
;
using
ForeignFifoBuffer
<
T
>::
Append
;
void
Grow
(
size_type
new_capacity
)
{
void
Grow
(
size_type
new_capacity
)
{
assert
(
new_capacity
>
capacity
);
assert
(
new_capacity
>
GetCapacity
()
);
T
*
old_data
=
GetBuffer
();
T
*
new_data
=
new
T
[
new_capacity
];
T
*
new_data
=
new
T
[
new_capacity
];
std
::
move
(
data
+
head
,
data
+
tail
,
new_data
);
ForeignFifoBuffer
<
T
>::
MoveBuffer
(
new_data
,
new_capacity
);
delete
[]
data
;
delete
[]
old_data
;
data
=
new_data
;
capacity
=
new_capacity
;
tail
-=
head
;
head
=
0
;
}
void
Clear
()
{
head
=
tail
=
0
;
}
bool
IsEmpty
()
const
{
return
head
==
tail
;
}
bool
IsFull
()
const
{
return
head
==
0
&&
tail
==
capacity
;
}
/**
* Prepares writing. Returns a buffer range which may be written.
* When you are finished, call append().
*/
Range
Write
()
{
Shift
();
return
Range
(
data
+
tail
,
capacity
-
tail
);
}
/**
* Expands the tail of the buffer, after data has been written to
* the buffer returned by write().
*/
void
Append
(
size_type
n
)
{
assert
(
tail
<=
capacity
);
assert
(
n
<=
capacity
);
assert
(
tail
+
n
<=
capacity
);
tail
+=
n
;
}
}
void
WantWrite
(
size_type
n
)
{
void
WantWrite
(
size_type
n
)
{
if
(
tail
+
n
<=
capacity
)
if
(
ForeignFifoBuffer
<
T
>::
WantWrite
(
n
)
)
/*
enough space after the tail
*/
/*
we already have enough space
*/
return
;
return
;
const
size_type
in_use
=
tail
-
head
;
const
size_type
in_use
=
Read
().
size
;
const
size_type
required_capacity
=
in_use
+
n
;
const
size_type
required_capacity
=
in_use
+
n
;
if
(
capacity
>=
required_capacity
)
{
size_type
new_capacity
=
GetCapacity
();
Shift
();
}
else
{
size_type
new_capacity
=
capacity
;
do
{
do
{
new_capacity
<<=
1
;
new_capacity
<<=
1
;
}
while
(
new_capacity
<
required_capacity
);
}
while
(
new_capacity
<
required_capacity
);
Grow
(
new_capacity
);
Grow
(
new_capacity
);
}
}
}
/**
/**
* Write data to the buffer, growing it as needed. Returns a
* Write data to the buffer, growing it as needed. Returns a
...
@@ -140,7 +89,7 @@ public:
...
@@ -140,7 +89,7 @@ public:
*/
*/
pointer_type
Write
(
size_type
n
)
{
pointer_type
Write
(
size_type
n
)
{
WantWrite
(
n
);
WantWrite
(
n
);
return
data
+
tail
;
return
Write
().
data
;
}
}
/**
/**
...
@@ -151,49 +100,9 @@ public:
...
@@ -151,49 +100,9 @@ public:
Append
(
n
);
Append
(
n
);
}
}
/**
* Return a buffer range which may be read. The buffer pointer is
* writable, to allow modifications while parsing.
*/
Range
Read
()
{
return
Range
(
data
+
head
,
tail
-
head
);
}
/**
* Marks a chunk as consumed.
*/
void
Consume
(
size_type
n
)
{
assert
(
tail
<=
capacity
);
assert
(
head
<=
tail
);
assert
(
n
<=
tail
);
assert
(
head
+
n
<=
tail
);
head
+=
n
;
}
size_type
Read
(
pointer_type
p
,
size_type
n
)
{
auto
range
=
Read
();
if
(
n
>
range
.
size
)
n
=
range
.
size
;
std
::
copy_n
(
range
.
data
,
n
,
p
);
Consume
(
n
);
return
n
;
}
protected
:
protected
:
void
Shift
()
{
using
ForeignFifoBuffer
<
T
>::
GetBuffer
;
if
(
head
==
0
)
using
ForeignFifoBuffer
<
T
>::
GetCapacity
;
return
;
assert
(
head
<=
capacity
);
assert
(
tail
<=
capacity
);
assert
(
tail
>=
head
);
std
::
move
(
data
+
head
,
data
+
tail
,
data
);
tail
-=
head
;
head
=
0
;
}
};
};
#endif
#endif
src/util/ForeignFifoBuffer.hxx
0 → 100644
View file @
f89da178
/*
* Copyright (C) 2003-2014 Max Kellermann <max@duempel.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - 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
* FOUNDATION 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 FOREIGN_FIFO_BUFFER_HXX
#define FOREIGN_FIFO_BUFFER_HXX
#include "WritableBuffer.hxx"
#include <utility>
#include <algorithm>
#include <cstddef>
#include <assert.h>
/**
* A first-in-first-out buffer: you can append data at the end, and
* read data from the beginning. This class automatically shifts the
* buffer as needed. It is not thread safe.
*
* This class does not manage buffer memory. It will not allocate or
* free any memory, it only manages the contents of an existing buffer
* given to the constructor.
*/
template
<
typename
T
>
class
ForeignFifoBuffer
{
public
:
typedef
size_t
size_type
;
typedef
WritableBuffer
<
T
>
Range
;
typedef
typename
Range
::
pointer_type
pointer_type
;
typedef
typename
Range
::
const_pointer_type
const_pointer_type
;
protected
:
size_type
head
,
tail
,
capacity
;
T
*
data
;
public
:
explicit
constexpr
ForeignFifoBuffer
(
std
::
nullptr_t
n
)
:
head
(
0
),
tail
(
0
),
capacity
(
0
),
data
(
n
)
{}
constexpr
ForeignFifoBuffer
(
T
*
_data
,
size_type
_capacity
)
:
head
(
0
),
tail
(
0
),
capacity
(
_capacity
),
data
(
_data
)
{}
ForeignFifoBuffer
(
ForeignFifoBuffer
&&
src
)
:
head
(
src
.
head
),
tail
(
src
.
tail
),
capacity
(
src
.
capacity
),
data
(
src
.
data
)
{
src
.
SetNull
();
}
ForeignFifoBuffer
&
operator
=
(
ForeignFifoBuffer
&&
src
)
{
head
=
src
.
head
;
tail
=
src
.
tail
;
capacity
=
src
.
capacity
;
data
=
src
.
data
;
src
.
SetNull
();
return
*
this
;
}
constexpr
bool
IsNull
()
const
{
return
data
==
nullptr
;
}
constexpr
bool
IsDefined
()
const
{
return
!
IsNull
();
}
T
*
GetBuffer
()
{
return
data
;
}
constexpr
size_type
GetCapacity
()
const
{
return
capacity
;
}
void
SetNull
()
{
head
=
tail
=
0
;
capacity
=
0
;
data
=
nullptr
;
}
void
SetBuffer
(
T
*
_data
,
size_type
_capacity
)
{
assert
(
_data
!=
nullptr
);
assert
(
_capacity
>
0
);
head
=
tail
=
0
;
capacity
=
_capacity
;
data
=
_data
;
}
void
MoveBuffer
(
T
*
new_data
,
size_type
new_capacity
)
{
assert
(
new_capacity
>=
tail
-
head
);
std
::
move
(
data
+
head
,
data
+
tail
,
new_data
);
data
=
new_data
;
capacity
=
new_capacity
;
tail
-=
head
;
head
=
0
;
}
void
Clear
()
{
head
=
tail
=
0
;
}
constexpr
bool
IsEmpty
()
const
{
return
head
==
tail
;
}
constexpr
bool
IsFull
()
const
{
return
head
==
0
&&
tail
==
capacity
;
}
/**
* Prepares writing. Returns a buffer range which may be written.
* When you are finished, call append().
*/
Range
Write
()
{
Shift
();
return
Range
(
data
+
tail
,
capacity
-
tail
);
}
bool
WantWrite
(
size_type
n
)
{
if
(
tail
+
n
<=
capacity
)
/* enough space after the tail */
return
true
;
const
size_type
in_use
=
tail
-
head
;
const
size_type
required_capacity
=
in_use
+
n
;
if
(
required_capacity
>
capacity
)
return
false
;
Shift
();
assert
(
tail
+
n
<=
capacity
);
return
true
;
}
/**
* Expands the tail of the buffer, after data has been written to
* the buffer returned by write().
*/
void
Append
(
size_type
n
)
{
assert
(
tail
<=
capacity
);
assert
(
n
<=
capacity
);
assert
(
tail
+
n
<=
capacity
);
tail
+=
n
;
}
/**
* Return a buffer range which may be read. The buffer pointer is
* writable, to allow modifications while parsing.
*/
constexpr
Range
Read
()
const
{
return
Range
(
data
+
head
,
tail
-
head
);
}
/**
* Marks a chunk as consumed.
*/
void
Consume
(
size_type
n
)
{
assert
(
tail
<=
capacity
);
assert
(
head
<=
tail
);
assert
(
n
<=
tail
);
assert
(
head
+
n
<=
tail
);
head
+=
n
;
}
size_type
Read
(
pointer_type
p
,
size_type
n
)
{
auto
range
=
Read
();
if
(
n
>
range
.
size
)
n
=
range
.
size
;
std
::
copy_n
(
range
.
data
,
n
,
p
);
Consume
(
n
);
return
n
;
}
protected
:
void
Shift
()
{
if
(
head
==
0
)
return
;
assert
(
head
<=
capacity
);
assert
(
tail
<=
capacity
);
assert
(
tail
>=
head
);
std
::
move
(
data
+
head
,
data
+
tail
,
data
);
tail
-=
head
;
head
=
0
;
}
};
#endif
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