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