alt_sstream_impl.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. // ----------------------------------------------------------------------------
  2. // alt_sstream_impl.hpp : alternative stringstream, templates implementation
  3. // ----------------------------------------------------------------------------
  4. // Copyright Samuel Krempp 2003. Use, modification, and distribution are
  5. // subject to the Boost Software License, Version 1.0. (See accompanying
  6. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. // See http://www.boost.org/libs/format for library home page
  8. // ----------------------------------------------------------------------------
  9. #ifndef BOOST_SK_ALT_SSTREAM_IMPL_HPP
  10. #define BOOST_SK_ALT_SSTREAM_IMPL_HPP
  11. namespace boost {
  12. namespace io {
  13. // --- Implementation ------------------------------------------------------//
  14. template<class Ch, class Tr, class Alloc>
  15. void basic_altstringbuf<Ch, Tr, Alloc>::
  16. clear_buffer () {
  17. const Ch * p = pptr();
  18. const Ch * b = pbase();
  19. if(p != NULL && p != b) {
  20. seekpos(0, ::std::ios_base::out);
  21. }
  22. p = gptr();
  23. b = eback();
  24. if(p != NULL && p != b) {
  25. seekpos(0, ::std::ios_base::in);
  26. }
  27. }
  28. template<class Ch, class Tr, class Alloc>
  29. void basic_altstringbuf<Ch, Tr, Alloc>::
  30. str (const string_type& s) {
  31. size_type sz=s.size();
  32. if(sz != 0 && mode_ & (::std::ios_base::in | ::std::ios_base::out) ) {
  33. #ifdef _RWSTD_NO_CLASS_PARTIAL_SPEC
  34. void *vd_ptr = boost::allocator_allocate(alloc_, sz, is_allocated_? eback() : 0);
  35. Ch *new_ptr = static_cast<Ch *>(vd_ptr);
  36. #else
  37. Ch *new_ptr = boost::allocator_allocate(alloc_, sz, is_allocated_? eback() : 0);
  38. #endif
  39. // if this didnt throw, we're safe, update the buffer
  40. dealloc();
  41. sz = s.copy(new_ptr, sz);
  42. putend_ = new_ptr + sz;
  43. if(mode_ & ::std::ios_base::in)
  44. streambuf_t::setg(new_ptr, new_ptr, new_ptr + sz);
  45. if(mode_ & ::std::ios_base::out) {
  46. streambuf_t::setp(new_ptr, new_ptr + sz);
  47. if(mode_ & (::std::ios_base::app | ::std::ios_base::ate))
  48. streambuf_t::pbump(static_cast<int>(sz));
  49. if(gptr() == NULL)
  50. streambuf_t::setg(new_ptr, NULL, new_ptr);
  51. }
  52. is_allocated_ = true;
  53. }
  54. else
  55. dealloc();
  56. }
  57. template<class Ch, class Tr, class Alloc>
  58. Ch* basic_altstringbuf<Ch, Tr, Alloc>::
  59. begin () const {
  60. if(mode_ & ::std::ios_base::out && pptr() != NULL)
  61. return pbase();
  62. else if(mode_ & ::std::ios_base::in && gptr() != NULL)
  63. return eback();
  64. return NULL;
  65. }
  66. template<class Ch, class Tr, class Alloc>
  67. typename std::basic_string<Ch,Tr,Alloc>::size_type
  68. basic_altstringbuf<Ch, Tr, Alloc>::
  69. size () const {
  70. if(mode_ & ::std::ios_base::out && pptr())
  71. return static_cast<size_type>(pend() - pbase());
  72. else if(mode_ & ::std::ios_base::in && gptr())
  73. return static_cast<size_type>(egptr() - eback());
  74. else
  75. return 0;
  76. }
  77. template<class Ch, class Tr, class Alloc>
  78. typename std::basic_string<Ch,Tr,Alloc>::size_type
  79. basic_altstringbuf<Ch, Tr, Alloc>::
  80. cur_size () const {
  81. if(mode_ & ::std::ios_base::out && pptr())
  82. return static_cast<streamsize>( pptr() - pbase());
  83. else if(mode_ & ::std::ios_base::in && gptr())
  84. return static_cast<streamsize>( gptr() - eback());
  85. else
  86. return 0;
  87. }
  88. template<class Ch, class Tr, class Alloc>
  89. typename basic_altstringbuf<Ch, Tr, Alloc>::pos_type
  90. basic_altstringbuf<Ch, Tr, Alloc>::
  91. seekoff (off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which) {
  92. if(pptr() != NULL && putend_ < pptr())
  93. putend_ = pptr();
  94. if(which & ::std::ios_base::in && gptr() != NULL) {
  95. // get area
  96. if(way == ::std::ios_base::end)
  97. off += static_cast<off_type>(putend_ - gptr());
  98. else if(way == ::std::ios_base::beg)
  99. off += static_cast<off_type>(eback() - gptr());
  100. else if(way != ::std::ios_base::cur || (which & ::std::ios_base::out) )
  101. // (altering in&out is only supported if way is beg or end, not cur)
  102. return pos_type(off_type(-1));
  103. if(eback() <= off+gptr() && off+gptr() <= putend_ ) {
  104. // set gptr
  105. streambuf_t::gbump(static_cast<int>(off));
  106. if(which & ::std::ios_base::out && pptr() != NULL)
  107. // update pptr to match gptr
  108. streambuf_t::pbump(static_cast<int>(gptr()-pptr()));
  109. }
  110. else
  111. off = off_type(-1);
  112. }
  113. else if(which & ::std::ios_base::out && pptr() != NULL) {
  114. // put area
  115. if(way == ::std::ios_base::end)
  116. off += static_cast<off_type>(putend_ - pptr());
  117. else if(way == ::std::ios_base::beg)
  118. off += static_cast<off_type>(pbase() - pptr());
  119. else if(way != ::std::ios_base::beg)
  120. return pos_type(off_type(-1));
  121. if(pbase() <= off+pptr() && off+pptr() <= putend_)
  122. // set pptr
  123. streambuf_t::pbump(static_cast<int>(off));
  124. else
  125. off = off_type(-1);
  126. }
  127. else // neither in nor out
  128. off = off_type(-1);
  129. return (pos_type(off));
  130. }
  131. //- end seekoff(..)
  132. template<class Ch, class Tr, class Alloc>
  133. typename basic_altstringbuf<Ch, Tr, Alloc>::pos_type
  134. basic_altstringbuf<Ch, Tr, Alloc>::
  135. seekpos (pos_type pos, ::std::ios_base::openmode which) {
  136. off_type off = off_type(pos); // operation guaranteed by fpos.operations table 127
  137. if(pptr() != NULL && putend_ < pptr())
  138. putend_ = pptr();
  139. if(off != off_type(-1)) {
  140. if(which & ::std::ios_base::in && gptr() != NULL) {
  141. // get area
  142. if(0 <= off && off <= putend_ - eback()) {
  143. streambuf_t::gbump(static_cast<int>(eback() - gptr() + off));
  144. if(which & ::std::ios_base::out && pptr() != NULL) {
  145. // update pptr to match gptr
  146. streambuf_t::pbump(static_cast<int>(gptr()-pptr()));
  147. }
  148. }
  149. else
  150. off = off_type(-1);
  151. }
  152. else if(which & ::std::ios_base::out && pptr() != NULL) {
  153. // put area
  154. if(0 <= off && off <= putend_ - eback())
  155. streambuf_t::pbump(static_cast<int>(eback() - pptr() + off));
  156. else
  157. off = off_type(-1);
  158. }
  159. else // neither in nor out
  160. off = off_type(-1);
  161. return (pos_type(off));
  162. }
  163. else {
  164. BOOST_ASSERT(0); // fpos.operations allows undefined-behaviour here
  165. return pos_type(off_type(-1));
  166. }
  167. }
  168. // -end seekpos(..)
  169. template<class Ch, class Tr, class Alloc>
  170. typename basic_altstringbuf<Ch, Tr, Alloc>::int_type
  171. basic_altstringbuf<Ch, Tr, Alloc>::
  172. underflow () {
  173. if(gptr() == NULL) // no get area -> nothing to get.
  174. return (compat_traits_type::eof());
  175. else if(gptr() < egptr()) // ok, in buffer
  176. return (compat_traits_type::to_int_type(*gptr()));
  177. else if(mode_ & ::std::ios_base::in && pptr() != NULL
  178. && (gptr() < pptr() || gptr() < putend_) )
  179. { // expand get area
  180. if(putend_ < pptr())
  181. putend_ = pptr(); // remember pptr reached this far
  182. streambuf_t::setg(eback(), gptr(), putend_);
  183. return (compat_traits_type::to_int_type(*gptr()));
  184. }
  185. else // couldnt get anything. EOF.
  186. return (compat_traits_type::eof());
  187. }
  188. // -end underflow(..)
  189. template<class Ch, class Tr, class Alloc>
  190. typename basic_altstringbuf<Ch, Tr, Alloc>::int_type
  191. basic_altstringbuf<Ch, Tr, Alloc>::
  192. pbackfail (int_type meta) {
  193. if(gptr() != NULL && (eback() < gptr())
  194. && (mode_ & (::std::ios_base::out)
  195. || compat_traits_type::eq_int_type(compat_traits_type::eof(), meta)
  196. || compat_traits_type::eq(compat_traits_type::to_char_type(meta), gptr()[-1]) ) ) {
  197. streambuf_t::gbump(-1); // back one character
  198. if(!compat_traits_type::eq_int_type(compat_traits_type::eof(), meta))
  199. // put-back meta into get area
  200. *gptr() = compat_traits_type::to_char_type(meta);
  201. return (compat_traits_type::not_eof(meta));
  202. }
  203. else
  204. return (compat_traits_type::eof()); // failed putback
  205. }
  206. // -end pbackfail(..)
  207. template<class Ch, class Tr, class Alloc>
  208. typename basic_altstringbuf<Ch, Tr, Alloc>::int_type
  209. basic_altstringbuf<Ch, Tr, Alloc>::
  210. overflow (int_type meta) {
  211. #ifdef BOOST_MSVC
  212. #pragma warning(push)
  213. #pragma warning(disable:4996)
  214. #endif
  215. if(compat_traits_type::eq_int_type(compat_traits_type::eof(), meta))
  216. return compat_traits_type::not_eof(meta); // nothing to do
  217. else if(pptr() != NULL && pptr() < epptr()) {
  218. streambuf_t::sputc(compat_traits_type::to_char_type(meta));
  219. return meta;
  220. }
  221. else if(! (mode_ & ::std::ios_base::out))
  222. // no write position, and cant make one
  223. return compat_traits_type::eof();
  224. else { // make a write position available
  225. std::size_t prev_size = pptr() == NULL ? 0 : epptr() - eback();
  226. std::size_t new_size = prev_size;
  227. // exponential growth : size *= 1.5
  228. std::size_t add_size = new_size / 2;
  229. if(add_size < alloc_min)
  230. add_size = alloc_min;
  231. Ch * newptr = NULL, *oldptr = eback();
  232. // make sure adding add_size wont overflow size_t
  233. while (0 < add_size && ((std::numeric_limits<std::size_t>::max)()
  234. - add_size < new_size) )
  235. add_size /= 2;
  236. if(0 < add_size) {
  237. new_size += add_size;
  238. #ifdef _RWSTD_NO_CLASS_PARTIAL_SPEC
  239. void *vdptr = boost::allocator_allocate(alloc_, new_size, is_allocated_? oldptr : 0);
  240. newptr = static_cast<Ch *>(vdptr);
  241. #else
  242. newptr = boost::allocator_allocate(alloc_, new_size, is_allocated_? oldptr : 0);
  243. #endif
  244. }
  245. if(0 < prev_size)
  246. compat_traits_type::copy(newptr, oldptr, prev_size);
  247. if(is_allocated_)
  248. alloc_.deallocate(oldptr, prev_size);
  249. is_allocated_=true;
  250. if(prev_size == 0) { // first allocation
  251. putend_ = newptr;
  252. streambuf_t::setp(newptr, newptr + new_size);
  253. if(mode_ & ::std::ios_base::in)
  254. streambuf_t::setg(newptr, newptr, newptr + 1);
  255. else
  256. streambuf_t::setg(newptr, 0, newptr);
  257. }
  258. else { // update pointers
  259. putend_ = putend_ - oldptr + newptr;
  260. int pptr_count = static_cast<int>(pptr()-pbase());
  261. int gptr_count = static_cast<int>(gptr()-eback());
  262. streambuf_t::setp(pbase() - oldptr + newptr, newptr + new_size);
  263. streambuf_t::pbump(pptr_count);
  264. if(mode_ & ::std::ios_base::in)
  265. streambuf_t::setg(newptr, newptr + gptr_count, pptr() + 1);
  266. else
  267. streambuf_t::setg(newptr, 0, newptr);
  268. }
  269. streambuf_t::sputc(compat_traits_type::to_char_type(meta));
  270. return meta;
  271. }
  272. #ifdef BOOST_MSVC
  273. #pragma warning(pop)
  274. #endif
  275. }
  276. // -end overflow(..)
  277. template<class Ch, class Tr, class Alloc>
  278. void basic_altstringbuf<Ch, Tr, Alloc>:: dealloc() {
  279. if(is_allocated_)
  280. alloc_.deallocate(eback(), (pptr() != NULL ? epptr() : egptr()) - eback());
  281. is_allocated_ = false;
  282. streambuf_t::setg(0, 0, 0);
  283. streambuf_t::setp(0, 0);
  284. putend_ = NULL;
  285. }
  286. }// N.S. io
  287. } // N.S. boost
  288. #endif // include guard