blob: 0b9c32754817e79cef11511aa22e14cf8d759462 [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
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080015namespace ndn {
16
17class Buffer;
18typedef ptr_lib::shared_ptr<const Buffer> ConstBufferPtr;
19typedef ptr_lib::shared_ptr<Buffer> BufferPtr;
20
21/**
22 * @brief Class representing a general-use automatically managed/resized buffer
23 *
24 * In most respect, Buffer class is equivalent to std::vector<uint8_t> and is in fact
25 * uses it as a base class. In addition to that, it provides buf() and buf<T>() helper
26 * method for easier access to the underlying data (buf<T>() casts pointer to the requested class)
27 */
28class Buffer : public std::vector<uint8_t>
29{
30public:
31 /**
32 * @brief Creates an empty buffer
33 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -070034 Buffer()
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080035 {
36 }
37
38 /**
Wentao Shang77949212014-02-01 23:42:24 -080039 * @brief Creates a buffer with pre-allocated size
40 * @param size size of the buffer to be allocated
41 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -070042 explicit
43 Buffer(size_t size)
44 : std::vector<uint8_t>(size, 0)
Wentao Shang77949212014-02-01 23:42:24 -080045 {
46 }
47
48 /**
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080049 * @brief Create a buffer by copying the supplied data from a const buffer
50 * @param buf const pointer to buffer
51 * @param length length of the buffer to copy
52 */
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070053 Buffer(const void* buf, size_t length)
Alexander Afanasyeva465e972014-03-22 17:21:49 -070054 : std::vector<uint8_t>(reinterpret_cast<const uint8_t*>(buf),
55 reinterpret_cast<const uint8_t*>(buf) + length)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080056 {
57 }
58
59 /**
60 * @brief Create a buffer by copying the supplied data using iterator interface
61 *
62 * Note that the supplied iterators must be compatible with std::vector<uint8_t> interface
63 *
64 * @param first iterator to a first element to copy
65 * @param last iterator to an element immediately following the last element to copy
66 */
67 template <class InputIterator>
Alexander Afanasyeva465e972014-03-22 17:21:49 -070068 Buffer(InputIterator first, InputIterator last)
69 : std::vector<uint8_t>(first, last)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080070 {
71 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070072
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080073 /**
74 * @brief Get pointer to the first byte of the buffer
75 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -070076 uint8_t*
77 get()
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080078 {
Alexander Afanasyeva465e972014-03-22 17:21:49 -070079 return &front();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080080 }
81
82 /**
83 * @brief Get pointer to the first byte of the buffer (alternative version)
84 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -070085 uint8_t*
86 buf()
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080087 {
Alexander Afanasyeva465e972014-03-22 17:21:49 -070088 return &front();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080089 }
90
91 /**
92 * @brief Get pointer to the first byte of the buffer and cast
93 * it (reinterpret_cast) to the requested type T
94 */
95 template<class T>
Alexander Afanasyeva465e972014-03-22 17:21:49 -070096 T*
97 get()
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -080098 {
Alexander Afanasyeva465e972014-03-22 17:21:49 -070099 return reinterpret_cast<T*>(&front());
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800100 }
101
102 /**
103 * @brief Get pointer to the first byte of the buffer (alternative version)
104 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700105 const uint8_t*
106 buf() const
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800107 {
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700108 return &front();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800109 }
110
111 /**
112 * @brief Get const pointer to the first byte of the buffer
113 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700114 const uint8_t*
115 get() const
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800116 {
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700117 return &front();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800118 }
119
120 /**
121 * @brief Get const pointer to the first byte of the buffer and cast
122 * it (reinterpret_cast) to the requested type T
123 */
124 template<class T>
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700125 const T*
126 get() const
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800127 {
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700128 return reinterpret_cast<const T*>(&front());
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700129 }
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800130};
131
132/// @cond include_hidden
133namespace iostreams
134{
135
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700136class buffer_append_device
137{
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800138public:
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700139 typedef char char_type;
140 typedef boost::iostreams::sink_tag category;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700141
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700142 buffer_append_device(Buffer& container)
143 : m_container(container)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800144 {
145 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700146
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800147 std::streamsize
148 write(const char_type* s, std::streamsize n)
149 {
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700150 std::copy(s, s+n, std::back_inserter(m_container));
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800151 return n;
152 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700153
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800154protected:
155 Buffer& m_container;
156};
157
158} // iostreams
159/// @endcond
160
161/**
162 * Class implementing interface similar to ostringstream, but to construct ndn::Buffer
163 *
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700164 * The benefit of using stream interface is that it provides automatic buffering of
165 * written data and eliminates (or reduces) overhead of resizing the underlying buffer
166 * when writing small pieces of data.
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800167 *
168 * Usage example:
169 * @code
170 * OBufferStream obuf;
171 * obuf.put(0);
172 * obuf.write(another_buffer, another_buffer_size);
173 * ptr_lib::shared_ptr<Buffer> buf = obuf.get();
174 * @endcode
175 */
176struct OBufferStream : public boost::iostreams::stream<iostreams::buffer_append_device>
177{
178 /**
179 * Default constructor
180 */
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700181 OBufferStream()
182 : m_buffer(ptr_lib::make_shared<Buffer>())
183 , m_device(*m_buffer)
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800184 {
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700185 open(m_device);
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800186 }
187
188 /**
189 * Flush written data to the stream and return shared pointer to the underlying buffer
190 */
191 ptr_lib::shared_ptr<Buffer>
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700192 buf()
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800193 {
Alexander Afanasyeva465e972014-03-22 17:21:49 -0700194 flush();
Alexander Afanasyev13bb51a2014-01-02 19:13:26 -0800195 return m_buffer;
196 }
197
198private:
199 BufferPtr m_buffer;
200 iostreams::buffer_append_device m_device;
201};
202
203
204} // ndn
205
206#endif // NDN_BUFFER_HPP