blob: 1dc8f7e11adcee8a1259adda6e9eb266daca610c [file] [log] [blame]
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2013, Regents of the University of California
4 *
5 * BSD license, See the LICENSE file for more information
6 *
7 * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
8 */
9
10#ifndef NDN_BUFFER_HPP
11#define NDN_BUFFER_HPP
12
Alexander Afanasyev19508852014-01-29 01:01:51 -080013#include "../common.hpp"
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080014
15#include <boost/iostreams/detail/ios.hpp>
16#include <boost/iostreams/categories.hpp>
17#include <boost/iostreams/stream.hpp>
18
19#include <vector>
20
21namespace ndn {
22
23class Buffer;
24typedef ptr_lib::shared_ptr<const Buffer> ConstBufferPtr;
25typedef ptr_lib::shared_ptr<Buffer> BufferPtr;
26
27/**
28 * @brief Class representing a general-use automatically managed/resized buffer
29 *
30 * In most respect, Buffer class is equivalent to std::vector<uint8_t> and is in fact
31 * uses it as a base class. In addition to that, it provides buf() and buf<T>() helper
32 * method for easier access to the underlying data (buf<T>() casts pointer to the requested class)
33 */
34class Buffer : public std::vector<uint8_t>
35{
36public:
37 /**
38 * @brief Creates an empty buffer
39 */
40 Buffer ()
41 {
42 }
43
44 /**
45 * @brief Create a buffer by copying the supplied data from a const buffer
46 * @param buf const pointer to buffer
47 * @param length length of the buffer to copy
48 */
49 Buffer (const void *buf, size_t length)
50 : std::vector<uint8_t> (reinterpret_cast<const uint8_t*> (buf), reinterpret_cast<const uint8_t*> (buf) + length)
51 {
52 }
53
54 /**
55 * @brief Create a buffer by copying the supplied data using iterator interface
56 *
57 * Note that the supplied iterators must be compatible with std::vector<uint8_t> interface
58 *
59 * @param first iterator to a first element to copy
60 * @param last iterator to an element immediately following the last element to copy
61 */
62 template <class InputIterator>
63 Buffer (InputIterator first, InputIterator last)
64 : std::vector<uint8_t> (first, last)
65 {
66 }
67
68 /**
69 * @brief Get pointer to the first byte of the buffer
70 */
71 inline uint8_t*
72 get ()
73 {
74 return &front ();
75 }
76
77 /**
78 * @brief Get pointer to the first byte of the buffer (alternative version)
79 */
80 inline uint8_t*
81 buf ()
82 {
83 return &front ();
84 }
85
86 /**
87 * @brief Get pointer to the first byte of the buffer and cast
88 * it (reinterpret_cast) to the requested type T
89 */
90 template<class T>
91 inline T*
92 get ()
93 {
94 return reinterpret_cast<T *>(&front ());
95 }
96
97 /**
98 * @brief Get pointer to the first byte of the buffer (alternative version)
99 */
100 inline const uint8_t*
101 buf () const
102 {
103 return &front ();
104 }
105
106 /**
107 * @brief Get const pointer to the first byte of the buffer
108 */
109 inline const uint8_t*
110 get () const
111 {
112 return &front ();
113 }
114
115 /**
116 * @brief Get const pointer to the first byte of the buffer and cast
117 * it (reinterpret_cast) to the requested type T
118 */
119 template<class T>
120 inline const T*
121 get () const
122 {
123 return reinterpret_cast<const T *>(&front ());
124 }
125};
126
127/// @cond include_hidden
128namespace iostreams
129{
130
131class buffer_append_device {
132public:
133 typedef char char_type;
134 typedef boost::iostreams::sink_tag category;
135
136 buffer_append_device (Buffer& container)
137 : m_container (container)
138 {
139 }
140
141 std::streamsize
142 write(const char_type* s, std::streamsize n)
143 {
144 std::copy (s, s+n, std::back_inserter(m_container));
145 return n;
146 }
147
148protected:
149 Buffer& m_container;
150};
151
152} // iostreams
153/// @endcond
154
155/**
156 * Class implementing interface similar to ostringstream, but to construct ndn::Buffer
157 *
158 * The benefit of using stream interface is that it provides automatic buffering of written data
159 * and eliminates (or reduces) overhead of resizing the underlying buffer when writing small pieces of data.
160 *
161 * Usage example:
162 * @code
163 * OBufferStream obuf;
164 * obuf.put(0);
165 * obuf.write(another_buffer, another_buffer_size);
166 * ptr_lib::shared_ptr<Buffer> buf = obuf.get();
167 * @endcode
168 */
169struct OBufferStream : public boost::iostreams::stream<iostreams::buffer_append_device>
170{
171 /**
172 * Default constructor
173 */
174 OBufferStream ()
175 : m_buffer (ptr_lib::make_shared<Buffer> ())
176 , m_device (*m_buffer)
177 {
178 open (m_device);
179 }
180
181 /**
182 * Flush written data to the stream and return shared pointer to the underlying buffer
183 */
184 ptr_lib::shared_ptr<Buffer>
185 buf ()
186 {
187 flush ();
188 return m_buffer;
189 }
190
191private:
192 BufferPtr m_buffer;
193 iostreams::buffer_append_device m_device;
194};
195
196
197} // ndn
198
199#endif // NDN_BUFFER_HPP