1
2// vim:sw=2:ai
3
4/*
5 * Copyright (C) 2010-2011 DeNA Co.,Ltd.. All rights reserved.
6 * Copyright (C) 2011 Kentoku SHIBA
7 * See COPYRIGHT.txt for details.
8 */
9
10#ifndef DENA_STRING_BUFFER_HPP
11#define DENA_STRING_BUFFER_HPP
12
13/*
14#include <stdlib.h>
15#include <string.h>
16*/
17
18#include "util.hpp"
19#include "allocator.hpp"
20#include "fatal.hpp"
21
22namespace dena {
23
24struct string_buffer : private noncopyable {
25 string_buffer() : buffer(0), begin_offset(0), end_offset(0), alloc_size(0) { }
26 ~string_buffer() {
27 real_free();
28 }
29 void real_free() {
30 if (alloc_size) {
31 DENA_FREE(buffer);
32 buffer = 0;
33 begin_offset = 0;
34 end_offset = 0;
35 alloc_size = 0;
36 }
37 }
38 size_t real_size() {
39 return alloc_size;
40 }
41 const char *begin() const {
42 return buffer + begin_offset;
43 }
44 const char *end() const {
45 return buffer + end_offset;
46 }
47 char *begin() {
48 return buffer + begin_offset;
49 }
50 char *end() {
51 return buffer + end_offset;
52 }
53 size_t size() const {
54 return end_offset - begin_offset;
55 }
56 void clear() {
57 begin_offset = end_offset = 0;
58 }
59 void resize(size_t len) {
60 if (size() < len) {
61 reserve(len);
62 memset(buffer + end_offset, 0, len - size());
63 }
64 end_offset = begin_offset + len;
65 }
66 void reserve(size_t len) {
67 if (alloc_size >= begin_offset + len) {
68 return;
69 }
70 size_t asz = alloc_size;
71 while (asz < begin_offset + len) {
72 if (asz == 0) {
73 asz = 16;
74 }
75 const size_t asz_n = asz << 1;
76 if (asz_n < asz) {
77 fatal_abort("string_buffer::resize() overflow");
78 }
79 asz = asz_n;
80 }
81 void *const p = DENA_REALLOC(buffer, asz);
82 if (p == 0) {
83 fatal_abort("string_buffer::resize() realloc");
84 }
85 buffer = static_cast<char *>(p);
86 alloc_size = asz;
87 }
88 void erase_front(size_t len) {
89 if (len >= size()) {
90 clear();
91 } else {
92 begin_offset += len;
93 }
94 }
95 char *make_space(size_t len) {
96 reserve(size() + len);
97 return buffer + end_offset;
98 }
99 void space_wrote(size_t len) {
100 len = len < alloc_size - end_offset ? len : alloc_size - end_offset;
101 end_offset += len;
102 }
103 template <size_t N>
104 void append_literal(const char (& str)[N]) {
105 append(str, str + N - 1);
106 }
107 void append(const char *start, const char *finish) {
108 const size_t len = finish - start;
109 reserve(size() + len);
110 memcpy(buffer + end_offset, start, len);
111 end_offset += len;
112 }
113 void append_2(const char *s1, const char *f1, const char *s2,
114 const char *f2) {
115 const size_t l1 = f1 - s1;
116 const size_t l2 = f2 - s2;
117 reserve(end_offset + l1 + l2);
118 memcpy(buffer + end_offset, s1, l1);
119 memcpy(buffer + end_offset + l1, s2, l2);
120 end_offset += l1 + l2;
121 }
122 void swap(string_buffer& sb) {
123 char *tmp_buffer = buffer;
124 size_t tmp_begin_offset = begin_offset;
125 size_t tmp_end_offset = end_offset;
126 size_t tmp_alloc_size = alloc_size;
127 buffer = sb.buffer;
128 begin_offset = sb.begin_offset;
129 end_offset = sb.end_offset;
130 alloc_size = sb.alloc_size;
131 sb.buffer = tmp_buffer;
132 sb.begin_offset = tmp_begin_offset;
133 sb.end_offset = tmp_end_offset;
134 sb.alloc_size = tmp_alloc_size;
135 }
136 private:
137 char *buffer;
138 size_t begin_offset;
139 size_t end_offset;
140 size_t alloc_size;
141};
142
143};
144
145#endif
146
147