Build tool
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.

bufio.h 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. #pragma once
  2. #include <iostream>
  3. #include <fstream>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. namespace bufio {
  7. class IStream {
  8. public:
  9. virtual size_t read(char *buf, size_t maxlen) = 0;
  10. };
  11. class IFStream: public IStream {
  12. public:
  13. IFStream(const char *path);
  14. IFStream(const std::string &path): IFStream(path.c_str()) {}
  15. size_t read(char *buf, size_t maxlen) override;
  16. private:
  17. std::ifstream is_;
  18. };
  19. class ISStream: public IStream {
  20. public:
  21. ISStream(std::string str): str_(std::move(str)) {}
  22. size_t read(char *buf, size_t maxlen) override;
  23. private:
  24. size_t idx_ = 0;
  25. const std::string str_;
  26. };
  27. class OStream {
  28. public:
  29. virtual void write(const char *buf, size_t len) = 0;
  30. };
  31. class OFStream: public OStream {
  32. public:
  33. OFStream(const char *path);
  34. OFStream(const std::string &path): OFStream(path.c_str()) {}
  35. void write(const char *buf, size_t len) override;
  36. private:
  37. std::ofstream os_;
  38. };
  39. template<typename IS = IStream, size_t bufsiz = 1024>
  40. class IBuf {
  41. public:
  42. IBuf(IS &is): is_(is) {}
  43. char get();
  44. int peek(size_t count = 1);
  45. private:
  46. IS &is_;
  47. char buf_[bufsiz];
  48. size_t idx_ = 0;
  49. size_t len_ = 0;
  50. };
  51. template<typename OS = OStream, size_t bufsiz = 1024>
  52. class OBuf {
  53. public:
  54. OBuf(OS &os): os_(os) {}
  55. ~OBuf();
  56. void put(char ch);
  57. void put(const char *str, size_t len);
  58. void put(const char *str) { put(str, strlen(str)); }
  59. void put(const std::string &str) { put(str.c_str(), str.size()); }
  60. private:
  61. OS &os_;
  62. char buf_[bufsiz];
  63. size_t idx_ = 0;
  64. };
  65. /*
  66. * IFStream
  67. */
  68. inline IFStream::IFStream(const char *path) {
  69. is_.exceptions(std::ifstream::badbit);
  70. is_.open(path);
  71. if (!is_.good()) {
  72. throw std::system_error(errno, std::generic_category(), path);
  73. }
  74. }
  75. inline size_t IFStream::read(char *buf, size_t maxlen) {
  76. is_.read(buf, maxlen);
  77. return is_.gcount();
  78. }
  79. /*
  80. * ISStream
  81. */
  82. inline size_t ISStream::read(char *buf, size_t maxlen) {
  83. size_t left = str_.size() - idx_;
  84. size_t len = maxlen < left ? maxlen : left;
  85. idx_ += len;
  86. memcpy(buf, str_.c_str(), len);
  87. return len;
  88. }
  89. /*
  90. * OFStream
  91. */
  92. inline OFStream::OFStream(const char *path) {
  93. os_.exceptions(std::ofstream::badbit);
  94. os_.open(path);
  95. if (!os_.good()) {
  96. throw std::system_error(errno, std::generic_category(), path);
  97. }
  98. }
  99. inline void OFStream::write(const char *buf, size_t len) {
  100. os_.write(buf, len);
  101. }
  102. /*
  103. * IBuf
  104. */
  105. template<typename IS, size_t bufsiz>
  106. inline char IBuf<IS, bufsiz>::get() {
  107. if (idx_ < len_) {
  108. return buf_[idx_++];
  109. }
  110. idx_ = 0;
  111. len_ = is_.read(buf_, sizeof(buf_));
  112. if (len_ == 0) {
  113. return EOF;
  114. }
  115. return buf_[idx_++];
  116. }
  117. template<typename IS, size_t bufsiz>
  118. inline int IBuf<IS, bufsiz>::peek(size_t count) {
  119. size_t offset = count - 1;
  120. if (idx_ + offset < len_) {
  121. return buf_[idx_ + offset];
  122. } else {
  123. len_ -= idx_;
  124. memmove(buf_, buf_ + idx_, len_);
  125. idx_ = 0;
  126. len_ += is_.read(buf_ + len_, sizeof(buf_) - len_);
  127. if (len_ <= offset) {
  128. return EOF;
  129. }
  130. return buf_[idx_ + offset];
  131. }
  132. }
  133. /*
  134. * OBuf
  135. */
  136. template<typename OS, size_t bufsiz>
  137. inline OBuf<OS, bufsiz>::~OBuf() {
  138. if (idx_ > 0) {
  139. os_.write(buf_, idx_);
  140. }
  141. }
  142. template<typename OS, size_t bufsiz>
  143. inline void OBuf<OS, bufsiz>::put(char ch) {
  144. buf_[idx_++] = ch;
  145. if (idx_ == sizeof(buf_)) {
  146. os_.write(buf_, sizeof(buf_));
  147. idx_ = 0;
  148. }
  149. }
  150. template<typename OS, size_t bufsiz>
  151. inline void OBuf<OS, bufsiz>::put(const char *str, size_t len) {
  152. size_t w = sizeof(buf_) - idx_ - 1;
  153. if (w > len) {
  154. w = len;
  155. }
  156. memcpy(buf_ + idx_, str, w);
  157. if (len - w > 0) {
  158. os_.write(buf_, idx_ + w);
  159. os_.write(str + w, len - w);
  160. idx_ = 0;
  161. } else {
  162. idx_ += w;
  163. }
  164. }
  165. }