File: streambuf.hpp

package info (click to toggle)
libzeep 5.1.8-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 3,596 kB
  • sloc: cpp: 27,393; xml: 7,798; javascript: 180; sh: 37; makefile: 8
file content (127 lines) | stat: -rw-r--r-- 2,761 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
//          Copyright Maarten L. Hekkelman, 2020
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)

#pragma once

/// \file
/// A simple std::streambuf implementation that wraps around const char* data.

#include <zeep/config.hpp>

#include <cassert>
#include <cstring>

#include <streambuf>

namespace zeep
{

// --------------------------------------------------------------------
/// \brief A simple class to use const char buffers as streambuf
///
/// It is very often useful to have a streambuf class that can wrap
/// wrap around a const char* pointer.

class char_streambuf : public std::streambuf
{
  public:

	/// \brief constructor taking a \a buffer and a \a length
	char_streambuf(const char* buffer, size_t length)
		: m_begin(buffer), m_end(buffer + length), m_current(buffer)
	{
		assert(std::less_equal<const char*>()(m_begin, m_end));
	}

	/// \brief constructor taking a \a buffer using the standard strlen to determine the length
	char_streambuf(const char* buffer)
		: m_begin(buffer), m_end(buffer + strlen(buffer)), m_current(buffer)
	{
	}

	char_streambuf(const char_streambuf&) = delete;
	char_streambuf &operator=(const char_streambuf&) = delete;

  private:

	int_type underflow()
	{
		if (m_current == m_end)
			return traits_type::eof();

		return traits_type::to_int_type(*m_current);
	}

	int_type uflow()
	{
		if (m_current == m_end)
			return traits_type::eof();

		return traits_type::to_int_type(*m_current++);
	}

	int_type pbackfail(int_type ch)
	{
		if (m_current == m_begin or (ch != traits_type::eof() and ch != m_current[-1]))
			return traits_type::eof();

		return traits_type::to_int_type(*--m_current);
	}

	std::streamsize showmanyc()
	{
		assert(std::less_equal<const char*>()(m_current, m_end));
		return m_end - m_current;
	}

	pos_type seekoff(std::streambuf::off_type off, std::ios_base::seekdir dir, std::ios_base::openmode /*which*/)
	{
		switch (dir)
		{
			case std::ios_base::beg:
				m_current = m_begin + off;
				break;

			case std::ios_base::end:
				m_current = m_end + off;
				break;

			case std::ios_base::cur:
				m_current += off;
				break;
			
			default:
				break;
		}

		if (m_current < m_begin)
			m_current = m_begin;
		
		if (m_current > m_end)
			m_current = m_end;

		return m_current - m_begin;
	}

	pos_type seekpos(std::streambuf::pos_type pos, std::ios_base::openmode /*which*/)
	{
		m_current = m_begin + pos;

		if (m_current < m_begin)
			m_current = m_begin;
		
		if (m_current > m_end)
			m_current = m_end;

		return m_current - m_begin;
	}

  private:
	const char* const m_begin;
	const char* const m_end;
	const char* m_current;
};
	
} // namespace zeep