1 
2 // vim:sw=2:ai
3 
4 /*
5  * Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved.
6  * See COPYRIGHT.txt for details.
7  */
8 
9 #ifndef DENA_STRING_BUFFER_HPP
10 #define DENA_STRING_BUFFER_HPP
11 
12 #include <vector>
13 #include <stdlib.h>
14 #include <string.h>
15 
16 #include "util.hpp"
17 #include "allocator.hpp"
18 #include "fatal.hpp"
19 
20 namespace dena {
21 
22 struct string_buffer : private noncopyable {
string_bufferdena::string_buffer23   string_buffer() : buffer(0), begin_offset(0), end_offset(0), alloc_size(0) { }
~string_bufferdena::string_buffer24   ~string_buffer() {
25     DENA_FREE(buffer);
26   }
begindena::string_buffer27   const char *begin() const {
28     return buffer + begin_offset;
29   }
enddena::string_buffer30   const char *end() const {
31     return buffer + end_offset;
32   }
begindena::string_buffer33   char *begin() {
34     return buffer + begin_offset;
35   }
enddena::string_buffer36   char *end() {
37     return buffer + end_offset;
38   }
sizedena::string_buffer39   size_t size() const {
40     return end_offset - begin_offset;
41   }
cleardena::string_buffer42   void clear() {
43     begin_offset = end_offset = 0;
44   }
resizedena::string_buffer45   void resize(size_t len) {
46     if (size() < len) {
47       reserve(len);
48       memset(buffer + end_offset, 0, len - size());
49     }
50     end_offset = begin_offset + len;
51   }
reservedena::string_buffer52   void reserve(size_t len) {
53     if (alloc_size >= begin_offset + len) {
54       return;
55     }
56     size_t asz = alloc_size;
57     while (asz < begin_offset + len) {
58       if (asz == 0) {
59 	asz = 16;
60       }
61       const size_t asz_n = asz << 1;
62       if (asz_n < asz) {
63 	fatal_abort("string_buffer::resize() overflow");
64       }
65       asz = asz_n;
66     }
67     void *const p = DENA_REALLOC(buffer, asz);
68     if (p == 0) {
69       fatal_abort("string_buffer::resize() realloc");
70     }
71     buffer = static_cast<char *>(p);
72     alloc_size = asz;
73   }
erase_frontdena::string_buffer74   void erase_front(size_t len) {
75     if (len >= size()) {
76       clear();
77     } else {
78       begin_offset += len;
79     }
80   }
make_spacedena::string_buffer81   char *make_space(size_t len) {
82     reserve(size() + len);
83     return buffer + end_offset;
84   }
space_wrotedena::string_buffer85   void space_wrote(size_t len) {
86     len = std::min(len, alloc_size - end_offset);
87     end_offset += len;
88   }
89   template <size_t N>
append_literaldena::string_buffer90   void append_literal(const char (& str)[N]) {
91     append(str, str + N - 1);
92   }
appenddena::string_buffer93   void append(const char *start, const char *finish) {
94     const size_t len = finish - start;
95     reserve(size() + len);
96     memcpy(buffer + end_offset, start, len);
97     end_offset += len;
98   }
append_2dena::string_buffer99   void append_2(const char *s1, const char *f1, const char *s2,
100     const char *f2) {
101     const size_t l1 = f1 - s1;
102     const size_t l2 = f2 - s2;
103     reserve(end_offset + l1 + l2);
104     memcpy(buffer + end_offset, s1, l1);
105     memcpy(buffer + end_offset + l1, s2, l2);
106     end_offset += l1 + l2;
107   }
108  private:
109   char *buffer;
110   size_t begin_offset;
111   size_t end_offset;
112   size_t alloc_size;
113 };
114 
115 };
116 
117 #endif
118 
119