]> git.proxmox.com Git - ceph.git/blob - ceph/src/common/PrebufferedStreambuf.cc
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / common / PrebufferedStreambuf.cc
1
2 #include "common/PrebufferedStreambuf.h"
3 #include <string.h>
4 PrebufferedStreambuf::PrebufferedStreambuf(char *buf, size_t len)
5 : m_buf(buf), m_buf_len(len)
6 {
7 // init output buffer
8 this->setp(m_buf, m_buf + m_buf_len);
9
10 // so we underflow on first read
11 this->setg(0, 0, 0);
12 }
13
14 PrebufferedStreambuf::int_type PrebufferedStreambuf::overflow(int_type c)
15 {
16 int old_len = m_overflow.size();
17 if (old_len == 0) {
18 m_overflow.resize(80);
19 } else {
20 m_overflow.resize(old_len * 2);
21 }
22 m_overflow[old_len] = c;
23 this->setp(&m_overflow[old_len + 1], &*m_overflow.begin() + m_overflow.size());
24 return std::char_traits<char>::not_eof(c);
25 }
26
27 PrebufferedStreambuf::int_type PrebufferedStreambuf::underflow()
28 {
29 if (this->gptr() == 0) {
30 // first read; start with the static buffer
31 if (m_overflow.size())
32 // there is overflow, so start with entire prealloc buffer
33 this->setg(m_buf, m_buf, m_buf + m_buf_len);
34 else if (this->pptr() == m_buf)
35 // m_buf is empty
36 return traits_ty::eof(); // no data
37 else
38 // set up portion of m_buf we've filled
39 this->setg(m_buf, m_buf, this->pptr());
40 return *this->gptr();
41 }
42 if (this->gptr() == m_buf + m_buf_len && m_overflow.size()) {
43 // at end of m_buf; continue with the overflow string
44 this->setg(&m_overflow[0], &m_overflow[0], this->pptr());
45 return *this->gptr();
46 }
47
48 // otherwise we must be at the end (of m_buf and/or m_overflow)
49 return traits_ty::eof();
50 }
51
52 std::string PrebufferedStreambuf::get_str() const
53 {
54 if (m_overflow.size()) {
55 std::string s(m_buf, m_buf + m_buf_len);
56 s.append(&m_overflow[0], this->pptr() - &m_overflow[0]);
57 return s;
58 } else if (this->pptr() == m_buf) {
59 return std::string();
60 } else {
61 return std::string(m_buf, this->pptr() - m_buf);
62 }
63 }
64 // returns current size of content
65 size_t PrebufferedStreambuf::size() const
66 {
67 if (m_overflow.size() == 0) {
68 return this->pptr() - m_buf;
69 } else {
70 return m_buf_len + this->pptr() - &m_overflow[0];
71 }
72 }
73
74 // extracts up to avail chars of content
75 int PrebufferedStreambuf::snprintf(char* dst, size_t avail) const
76 {
77 size_t o_size = m_overflow.size();
78 size_t len_a;
79 size_t len_b;
80 if (o_size>0) {
81 len_a = m_buf_len;
82 len_b = this->pptr() - &m_overflow[0];
83 } else {
84 len_a = this->pptr() - m_buf;
85 len_b = 0;
86 }
87 if (avail > len_a + len_b) {
88 memcpy(dst, m_buf, len_a);
89 memcpy(dst + m_buf_len, m_overflow.c_str(), len_b);
90 dst[len_a + len_b] = 0;
91 } else {
92 if (avail > len_a) {
93 memcpy(dst, m_buf, len_a);
94 memcpy(dst + m_buf_len, m_overflow.c_str(), avail - len_a - 1);
95 dst[avail - 1] = 0;
96 } else {
97 memcpy(dst, m_buf, avail - 1);
98 dst[avail - 1] = 0;
99 }
100 }
101 return len_a + len_b;
102 }