strstream.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. /*
  2. * Copyright (c) 1999
  3. * Silicon Graphics Computer Systems, Inc.
  4. *
  5. * Copyright (c) 1999
  6. * Boris Fomitchev
  7. *
  8. * This material is provided "as is", with absolutely no warranty expressed
  9. * or implied. Any use is at your own risk.
  10. *
  11. * Permission to use or copy this software for any purpose is hereby granted
  12. * without fee, provided the above notices are retained on all copies.
  13. * Permission to modify the code and to distribute modified code is granted,
  14. * provided the above notices are retained, and a notice that the code was
  15. * modified is included with the above copyright notice.
  16. *
  17. */
  18. // Implementation of the classes in header <strstream>.
  19. // WARNING: The classes defined in <strstream> are DEPRECATED. This
  20. // header is defined in section D.7.1 of the C++ standard, and it
  21. // MAY BE REMOVED in a future standard revision. You should use the
  22. // header <sstream> instead.
  23. #include "stlport_prefix.h"
  24. #include <strstream>
  25. #include <algorithm>
  26. #include <limits>
  27. _STLP_BEGIN_NAMESPACE
  28. // strstreambuf constructor, destructor.
  29. strstreambuf::strstreambuf(streamsize initial_capacity)
  30. : _M_alloc_fun(0), _M_free_fun(0),
  31. _M_dynamic(true), _M_frozen(false), _M_constant(false) {
  32. size_t n = (sizeof(streamsize) > sizeof(size_t)) ? __STATIC_CAST(size_t, (min)(__STATIC_CAST(streamsize, (numeric_limits<size_t>::max)()),
  33. (max)(initial_capacity, streamsize(16))))
  34. : __STATIC_CAST(size_t, (max)(initial_capacity, streamsize(16)));
  35. char* buf = _M_alloc(n);
  36. if (buf) {
  37. setp(buf, buf + n);
  38. setg(buf, buf, buf);
  39. }
  40. }
  41. strstreambuf::strstreambuf(__alloc_fn alloc_f, __free_fn free_f)
  42. : _M_alloc_fun(alloc_f), _M_free_fun(free_f),
  43. _M_dynamic(true), _M_frozen(false), _M_constant(false) {
  44. size_t n = 16;
  45. char* buf = _M_alloc(n);
  46. if (buf) {
  47. setp(buf, buf + n);
  48. setg(buf, buf, buf);
  49. }
  50. }
  51. strstreambuf::strstreambuf(char* get, streamsize n, char* put)
  52. : _M_alloc_fun(0), _M_free_fun(0),
  53. _M_dynamic(false), _M_frozen(false), _M_constant(false) {
  54. _M_setup(get, put, n);
  55. }
  56. strstreambuf::strstreambuf(signed char* get, streamsize n, signed char* put)
  57. : _M_alloc_fun(0), _M_free_fun(0),
  58. _M_dynamic(false), _M_frozen(false), _M_constant(false) {
  59. _M_setup(__REINTERPRET_CAST(char*,get), __REINTERPRET_CAST(char*,put), n);
  60. }
  61. strstreambuf::strstreambuf(unsigned char* get, streamsize n,
  62. unsigned char* put)
  63. : _M_alloc_fun(0), _M_free_fun(0),
  64. _M_dynamic(false), _M_frozen(false), _M_constant(false) {
  65. _M_setup(__REINTERPRET_CAST(char*,get), __REINTERPRET_CAST(char*,put), n);
  66. }
  67. strstreambuf::strstreambuf(const char* get, streamsize n)
  68. : _M_alloc_fun(0), _M_free_fun(0),
  69. _M_dynamic(false), _M_frozen(false), _M_constant(true) {
  70. _M_setup(__CONST_CAST(char*,get), 0, n);
  71. }
  72. strstreambuf::strstreambuf(const signed char* get, streamsize n)
  73. : _M_alloc_fun(0), _M_free_fun(0),
  74. _M_dynamic(false), _M_frozen(false), _M_constant(true) {
  75. _M_setup(__REINTERPRET_CAST(char*, __CONST_CAST(signed char*,get)), 0, n);
  76. }
  77. strstreambuf::strstreambuf(const unsigned char* get, streamsize n)
  78. : _M_alloc_fun(0), _M_free_fun(0),
  79. _M_dynamic(false), _M_frozen(false), _M_constant(true) {
  80. _M_setup(__REINTERPRET_CAST(char*, __CONST_CAST(unsigned char*,get)), 0, n);
  81. }
  82. strstreambuf::~strstreambuf() {
  83. if (_M_dynamic && !_M_frozen)
  84. _M_free(eback());
  85. }
  86. void strstreambuf::freeze(bool frozenflag) {
  87. if (_M_dynamic)
  88. _M_frozen = frozenflag;
  89. }
  90. char* strstreambuf::str() {
  91. freeze(true);
  92. return eback();
  93. }
  94. int strstreambuf::pcount() const {
  95. return int(pptr() ? pptr() - pbase() : 0);
  96. }
  97. strstreambuf::int_type strstreambuf::overflow(int_type c) {
  98. if (c == traits_type::eof())
  99. return traits_type::not_eof(c);
  100. // Try to expand the buffer.
  101. if (pptr() == epptr() && _M_dynamic && !_M_frozen && !_M_constant) {
  102. ptrdiff_t old_size = epptr() - pbase();
  103. ptrdiff_t new_size = (max)(2 * old_size, ptrdiff_t(1));
  104. char* buf = _M_alloc(new_size);
  105. if (buf) {
  106. memcpy(buf, pbase(), old_size);
  107. char* old_buffer = pbase();
  108. bool reposition_get = false;
  109. ptrdiff_t old_get_offset;
  110. if (gptr() != 0) {
  111. reposition_get = true;
  112. old_get_offset = gptr() - eback();
  113. }
  114. setp(buf, buf + new_size);
  115. pbump((int)old_size);
  116. if (reposition_get)
  117. setg(buf, buf + old_get_offset, buf + (max)(old_get_offset, old_size));
  118. _M_free(old_buffer);
  119. }
  120. }
  121. if (pptr() != epptr()) {
  122. *pptr() = traits_type::to_char_type(c);
  123. pbump(1);
  124. return c;
  125. }
  126. else
  127. return traits_type::eof();
  128. }
  129. strstreambuf::int_type strstreambuf::pbackfail(int_type c) {
  130. if (gptr() != eback()) {
  131. if (c == traits_type::eof()) {
  132. gbump(-1);
  133. return traits_type::not_eof(c);
  134. }
  135. else if (c == gptr()[-1]) {
  136. gbump(-1);
  137. return c;
  138. }
  139. else if (!_M_constant) {
  140. gbump(-1);
  141. *gptr() = traits_type::to_char_type(c);
  142. return c;
  143. }
  144. }
  145. return traits_type::eof();
  146. }
  147. strstreambuf::int_type strstreambuf::underflow() {
  148. if (gptr() == egptr() && pptr() && pptr() > egptr())
  149. setg(eback(), gptr(), pptr());
  150. if (gptr() != egptr())
  151. return (unsigned char) *gptr();
  152. else
  153. return _Traits::eof();
  154. }
  155. basic_streambuf<char, char_traits<char> >*
  156. strstreambuf::setbuf(char*, streamsize) {
  157. return this;
  158. }
  159. strstreambuf::pos_type
  160. strstreambuf::seekoff(off_type off,
  161. ios_base::seekdir dir, ios_base::openmode mode) {
  162. bool do_get = false;
  163. bool do_put = false;
  164. if ((mode & (ios_base::in | ios_base::out)) ==
  165. (ios_base::in | ios_base::out) &&
  166. (dir == ios_base::beg || dir == ios_base::end))
  167. do_get = do_put = true;
  168. else if (mode & ios_base::in)
  169. do_get = true;
  170. else if (mode & ios_base::out)
  171. do_put = true;
  172. // !gptr() is here because, according to D.7.1 paragraph 4, the seekable
  173. // area is undefined if there is no get area.
  174. if ((!do_get && !do_put) || (do_put && !pptr()) || !gptr())
  175. return pos_type(off_type(-1));
  176. char* seeklow = eback();
  177. char* seekhigh = epptr() ? epptr() : egptr();
  178. off_type newoff;
  179. switch(dir) {
  180. case ios_base::beg:
  181. newoff = 0;
  182. break;
  183. case ios_base::end:
  184. newoff = seekhigh - seeklow;
  185. break;
  186. case ios_base::cur:
  187. newoff = do_put ? pptr() - seeklow : gptr() - seeklow;
  188. break;
  189. default:
  190. return pos_type(off_type(-1));
  191. }
  192. off += newoff;
  193. if (off < 0 || off > seekhigh - seeklow)
  194. return pos_type(off_type(-1));
  195. if (do_put) {
  196. if (seeklow + __STATIC_CAST(ptrdiff_t, off) < pbase()) {
  197. setp(seeklow, epptr());
  198. pbump((int)off);
  199. }
  200. else {
  201. setp(pbase(), epptr());
  202. pbump((int)(off - (pbase() - seeklow)));
  203. }
  204. }
  205. if (do_get) {
  206. if (off <= egptr() - seeklow)
  207. setg(seeklow, seeklow + __STATIC_CAST(ptrdiff_t, off), egptr());
  208. else if (off <= pptr() - seeklow)
  209. setg(seeklow, seeklow + __STATIC_CAST(ptrdiff_t, off), pptr());
  210. else
  211. setg(seeklow, seeklow + __STATIC_CAST(ptrdiff_t, off), epptr());
  212. }
  213. return pos_type(newoff);
  214. }
  215. strstreambuf::pos_type
  216. strstreambuf::seekpos(pos_type pos, ios_base::openmode mode) {
  217. return seekoff(pos - pos_type(off_type(0)), ios_base::beg, mode);
  218. }
  219. char* strstreambuf::_M_alloc(size_t n) {
  220. if (_M_alloc_fun)
  221. return __STATIC_CAST(char*,_M_alloc_fun(n));
  222. else
  223. return new char[n];
  224. }
  225. void strstreambuf::_M_free(char* p) {
  226. if (p) {
  227. if (_M_free_fun)
  228. _M_free_fun(p);
  229. else
  230. delete[] p;
  231. }
  232. }
  233. void strstreambuf::_M_setup(char* get, char* put, streamsize n) {
  234. if (get) {
  235. size_t N = n > 0 ? size_t(n) : n == 0 ? strlen(get) : size_t(INT_MAX);
  236. if (put) {
  237. setg(get, get, get + N);
  238. setp(put, put + N);
  239. }
  240. else {
  241. setg(get, get, get + N);
  242. }
  243. }
  244. }
  245. //----------------------------------------------------------------------
  246. // Class istrstream
  247. istrstream::istrstream(char* s)
  248. : basic_istream<char, char_traits<char> >(0), _M_buf(s, 0) {
  249. this->init(&_M_buf);
  250. }
  251. istrstream::istrstream(const char* s)
  252. : basic_istream<char, char_traits<char> >(0), _M_buf(s, 0) {
  253. this->init(&_M_buf);
  254. }
  255. istrstream::istrstream(char* s, streamsize n)
  256. : basic_istream<char, char_traits<char> >(0), _M_buf(s, n) {
  257. this->init(&_M_buf);
  258. }
  259. istrstream::istrstream(const char* s, streamsize n)
  260. : basic_istream<char, char_traits<char> >(0), _M_buf(s, n) {
  261. this->init(&_M_buf);
  262. }
  263. istrstream::~istrstream() {}
  264. strstreambuf* istrstream::rdbuf() const {
  265. return __CONST_CAST(strstreambuf*,&_M_buf);
  266. }
  267. char* istrstream::str() { return _M_buf.str(); }
  268. //----------------------------------------------------------------------
  269. // Class ostrstream
  270. ostrstream::ostrstream()
  271. : basic_ostream<char, char_traits<char> >(0), _M_buf() {
  272. basic_ios<char, char_traits<char> >::init(&_M_buf);
  273. }
  274. ostrstream::ostrstream(char* s, int n, ios_base::openmode mode)
  275. : basic_ostream<char, char_traits<char> >(0),
  276. _M_buf(s, n, mode & ios_base::app ? s + strlen(s) : s) {
  277. basic_ios<char, char_traits<char> >::init(&_M_buf);
  278. }
  279. ostrstream::~ostrstream() {}
  280. strstreambuf* ostrstream::rdbuf() const {
  281. return __CONST_CAST(strstreambuf*,&_M_buf);
  282. }
  283. void ostrstream::freeze(bool freezeflag) {
  284. _M_buf.freeze(freezeflag);
  285. }
  286. char* ostrstream::str() {
  287. return _M_buf.str();
  288. }
  289. int ostrstream::pcount() const {
  290. return _M_buf.pcount();
  291. }
  292. //----------------------------------------------------------------------
  293. // Class strstream
  294. strstream::strstream()
  295. : basic_iostream<char, char_traits<char> >(0), _M_buf() {
  296. basic_ios<char, char_traits<char> >::init(&_M_buf);
  297. }
  298. strstream::strstream(char* s, int n, ios_base::openmode mode)
  299. : basic_iostream<char, char_traits<char> >(0),
  300. _M_buf(s, n, mode & ios_base::app ? s + strlen(s) : s) {
  301. basic_ios<char, char_traits<char> >::init(&_M_buf);
  302. }
  303. strstream::~strstream() {}
  304. strstreambuf* strstream::rdbuf() const {
  305. return __CONST_CAST(strstreambuf*,&_M_buf);
  306. }
  307. void strstream::freeze(bool freezeflag) {
  308. _M_buf.freeze(freezeflag);
  309. }
  310. int strstream::pcount() const {
  311. return _M_buf.pcount();
  312. }
  313. char* strstream::str() {
  314. return _M_buf.str();
  315. }
  316. _STLP_END_NAMESPACE
  317. // Local Variables:
  318. // mode:C++
  319. // End: