CUBRID Engine  latest
string_buffer.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /*
20  * string_buffer.hpp
21  *
22  * - collects formatted text (printf-like syntax) in a fixed size buffer
23  * - useful to build a formatted string in successive function calls without dynamic memory allocation
24  * - if the provided buffer is too small then the len() method can be used to find necessary size
25  * (similar with snprintf() behavior)
26  * to simplify the caller code and because this class has only one functionality (add text with format), I used
27  * operator() instead of a named method (see below)
28  *
29  * Usage:
30  * string_buffer sb; //uses default_realloc & default_dealloc by default
31  * sb("simple text"); // <=> sb.add_with_format("simple text")
32  * sb("format i=%d f=%lf s=\"%s\"", 1, 2.3, "4567890");
33  * printf(sb.get_buffer()); // => i=1 f=2.3 s="4567890"
34  */
35 
36 #ifndef _STRING_BUFFER_HPP_
37 #define _STRING_BUFFER_HPP_
38 
39 #include "mem_block.hpp"
40 
41 #include <assert.h>
42 #include <stddef.h>
43 #include <stdio.h>
44 #include <functional>
45 
47 {
48  public:
50  : m_len (0)
51  , m_ext_block ()
52  {
53  }
54 
56  {
57  m_len = 0; //dtor
58  }
59 
61  : m_len {0}
62  , m_ext_block { alloc }
63  {
64  }
65 
66  string_buffer (const cubmem::block_allocator &alloc, size_t initial_size)
67  : string_buffer (alloc)
68  {
69  m_ext_block.extend_to (initial_size);
70  m_ext_block.get_ptr ()[m_len] = '\0';
71  }
72 
73  const char *get_buffer () const
74  {
75  return this->m_ext_block.get_read_ptr ();
76  }
77 
78  void clear ()
79  {
80  if (m_ext_block.get_ptr () != NULL)
81  {
82  m_len = 0;
83  *m_ext_block.get_ptr () = '\0';
84  }
85  }
86 
87  size_t len () const
88  {
89  // current content length, not including ending '\0' (similar with strlen(...))
90  return m_len;
91  }
92 
93  char *release_ptr ()
94  {
95  return m_ext_block.release_ptr ();
96  }
97 
98  inline void operator+= (const char ch); //add a single char
99 
100  void add_bytes (size_t len, const char *bytes); //add "len" bytes (can have '\0' in the middle)
101 
102  template<typename... Args> inline int operator() (Args &&... args); //add with printf format
103 
104  void hex_dump (const string_buffer &in, const size_t max_to_dump, const size_t line_size = 16,
105  const bool print_ascii = true);
106  void hex_dump (const char *ptr, const size_t length, const size_t line_size = 16, const bool print_ascii = true);
107 
108  private:
109  string_buffer (const string_buffer &) = delete; //copy ctor
110  string_buffer (string_buffer &&) = delete; //move ctor
111  void operator= (const string_buffer &) = delete; //copy assign
112  void operator= (string_buffer &&) = delete; //move assign
113 
114  size_t m_len; //current content length not including ending '\0'
116 };
117 
118 //implementation for small (inline) methods
119 
120 void string_buffer::operator+= (const char ch)
121 {
122  if (m_ext_block.get_size () == 0)
123  {
124  m_ext_block.extend_to (2); // 2 new bytes needed: ch + '\0'
125  }
126  else
127  {
128  assert (m_ext_block.get_ptr ()[m_len] == '\0');
129 
130  // (m_len + 1) is the current number of chars including ending '\0'
132  }
133 
134  m_ext_block.get_ptr ()[m_len] = ch;
135  m_ext_block.get_ptr ()[++m_len] = '\0';
136 }
137 
138 template<typename... Args> int string_buffer::operator() (Args &&... args)
139 {
140  int len = snprintf (NULL, 0, std::forward<Args> (args)...);
141 
142  assert (len >= 0);
143 
144  m_ext_block.extend_to (m_len + size_t (len) + 2);
145 
146  snprintf (m_ext_block.get_ptr () + m_len, m_ext_block.get_size () - m_len, std::forward<Args> (args)...);
147  m_len += len;
148 
149  return len;
150 }
151 
152 #endif /* _STRING_BUFFER_HPP_ */
cubmem::extensible_block m_ext_block
char * release_ptr()
int operator()(Args &&...args)
void hex_dump(const string_buffer &in, const size_t max_to_dump, const size_t line_size=16, const bool print_ascii=true)
std::size_t get_size() const
Definition: mem_block.hpp:374
void operator+=(const char ch)
#define assert(x)
#define NULL
Definition: freelistheap.h:34
const char * get_read_ptr() const
Definition: mem_block.hpp:368
const char * get_buffer() const
size_t len() const
string_buffer(const cubmem::block_allocator &alloc, size_t initial_size)
void extend_to(size_t total_bytes)
Definition: mem_block.hpp:346
void operator=(const string_buffer &)=delete
string_buffer(const cubmem::block_allocator &alloc)
void add_bytes(size_t len, const char *bytes)