You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

952 lines
32 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. // This is a modified version of the std::basic_filebuf from libc++
  3. // Copyright 20XX LLVM
  4. // (http://libcxx.llvm.org/).
  5. // It allows one to create basic_filebuf from an existing FILE* handle or file
  6. // descriptor.
  7. //
  8. // This file is dual licensed under the MIT and the University of Illinois Open
  9. // Source License licenses. See LICENSE.TXT for details (included at the
  10. // bottom).
  11. ///////////////////////////////////////////////////////////////////////////////
  12. #ifndef KALDI_UTIL_BASIC_FILEBUF_H_
  13. #define KALDI_UTIL_BASIC_FILEBUF_H_
  14. ///////////////////////////////////////////////////////////////////////////////
  15. #include <algorithm>
  16. #include <cstdio>
  17. #include <cstring>
  18. #include <fstream>
  19. #include <memory>
  20. #include <string>
  21. #include <utility>
  22. ///////////////////////////////////////////////////////////////////////////////
  23. namespace kaldi {
  24. ///////////////////////////////////////////////////////////////////////////////
  25. template <typename CharT, typename Traits = std::char_traits<CharT> >
  26. class basic_filebuf : public std::basic_streambuf<CharT, Traits> {
  27. public:
  28. typedef CharT char_type;
  29. typedef Traits traits_type;
  30. typedef typename traits_type::int_type int_type;
  31. typedef typename traits_type::pos_type pos_type;
  32. typedef typename traits_type::off_type off_type;
  33. typedef typename traits_type::state_type state_type;
  34. basic_filebuf();
  35. basic_filebuf(basic_filebuf&& rhs);
  36. virtual ~basic_filebuf();
  37. basic_filebuf& operator=(basic_filebuf&& rhs);
  38. void swap(basic_filebuf& rhs);
  39. bool is_open() const;
  40. basic_filebuf* open(const char* s, std::ios_base::openmode mode);
  41. basic_filebuf* open(const std::string& s, std::ios_base::openmode mode);
  42. basic_filebuf* open(int fd, std::ios_base::openmode mode);
  43. basic_filebuf* open(FILE* f, std::ios_base::openmode mode);
  44. basic_filebuf* close();
  45. FILE* file() { return this->_M_file; }
  46. int fd() { return fileno(this->_M_file); }
  47. protected:
  48. int_type underflow() override;
  49. int_type pbackfail(int_type c = traits_type::eof()) override;
  50. int_type overflow(int_type c = traits_type::eof()) override;
  51. std::basic_streambuf<char_type, traits_type>* setbuf(
  52. char_type* s, std::streamsize n) override;
  53. pos_type seekoff(off_type off, std::ios_base::seekdir way,
  54. std::ios_base::openmode wch = std::ios_base::in |
  55. std::ios_base::out) override;
  56. pos_type seekpos(pos_type sp,
  57. std::ios_base::openmode wch = std::ios_base::in |
  58. std::ios_base::out) override;
  59. int sync() override;
  60. void imbue(const std::locale& loc) override;
  61. protected:
  62. char* _M_extbuf;
  63. const char* _M_extbufnext;
  64. const char* _M_extbufend;
  65. char _M_extbuf_min[8];
  66. size_t _M_ebs;
  67. char_type* _M_intbuf;
  68. size_t _M_ibs;
  69. FILE* _M_file;
  70. const std::codecvt<char_type, char, state_type>* _M_cv;
  71. state_type _M_st;
  72. state_type _M_st_last;
  73. std::ios_base::openmode _M_om;
  74. std::ios_base::openmode _M_cm;
  75. bool _M_owns_eb;
  76. bool _M_owns_ib;
  77. bool _M_always_noconv;
  78. const char* _M_get_mode(std::ios_base::openmode mode);
  79. bool _M_read_mode();
  80. void _M_write_mode();
  81. };
  82. ///////////////////////////////////////////////////////////////////////////////
  83. template <class CharT, class Traits>
  84. basic_filebuf<CharT, Traits>::basic_filebuf()
  85. : _M_extbuf(nullptr),
  86. _M_extbufnext(nullptr),
  87. _M_extbufend(nullptr),
  88. _M_ebs(0),
  89. _M_intbuf(nullptr),
  90. _M_ibs(0),
  91. _M_file(nullptr),
  92. _M_cv(nullptr),
  93. _M_st(),
  94. _M_st_last(),
  95. _M_om(std::ios_base::openmode(0)),
  96. _M_cm(std::ios_base::openmode(0)),
  97. _M_owns_eb(false),
  98. _M_owns_ib(false),
  99. _M_always_noconv(false) {
  100. if (std::has_facet<std::codecvt<char_type, char, state_type> >(
  101. this->getloc())) {
  102. _M_cv = &std::use_facet<std::codecvt<char_type, char, state_type> >(
  103. this->getloc());
  104. _M_always_noconv = _M_cv->always_noconv();
  105. }
  106. setbuf(0, 4096);
  107. }
  108. ///////////////////////////////////////////////////////////////////////////////
  109. template <class CharT, class Traits>
  110. basic_filebuf<CharT, Traits>::basic_filebuf(basic_filebuf&& rhs)
  111. : std::basic_streambuf<CharT, Traits>(rhs) {
  112. if (rhs._M_extbuf == rhs._M_extbuf_min) {
  113. _M_extbuf = _M_extbuf_min;
  114. _M_extbufnext = _M_extbuf + (rhs._M_extbufnext - rhs._M_extbuf);
  115. _M_extbufend = _M_extbuf + (rhs._M_extbufend - rhs._M_extbuf);
  116. } else {
  117. _M_extbuf = rhs._M_extbuf;
  118. _M_extbufnext = rhs._M_extbufnext;
  119. _M_extbufend = rhs._M_extbufend;
  120. }
  121. _M_ebs = rhs._M_ebs;
  122. _M_intbuf = rhs._M_intbuf;
  123. _M_ibs = rhs._M_ibs;
  124. _M_file = rhs._M_file;
  125. _M_cv = rhs._M_cv;
  126. _M_st = rhs._M_st;
  127. _M_st_last = rhs._M_st_last;
  128. _M_om = rhs._M_om;
  129. _M_cm = rhs._M_cm;
  130. _M_owns_eb = rhs._M_owns_eb;
  131. _M_owns_ib = rhs._M_owns_ib;
  132. _M_always_noconv = rhs._M_always_noconv;
  133. if (rhs.pbase()) {
  134. if (rhs.pbase() == rhs._M_intbuf)
  135. this->setp(_M_intbuf, _M_intbuf + (rhs.epptr() - rhs.pbase()));
  136. else
  137. this->setp(reinterpret_cast<char_type*>(_M_extbuf),
  138. reinterpret_cast<char_type*>(_M_extbuf) +
  139. (rhs.epptr() - rhs.pbase()));
  140. this->pbump(rhs.pptr() - rhs.pbase());
  141. } else if (rhs.eback()) {
  142. if (rhs.eback() == rhs._M_intbuf)
  143. this->setg(_M_intbuf, _M_intbuf + (rhs.gptr() - rhs.eback()),
  144. _M_intbuf + (rhs.egptr() - rhs.eback()));
  145. else
  146. this->setg(
  147. reinterpret_cast<char_type*>(_M_extbuf),
  148. reinterpret_cast<char_type*>(_M_extbuf) + (rhs.gptr() - rhs.eback()),
  149. reinterpret_cast<char_type*>(_M_extbuf) +
  150. (rhs.egptr() - rhs.eback()));
  151. }
  152. rhs._M_extbuf = nullptr;
  153. rhs._M_extbufnext = nullptr;
  154. rhs._M_extbufend = nullptr;
  155. rhs._M_ebs = 0;
  156. rhs._M_intbuf = nullptr;
  157. rhs._M_ibs = 0;
  158. rhs._M_file = nullptr;
  159. rhs._M_st = state_type();
  160. rhs._M_st_last = state_type();
  161. rhs._M_om = std::ios_base::openmode(0);
  162. rhs._M_cm = std::ios_base::openmode(0);
  163. rhs._M_owns_eb = false;
  164. rhs._M_owns_ib = false;
  165. rhs.setg(0, 0, 0);
  166. rhs.setp(0, 0);
  167. }
  168. ///////////////////////////////////////////////////////////////////////////////
  169. template <class CharT, class Traits>
  170. inline basic_filebuf<CharT, Traits>& basic_filebuf<CharT, Traits>::operator=(
  171. basic_filebuf&& rhs) {
  172. close();
  173. swap(rhs);
  174. return *this;
  175. }
  176. ///////////////////////////////////////////////////////////////////////////////
  177. template <class CharT, class Traits>
  178. basic_filebuf<CharT, Traits>::~basic_filebuf() {
  179. // try
  180. // {
  181. // close();
  182. // }
  183. // catch (...)
  184. // {
  185. // }
  186. if (_M_owns_eb) delete[] _M_extbuf;
  187. if (_M_owns_ib) delete[] _M_intbuf;
  188. }
  189. ///////////////////////////////////////////////////////////////////////////////
  190. template <class CharT, class Traits>
  191. void basic_filebuf<CharT, Traits>::swap(basic_filebuf& rhs) {
  192. std::basic_streambuf<char_type, traits_type>::swap(rhs);
  193. if (_M_extbuf != _M_extbuf_min && rhs._M_extbuf != rhs._M_extbuf_min) {
  194. std::swap(_M_extbuf, rhs._M_extbuf);
  195. std::swap(_M_extbufnext, rhs._M_extbufnext);
  196. std::swap(_M_extbufend, rhs._M_extbufend);
  197. } else {
  198. ptrdiff_t ln = _M_extbufnext - _M_extbuf;
  199. ptrdiff_t le = _M_extbufend - _M_extbuf;
  200. ptrdiff_t rn = rhs._M_extbufnext - rhs._M_extbuf;
  201. ptrdiff_t re = rhs._M_extbufend - rhs._M_extbuf;
  202. if (_M_extbuf == _M_extbuf_min && rhs._M_extbuf != rhs._M_extbuf_min) {
  203. _M_extbuf = rhs._M_extbuf;
  204. rhs._M_extbuf = rhs._M_extbuf_min;
  205. } else if (_M_extbuf != _M_extbuf_min &&
  206. rhs._M_extbuf == rhs._M_extbuf_min) {
  207. rhs._M_extbuf = _M_extbuf;
  208. _M_extbuf = _M_extbuf_min;
  209. }
  210. _M_extbufnext = _M_extbuf + rn;
  211. _M_extbufend = _M_extbuf + re;
  212. rhs._M_extbufnext = rhs._M_extbuf + ln;
  213. rhs._M_extbufend = rhs._M_extbuf + le;
  214. }
  215. std::swap(_M_ebs, rhs._M_ebs);
  216. std::swap(_M_intbuf, rhs._M_intbuf);
  217. std::swap(_M_ibs, rhs._M_ibs);
  218. std::swap(_M_file, rhs._M_file);
  219. std::swap(_M_cv, rhs._M_cv);
  220. std::swap(_M_st, rhs._M_st);
  221. std::swap(_M_st_last, rhs._M_st_last);
  222. std::swap(_M_om, rhs._M_om);
  223. std::swap(_M_cm, rhs._M_cm);
  224. std::swap(_M_owns_eb, rhs._M_owns_eb);
  225. std::swap(_M_owns_ib, rhs._M_owns_ib);
  226. std::swap(_M_always_noconv, rhs._M_always_noconv);
  227. if (this->eback() == reinterpret_cast<char_type*>(rhs._M_extbuf_min)) {
  228. ptrdiff_t n = this->gptr() - this->eback();
  229. ptrdiff_t e = this->egptr() - this->eback();
  230. this->setg(reinterpret_cast<char_type*>(_M_extbuf_min),
  231. reinterpret_cast<char_type*>(_M_extbuf_min) + n,
  232. reinterpret_cast<char_type*>(_M_extbuf_min) + e);
  233. } else if (this->pbase() == reinterpret_cast<char_type*>(rhs._M_extbuf_min)) {
  234. ptrdiff_t n = this->pptr() - this->pbase();
  235. ptrdiff_t e = this->epptr() - this->pbase();
  236. this->setp(reinterpret_cast<char_type*>(_M_extbuf_min),
  237. reinterpret_cast<char_type*>(_M_extbuf_min) + e);
  238. this->pbump(n);
  239. }
  240. if (rhs.eback() == reinterpret_cast<char_type*>(_M_extbuf_min)) {
  241. ptrdiff_t n = rhs.gptr() - rhs.eback();
  242. ptrdiff_t e = rhs.egptr() - rhs.eback();
  243. rhs.setg(reinterpret_cast<char_type*>(rhs._M_extbuf_min),
  244. reinterpret_cast<char_type*>(rhs._M_extbuf_min) + n,
  245. reinterpret_cast<char_type*>(rhs._M_extbuf_min) + e);
  246. } else if (rhs.pbase() == reinterpret_cast<char_type*>(_M_extbuf_min)) {
  247. ptrdiff_t n = rhs.pptr() - rhs.pbase();
  248. ptrdiff_t e = rhs.epptr() - rhs.pbase();
  249. rhs.setp(reinterpret_cast<char_type*>(rhs._M_extbuf_min),
  250. reinterpret_cast<char_type*>(rhs._M_extbuf_min) + e);
  251. rhs.pbump(n);
  252. }
  253. }
  254. ///////////////////////////////////////////////////////////////////////////////
  255. template <class CharT, class Traits>
  256. inline void swap(basic_filebuf<CharT, Traits>& x,
  257. basic_filebuf<CharT, Traits>& y) {
  258. x.swap(y);
  259. }
  260. ///////////////////////////////////////////////////////////////////////////////
  261. template <class CharT, class Traits>
  262. inline bool basic_filebuf<CharT, Traits>::is_open() const {
  263. return _M_file != nullptr;
  264. }
  265. ///////////////////////////////////////////////////////////////////////////////
  266. template <class CharT, class Traits>
  267. const char* basic_filebuf<CharT, Traits>::_M_get_mode(
  268. std::ios_base::openmode mode) {
  269. switch ((mode & ~std::ios_base::ate) | 0) {
  270. case std::ios_base::out:
  271. case std::ios_base::out | std::ios_base::trunc:
  272. return "w";
  273. case std::ios_base::out | std::ios_base::app:
  274. case std::ios_base::app:
  275. return "a";
  276. break;
  277. case std::ios_base::in:
  278. return "r";
  279. case std::ios_base::in | std::ios_base::out:
  280. return "r+";
  281. case std::ios_base::in | std::ios_base::out | std::ios_base::trunc:
  282. return "w+";
  283. case std::ios_base::in | std::ios_base::out | std::ios_base::app:
  284. case std::ios_base::in | std::ios_base::app:
  285. return "a+";
  286. case std::ios_base::out | std::ios_base::binary:
  287. case std::ios_base::out | std::ios_base::trunc | std::ios_base::binary:
  288. return "wb";
  289. case std::ios_base::out | std::ios_base::app | std::ios_base::binary:
  290. case std::ios_base::app | std::ios_base::binary:
  291. return "ab";
  292. case std::ios_base::in | std::ios_base::binary:
  293. return "rb";
  294. case std::ios_base::in | std::ios_base::out | std::ios_base::binary:
  295. return "r+b";
  296. case std::ios_base::in | std::ios_base::out | std::ios_base::trunc |
  297. std::ios_base::binary:
  298. return "w+b";
  299. case std::ios_base::in | std::ios_base::out | std::ios_base::app |
  300. std::ios_base::binary:
  301. case std::ios_base::in | std::ios_base::app | std::ios_base::binary:
  302. return "a+b";
  303. default:
  304. return nullptr;
  305. }
  306. }
  307. ///////////////////////////////////////////////////////////////////////////////
  308. template <class CharT, class Traits>
  309. basic_filebuf<CharT, Traits>* basic_filebuf<CharT, Traits>::open(
  310. const char* s, std::ios_base::openmode mode) {
  311. basic_filebuf<CharT, Traits>* rt = nullptr;
  312. if (_M_file == nullptr) {
  313. const char* md = _M_get_mode(mode);
  314. if (md) {
  315. _M_file = fopen(s, md);
  316. if (_M_file) {
  317. rt = this;
  318. _M_om = mode;
  319. if (mode & std::ios_base::ate) {
  320. if (fseek(_M_file, 0, SEEK_END)) {
  321. fclose(_M_file);
  322. _M_file = nullptr;
  323. rt = nullptr;
  324. }
  325. }
  326. }
  327. }
  328. }
  329. return rt;
  330. }
  331. ///////////////////////////////////////////////////////////////////////////////
  332. template <class CharT, class Traits>
  333. inline basic_filebuf<CharT, Traits>* basic_filebuf<CharT, Traits>::open(
  334. const std::string& s, std::ios_base::openmode mode) {
  335. return open(s.c_str(), mode);
  336. }
  337. ///////////////////////////////////////////////////////////////////////////////
  338. template <class CharT, class Traits>
  339. basic_filebuf<CharT, Traits>* basic_filebuf<CharT, Traits>::open(
  340. int fd, std::ios_base::openmode mode) {
  341. const char* md = this->_M_get_mode(mode);
  342. if (md) {
  343. this->_M_file = fdopen(fd, md);
  344. this->_M_om = mode;
  345. return this;
  346. } else {
  347. return nullptr;
  348. }
  349. }
  350. ///////////////////////////////////////////////////////////////////////////////
  351. template <class CharT, class Traits>
  352. basic_filebuf<CharT, Traits>* basic_filebuf<CharT, Traits>::open(
  353. FILE* f, std::ios_base::openmode mode) {
  354. this->_M_file = f;
  355. this->_M_om = mode;
  356. return this;
  357. }
  358. ///////////////////////////////////////////////////////////////////////////////
  359. template <class CharT, class Traits>
  360. basic_filebuf<CharT, Traits>* basic_filebuf<CharT, Traits>::close() {
  361. basic_filebuf<CharT, Traits>* rt = nullptr;
  362. if (_M_file) {
  363. rt = this;
  364. std::unique_ptr<FILE, int (*)(FILE*)> h(_M_file, fclose);
  365. if (sync()) rt = nullptr;
  366. if (fclose(h.release()) == 0)
  367. _M_file = nullptr;
  368. else
  369. rt = nullptr;
  370. }
  371. return rt;
  372. }
  373. ///////////////////////////////////////////////////////////////////////////////
  374. template <class CharT, class Traits>
  375. typename basic_filebuf<CharT, Traits>::int_type
  376. basic_filebuf<CharT, Traits>::underflow() {
  377. if (_M_file == nullptr) return traits_type::eof();
  378. bool initial = _M_read_mode();
  379. char_type buf;
  380. if (this->gptr() == nullptr) this->setg(&buf, &buf + 1, &buf + 1);
  381. const size_t unget_sz =
  382. initial ? 0 : std::min<size_t>((this->egptr() - this->eback()) / 2, 4);
  383. int_type c = traits_type::eof();
  384. if (this->gptr() == this->egptr()) {
  385. memmove(this->eback(), this->egptr() - unget_sz,
  386. unget_sz * sizeof(char_type));
  387. if (_M_always_noconv) {
  388. size_t nmemb =
  389. static_cast<size_t>(this->egptr() - this->eback() - unget_sz);
  390. nmemb = fread(this->eback() + unget_sz, 1, nmemb, _M_file);
  391. if (nmemb != 0) {
  392. this->setg(this->eback(), this->eback() + unget_sz,
  393. this->eback() + unget_sz + nmemb);
  394. c = traits_type::to_int_type(*this->gptr());
  395. }
  396. } else {
  397. memmove(_M_extbuf, _M_extbufnext, _M_extbufend - _M_extbufnext);
  398. _M_extbufnext = _M_extbuf + (_M_extbufend - _M_extbufnext);
  399. _M_extbufend =
  400. _M_extbuf +
  401. (_M_extbuf == _M_extbuf_min ? sizeof(_M_extbuf_min) : _M_ebs);
  402. size_t nmemb =
  403. std::min(static_cast<size_t>(_M_ibs - unget_sz),
  404. static_cast<size_t>(_M_extbufend - _M_extbufnext));
  405. std::codecvt_base::result r;
  406. _M_st_last = _M_st;
  407. size_t nr =
  408. fread(reinterpret_cast<void*>(const_cast<char_type*>(_M_extbufnext)),
  409. 1, nmemb, _M_file);
  410. if (nr != 0) {
  411. if (!_M_cv) throw std::bad_cast();
  412. _M_extbufend = _M_extbufnext + nr;
  413. char_type* inext;
  414. r = _M_cv->in(_M_st, _M_extbuf, _M_extbufend, _M_extbufnext,
  415. this->eback() + unget_sz, this->eback() + _M_ibs, inext);
  416. if (r == std::codecvt_base::noconv) {
  417. this->setg(reinterpret_cast<char_type*>(_M_extbuf),
  418. reinterpret_cast<char_type*>(_M_extbuf),
  419. const_cast<char_type*>(_M_extbufend));
  420. c = traits_type::to_int_type(*this->gptr());
  421. } else if (inext != this->eback() + unget_sz) {
  422. this->setg(this->eback(), this->eback() + unget_sz, inext);
  423. c = traits_type::to_int_type(*this->gptr());
  424. }
  425. }
  426. }
  427. } else {
  428. c = traits_type::to_int_type(*this->gptr());
  429. }
  430. if (this->eback() == &buf) this->setg(0, 0, 0);
  431. return c;
  432. }
  433. ///////////////////////////////////////////////////////////////////////////////
  434. template <class CharT, class Traits>
  435. typename basic_filebuf<CharT, Traits>::int_type
  436. basic_filebuf<CharT, Traits>::pbackfail(int_type c) {
  437. if (_M_file && this->eback() < this->gptr()) {
  438. if (traits_type::eq_int_type(c, traits_type::eof())) {
  439. this->gbump(-1);
  440. return traits_type::not_eof(c);
  441. }
  442. if ((_M_om & std::ios_base::out) ||
  443. traits_type::eq(traits_type::to_char_type(c), this->gptr()[-1])) {
  444. this->gbump(-1);
  445. *this->gptr() = traits_type::to_char_type(c);
  446. return c;
  447. }
  448. }
  449. return traits_type::eof();
  450. }
  451. ///////////////////////////////////////////////////////////////////////////////
  452. template <class CharT, class Traits>
  453. typename basic_filebuf<CharT, Traits>::int_type
  454. basic_filebuf<CharT, Traits>::overflow(int_type c) {
  455. if (_M_file == nullptr) return traits_type::eof();
  456. _M_write_mode();
  457. char_type buf;
  458. char_type* pb_save = this->pbase();
  459. char_type* epb_save = this->epptr();
  460. if (!traits_type::eq_int_type(c, traits_type::eof())) {
  461. if (this->pptr() == nullptr) this->setp(&buf, &buf + 1);
  462. *this->pptr() = traits_type::to_char_type(c);
  463. this->pbump(1);
  464. }
  465. if (this->pptr() != this->pbase()) {
  466. if (_M_always_noconv) {
  467. size_t nmemb = static_cast<size_t>(this->pptr() - this->pbase());
  468. if (fwrite(this->pbase(), sizeof(char_type), nmemb, _M_file) != nmemb)
  469. return traits_type::eof();
  470. } else {
  471. char* extbe = _M_extbuf;
  472. std::codecvt_base::result r;
  473. do {
  474. if (!_M_cv) throw std::bad_cast();
  475. const char_type* e;
  476. r = _M_cv->out(_M_st, this->pbase(), this->pptr(), e, _M_extbuf,
  477. _M_extbuf + _M_ebs, extbe);
  478. if (e == this->pbase()) return traits_type::eof();
  479. if (r == std::codecvt_base::noconv) {
  480. size_t nmemb = static_cast<size_t>(this->pptr() - this->pbase());
  481. if (fwrite(this->pbase(), 1, nmemb, _M_file) != nmemb)
  482. return traits_type::eof();
  483. } else if (r == std::codecvt_base::ok ||
  484. r == std::codecvt_base::partial) {
  485. size_t nmemb = static_cast<size_t>(extbe - _M_extbuf);
  486. if (fwrite(_M_extbuf, 1, nmemb, _M_file) != nmemb)
  487. return traits_type::eof();
  488. if (r == std::codecvt_base::partial) {
  489. this->setp(const_cast<char_type*>(e), this->pptr());
  490. this->pbump(this->epptr() - this->pbase());
  491. }
  492. } else {
  493. return traits_type::eof();
  494. }
  495. } while (r == std::codecvt_base::partial);
  496. }
  497. this->setp(pb_save, epb_save);
  498. }
  499. return traits_type::not_eof(c);
  500. }
  501. ///////////////////////////////////////////////////////////////////////////////
  502. template <class CharT, class Traits>
  503. std::basic_streambuf<CharT, Traits>* basic_filebuf<CharT, Traits>::setbuf(
  504. char_type* s, std::streamsize n) {
  505. this->setg(0, 0, 0);
  506. this->setp(0, 0);
  507. if (_M_owns_eb) delete[] _M_extbuf;
  508. if (_M_owns_ib) delete[] _M_intbuf;
  509. _M_ebs = n;
  510. if (_M_ebs > sizeof(_M_extbuf_min)) {
  511. if (_M_always_noconv && s) {
  512. _M_extbuf = reinterpret_cast<char*>(s);
  513. _M_owns_eb = false;
  514. } else {
  515. _M_extbuf = new char[_M_ebs];
  516. _M_owns_eb = true;
  517. }
  518. } else {
  519. _M_extbuf = _M_extbuf_min;
  520. _M_ebs = sizeof(_M_extbuf_min);
  521. _M_owns_eb = false;
  522. }
  523. if (!_M_always_noconv) {
  524. _M_ibs = std::max<std::streamsize>(n, sizeof(_M_extbuf_min));
  525. if (s && _M_ibs >= sizeof(_M_extbuf_min)) {
  526. _M_intbuf = s;
  527. _M_owns_ib = false;
  528. } else {
  529. _M_intbuf = new char_type[_M_ibs];
  530. _M_owns_ib = true;
  531. }
  532. } else {
  533. _M_ibs = 0;
  534. _M_intbuf = 0;
  535. _M_owns_ib = false;
  536. }
  537. return this;
  538. }
  539. ///////////////////////////////////////////////////////////////////////////////
  540. template <class CharT, class Traits>
  541. typename basic_filebuf<CharT, Traits>::pos_type
  542. basic_filebuf<CharT, Traits>::seekoff(off_type off, std::ios_base::seekdir way,
  543. std::ios_base::openmode) {
  544. if (!_M_cv) throw std::bad_cast();
  545. int width = _M_cv->encoding();
  546. if (_M_file == nullptr || (width <= 0 && off != 0) || sync())
  547. return pos_type(off_type(-1));
  548. // width > 0 || off == 0
  549. int whence;
  550. switch (way) {
  551. case std::ios_base::beg:
  552. whence = SEEK_SET;
  553. break;
  554. case std::ios_base::cur:
  555. whence = SEEK_CUR;
  556. break;
  557. case std::ios_base::end:
  558. whence = SEEK_END;
  559. break;
  560. default:
  561. return pos_type(off_type(-1));
  562. }
  563. #if _WIN32
  564. if (fseek(_M_file, width > 0 ? width * off : 0, whence))
  565. return pos_type(off_type(-1));
  566. pos_type r = ftell(_M_file);
  567. #else
  568. if (fseeko(_M_file, width > 0 ? width * off : 0, whence))
  569. return pos_type(off_type(-1));
  570. pos_type r = ftello(_M_file);
  571. #endif
  572. r.state(_M_st);
  573. return r;
  574. }
  575. ///////////////////////////////////////////////////////////////////////////////
  576. template <class CharT, class Traits>
  577. typename basic_filebuf<CharT, Traits>::pos_type
  578. basic_filebuf<CharT, Traits>::seekpos(pos_type sp, std::ios_base::openmode) {
  579. if (_M_file == nullptr || sync()) return pos_type(off_type(-1));
  580. #if _WIN32
  581. if (fseek(_M_file, sp, SEEK_SET)) return pos_type(off_type(-1));
  582. #else
  583. if (fseeko(_M_file, sp, SEEK_SET)) return pos_type(off_type(-1));
  584. #endif
  585. _M_st = sp.state();
  586. return sp;
  587. }
  588. ///////////////////////////////////////////////////////////////////////////////
  589. template <class CharT, class Traits>
  590. int basic_filebuf<CharT, Traits>::sync() {
  591. if (_M_file == nullptr) return 0;
  592. if (!_M_cv) throw std::bad_cast();
  593. if (_M_cm & std::ios_base::out) {
  594. if (this->pptr() != this->pbase())
  595. if (overflow() == traits_type::eof()) return -1;
  596. std::codecvt_base::result r;
  597. do {
  598. char* extbe;
  599. r = _M_cv->unshift(_M_st, _M_extbuf, _M_extbuf + _M_ebs, extbe);
  600. size_t nmemb = static_cast<size_t>(extbe - _M_extbuf);
  601. if (fwrite(_M_extbuf, 1, nmemb, _M_file) != nmemb) return -1;
  602. } while (r == std::codecvt_base::partial);
  603. if (r == std::codecvt_base::error) return -1;
  604. if (fflush(_M_file)) return -1;
  605. } else if (_M_cm & std::ios_base::in) {
  606. off_type c;
  607. state_type state = _M_st_last;
  608. bool update_st = false;
  609. if (_M_always_noconv) {
  610. c = this->egptr() - this->gptr();
  611. } else {
  612. int width = _M_cv->encoding();
  613. c = _M_extbufend - _M_extbufnext;
  614. if (width > 0) {
  615. c += width * (this->egptr() - this->gptr());
  616. } else {
  617. if (this->gptr() != this->egptr()) {
  618. const int off = _M_cv->length(state, _M_extbuf, _M_extbufnext,
  619. this->gptr() - this->eback());
  620. c += _M_extbufnext - _M_extbuf - off;
  621. update_st = true;
  622. }
  623. }
  624. }
  625. #if _WIN32
  626. if (fseek(_M_file_, -c, SEEK_CUR)) return -1;
  627. #else
  628. if (fseeko(_M_file, -c, SEEK_CUR)) return -1;
  629. #endif
  630. if (update_st) _M_st = state;
  631. _M_extbufnext = _M_extbufend = _M_extbuf;
  632. this->setg(0, 0, 0);
  633. _M_cm = std::ios_base::openmode(0);
  634. }
  635. return 0;
  636. }
  637. ///////////////////////////////////////////////////////////////////////////////
  638. template <class CharT, class Traits>
  639. void basic_filebuf<CharT, Traits>::imbue(const std::locale& loc) {
  640. sync();
  641. _M_cv = &std::use_facet<std::codecvt<char_type, char, state_type> >(loc);
  642. bool old_anc = _M_always_noconv;
  643. _M_always_noconv = _M_cv->always_noconv();
  644. if (old_anc != _M_always_noconv) {
  645. this->setg(0, 0, 0);
  646. this->setp(0, 0);
  647. // invariant, char_type is char, else we couldn't get here
  648. // need to dump _M_intbuf
  649. if (_M_always_noconv) {
  650. if (_M_owns_eb) delete[] _M_extbuf;
  651. _M_owns_eb = _M_owns_ib;
  652. _M_ebs = _M_ibs;
  653. _M_extbuf = reinterpret_cast<char*>(_M_intbuf);
  654. _M_ibs = 0;
  655. _M_intbuf = nullptr;
  656. _M_owns_ib = false;
  657. } else { // need to obtain an _M_intbuf.
  658. // If _M_extbuf is user-supplied, use it, else new _M_intbuf
  659. if (!_M_owns_eb && _M_extbuf != _M_extbuf_min) {
  660. _M_ibs = _M_ebs;
  661. _M_intbuf = reinterpret_cast<char_type*>(_M_extbuf);
  662. _M_owns_ib = false;
  663. _M_extbuf = new char[_M_ebs];
  664. _M_owns_eb = true;
  665. } else {
  666. _M_ibs = _M_ebs;
  667. _M_intbuf = new char_type[_M_ibs];
  668. _M_owns_ib = true;
  669. }
  670. }
  671. }
  672. }
  673. ///////////////////////////////////////////////////////////////////////////////
  674. template <class CharT, class Traits>
  675. bool basic_filebuf<CharT, Traits>::_M_read_mode() {
  676. if (!(_M_cm & std::ios_base::in)) {
  677. this->setp(0, 0);
  678. if (_M_always_noconv)
  679. this->setg(reinterpret_cast<char_type*>(_M_extbuf),
  680. reinterpret_cast<char_type*>(_M_extbuf) + _M_ebs,
  681. reinterpret_cast<char_type*>(_M_extbuf) + _M_ebs);
  682. else
  683. this->setg(_M_intbuf, _M_intbuf + _M_ibs, _M_intbuf + _M_ibs);
  684. _M_cm = std::ios_base::in;
  685. return true;
  686. }
  687. return false;
  688. }
  689. ///////////////////////////////////////////////////////////////////////////////
  690. template <class CharT, class Traits>
  691. void basic_filebuf<CharT, Traits>::_M_write_mode() {
  692. if (!(_M_cm & std::ios_base::out)) {
  693. this->setg(0, 0, 0);
  694. if (_M_ebs > sizeof(_M_extbuf_min)) {
  695. if (_M_always_noconv)
  696. this->setp(reinterpret_cast<char_type*>(_M_extbuf),
  697. reinterpret_cast<char_type*>(_M_extbuf) + (_M_ebs - 1));
  698. else
  699. this->setp(_M_intbuf, _M_intbuf + (_M_ibs - 1));
  700. } else {
  701. this->setp(0, 0);
  702. }
  703. _M_cm = std::ios_base::out;
  704. }
  705. }
  706. ///////////////////////////////////////////////////////////////////////////////
  707. } // namespace kaldi
  708. ///////////////////////////////////////////////////////////////////////////////
  709. #endif // KALDI_UTIL_BASIC_FILEBUF_H_
  710. ///////////////////////////////////////////////////////////////////////////////
  711. /*
  712. * ============================================================================
  713. * libc++ License
  714. * ============================================================================
  715. *
  716. * The libc++ library is dual licensed under both the University of Illinois
  717. * "BSD-Like" license and the MIT license. As a user of this code you may
  718. * choose to use it under either license. As a contributor, you agree to allow
  719. * your code to be used under both.
  720. *
  721. * Full text of the relevant licenses is included below.
  722. *
  723. * ============================================================================
  724. *
  725. * University of Illinois/NCSA
  726. * Open Source License
  727. *
  728. * Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT (included
  729. * below)
  730. *
  731. * All rights reserved.
  732. *
  733. * Developed by:
  734. *
  735. * LLVM Team
  736. *
  737. * University of Illinois at Urbana-Champaign
  738. *
  739. * http://llvm.org
  740. *
  741. * Permission is hereby granted, free of charge, to any person obtaining a copy
  742. * of this software and associated documentation files (the "Software"), to deal
  743. * with the Software without restriction, including without limitation the
  744. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  745. * sell copies of the Software, and to permit persons to whom the Software is
  746. * furnished to do so, subject to the following conditions:
  747. *
  748. * * Redistributions of source code must retain the above copyright notice,
  749. * this list of conditions and the following disclaimers.
  750. *
  751. * * Redistributions in binary form must reproduce the above copyright
  752. * notice, this list of conditions and the following disclaimers in the
  753. * documentation and/or other materials provided with the distribution.
  754. *
  755. * * Neither the names of the LLVM Team, University of Illinois at
  756. * Urbana-Champaign, nor the names of its contributors may be used to
  757. * endorse or promote products derived from this Software without specific
  758. * prior written permission.
  759. *
  760. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  761. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  762. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  763. * CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  764. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  765. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH
  766. * THE SOFTWARE.
  767. *
  768. * ==============================================================================
  769. *
  770. * Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT (included
  771. * below)
  772. *
  773. * Permission is hereby granted, free of charge, to any person obtaining a copy
  774. * of this software and associated documentation files (the "Software"), to deal
  775. * in the Software without restriction, including without limitation the rights
  776. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  777. * copies of the Software, and to permit persons to whom the Software is
  778. * furnished to do so, subject to the following conditions:
  779. *
  780. * The above copyright notice and this permission notice shall be included in
  781. * all copies or substantial portions of the Software.
  782. *
  783. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  784. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  785. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  786. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  787. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  788. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  789. * THE SOFTWARE.
  790. *
  791. * ==============================================================================
  792. *
  793. * This file is a partial list of people who have contributed to the LLVM/libc++
  794. * project. If you have contributed a patch or made some other contribution to
  795. * LLVM/libc++, please submit a patch to this file to add yourself, and it will
  796. * be done!
  797. *
  798. * The list is sorted by surname and formatted to allow easy grepping and
  799. * beautification by scripts. The fields are: name (N), email (E), web-address
  800. * (W), PGP key ID and fingerprint (P), description (D), and snail-mail address
  801. * (S).
  802. *
  803. * N: Saleem Abdulrasool
  804. * E: compnerd@compnerd.org
  805. * D: Minor patches and Linux fixes.
  806. *
  807. * N: Dimitry Andric
  808. * E: dimitry@andric.com
  809. * D: Visibility fixes, minor FreeBSD portability patches.
  810. *
  811. * N: Holger Arnold
  812. * E: holgerar@gmail.com
  813. * D: Minor fix.
  814. *
  815. * N: Ruben Van Boxem
  816. * E: vanboxem dot ruben at gmail dot com
  817. * D: Initial Windows patches.
  818. *
  819. * N: David Chisnall
  820. * E: theraven at theravensnest dot org
  821. * D: FreeBSD and Solaris ports, libcxxrt support, some atomics work.
  822. *
  823. * N: Marshall Clow
  824. * E: mclow.lists@gmail.com
  825. * E: marshall@idio.com
  826. * D: C++14 support, patches and bug fixes.
  827. *
  828. * N: Bill Fisher
  829. * E: william.w.fisher@gmail.com
  830. * D: Regex bug fixes.
  831. *
  832. * N: Matthew Dempsky
  833. * E: matthew@dempsky.org
  834. * D: Minor patches and bug fixes.
  835. *
  836. * N: Google Inc.
  837. * D: Copyright owner and contributor of the CityHash algorithm
  838. *
  839. * N: Howard Hinnant
  840. * E: hhinnant@apple.com
  841. * D: Architect and primary author of libc++
  842. *
  843. * N: Hyeon-bin Jeong
  844. * E: tuhertz@gmail.com
  845. * D: Minor patches and bug fixes.
  846. *
  847. * N: Argyrios Kyrtzidis
  848. * E: kyrtzidis@apple.com
  849. * D: Bug fixes.
  850. *
  851. * N: Bruce Mitchener, Jr.
  852. * E: bruce.mitchener@gmail.com
  853. * D: Emscripten-related changes.
  854. *
  855. * N: Michel Morin
  856. * E: mimomorin@gmail.com
  857. * D: Minor patches to is_convertible.
  858. *
  859. * N: Andrew Morrow
  860. * E: andrew.c.morrow@gmail.com
  861. * D: Minor patches and Linux fixes.
  862. *
  863. * N: Arvid Picciani
  864. * E: aep at exys dot org
  865. * D: Minor patches and musl port.
  866. *
  867. * N: Bjorn Reese
  868. * E: breese@users.sourceforge.net
  869. * D: Initial regex prototype
  870. *
  871. * N: Nico Rieck
  872. * E: nico.rieck@gmail.com
  873. * D: Windows fixes
  874. *
  875. * N: Jonathan Sauer
  876. * D: Minor patches, mostly related to constexpr
  877. *
  878. * N: Craig Silverstein
  879. * E: csilvers@google.com
  880. * D: Implemented Cityhash as the string hash function on 64-bit machines
  881. *
  882. * N: Richard Smith
  883. * D: Minor patches.
  884. *
  885. * N: Joerg Sonnenberger
  886. * E: joerg@NetBSD.org
  887. * D: NetBSD port.
  888. *
  889. * N: Stephan Tolksdorf
  890. * E: st@quanttec.com
  891. * D: Minor <atomic> fix
  892. *
  893. * N: Michael van der Westhuizen
  894. * E: r1mikey at gmail dot com
  895. *
  896. * N: Klaas de Vries
  897. * E: klaas at klaasgaaf dot nl
  898. * D: Minor bug fix.
  899. *
  900. * N: Zhang Xiongpang
  901. * E: zhangxiongpang@gmail.com
  902. * D: Minor patches and bug fixes.
  903. *
  904. * N: Xing Xue
  905. * E: xingxue@ca.ibm.com
  906. * D: AIX port
  907. *
  908. * N: Zhihao Yuan
  909. * E: lichray@gmail.com
  910. * D: Standard compatibility fixes.
  911. *
  912. * N: Jeffrey Yasskin
  913. * E: jyasskin@gmail.com
  914. * E: jyasskin@google.com
  915. * D: Linux fixes.
  916. */