input.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. #include "input.h"
  2. #include "output.h"
  3. #include "str.h"
  4. #include <util/charset/wide.h>
  5. #include <util/memory/tempbuf.h>
  6. #include <util/generic/string.h>
  7. #include <util/generic/yexception.h>
  8. #include <util/generic/singleton.h>
  9. #include <util/string/cast.h>
  10. #include <util/system/compat.h>
  11. #include <util/system/spinlock.h>
  12. #include <cstdlib>
  13. IInputStream::IInputStream() noexcept = default;
  14. IInputStream::~IInputStream() = default;
  15. size_t IInputStream::DoReadTo(TString& st, char to) {
  16. char ch;
  17. if (!Read(&ch, 1)) {
  18. return 0;
  19. }
  20. st.clear();
  21. size_t result = 0;
  22. do {
  23. ++result;
  24. if (ch == to) {
  25. break;
  26. }
  27. st += ch;
  28. } while (Read(&ch, 1));
  29. return result;
  30. }
  31. ui64 IInputStream::DoReadAll(IOutputStream& out) {
  32. TTempBuf buffer;
  33. void* ptr = buffer.Data();
  34. size_t size = buffer.Size();
  35. ui64 result = 0;
  36. while (size_t read = Read(ptr, size)) {
  37. out.Write(ptr, read);
  38. result += read;
  39. }
  40. return result;
  41. }
  42. size_t IInputStream::Load(void* buf_in, size_t len) {
  43. char* buf = (char*)buf_in;
  44. while (len) {
  45. const size_t ret = Read(buf, len);
  46. buf += ret;
  47. len -= ret;
  48. if (ret == 0) {
  49. break;
  50. }
  51. }
  52. return buf - (char*)buf_in;
  53. }
  54. void IInputStream::LoadOrFail(void* buf, size_t len) {
  55. const size_t realLen = Load(buf, len);
  56. if (Y_UNLIKELY(realLen != len)) {
  57. ythrow yexception() << "Failed to read required number of bytes from stream! Expected: " << len << ", gained: " << realLen << "!";
  58. }
  59. }
  60. size_t IInputStream::ReadLine(TString& st) {
  61. const size_t ret = ReadTo(st, '\n');
  62. if (ret && !st.empty() && st.back() == '\r') {
  63. st.pop_back();
  64. }
  65. return ret;
  66. }
  67. size_t IInputStream::ReadLine(TUtf16String& w) {
  68. TString s;
  69. size_t result = ReadLine(s);
  70. if (result) {
  71. UTF8ToWide(s, w);
  72. }
  73. return result;
  74. }
  75. TString IInputStream::ReadLine() {
  76. TString ret;
  77. if (!ReadLine(ret)) {
  78. ythrow yexception() << "can not read line from stream";
  79. }
  80. return ret;
  81. }
  82. TString IInputStream::ReadTo(char ch) {
  83. TString ret;
  84. if (!ReadTo(ret, ch)) {
  85. ythrow yexception() << "can not read from stream";
  86. }
  87. return ret;
  88. }
  89. size_t IInputStream::Skip(size_t sz) {
  90. return DoSkip(sz);
  91. }
  92. size_t IInputStream::DoSkip(size_t sz) {
  93. if (sz < 128) {
  94. return Load(alloca(sz), sz);
  95. }
  96. TTempBuf buf;
  97. size_t total = 0;
  98. while (sz) {
  99. const size_t lresult = Read(buf.Data(), Min<size_t>(sz, buf.Size()));
  100. if (lresult == 0) {
  101. return total;
  102. }
  103. total += lresult;
  104. sz -= lresult;
  105. }
  106. return total;
  107. }
  108. TString IInputStream::ReadAll() {
  109. TString result;
  110. TStringOutput stream(result);
  111. DoReadAll(stream);
  112. return result;
  113. }
  114. ui64 IInputStream::ReadAll(IOutputStream& out) {
  115. return DoReadAll(out);
  116. }
  117. ui64 TransferData(IInputStream* in, IOutputStream* out) {
  118. return in->ReadAll(*out);
  119. }
  120. namespace {
  121. struct TStdIn: public IInputStream {
  122. ~TStdIn() override = default;
  123. size_t DoRead(void* buf, size_t len) override {
  124. const size_t ret = fread(buf, 1, len, F_);
  125. if (ret < len && ferror(F_)) {
  126. ythrow TSystemError() << "can not read from stdin";
  127. }
  128. return ret;
  129. }
  130. FILE* F_ = stdin;
  131. };
  132. #if defined(_win_)
  133. using TGetLine = TStdIn;
  134. #else
  135. #if defined(_bionic_)
  136. using TGetLineBase = TStdIn;
  137. #else
  138. struct TGetLineBase: public TStdIn {
  139. ~TGetLineBase() override {
  140. free(B_);
  141. }
  142. size_t DoReadTo(TString& st, char ch) override {
  143. auto&& guard = Guard(M_);
  144. (void)guard;
  145. const auto r = getdelim(&B_, &L_, ch, F_);
  146. if (r < 0) {
  147. if (ferror(F_)) {
  148. ythrow TSystemError() << "can not read from stdin";
  149. }
  150. st.clear();
  151. return 0;
  152. }
  153. st.AssignNoAlias(B_, r);
  154. if (st && st.back() == ch) {
  155. st.pop_back();
  156. }
  157. return r;
  158. }
  159. TAdaptiveLock M_;
  160. char* B_ = nullptr;
  161. size_t L_ = 0;
  162. };
  163. #endif
  164. #if defined(_glibc_) || defined(_cygwin_)
  165. // glibc does not have fgetln
  166. using TGetLine = TGetLineBase;
  167. #else
  168. struct TGetLine: public TGetLineBase {
  169. size_t DoReadTo(TString& st, char ch) override {
  170. if (ch == '\n') {
  171. size_t len = 0;
  172. auto r = fgetln(F_, &len);
  173. if (r) {
  174. st.AssignNoAlias(r, len);
  175. if (st && st.back() == '\n') {
  176. st.pop_back();
  177. }
  178. return len;
  179. }
  180. }
  181. return TGetLineBase::DoReadTo(st, ch);
  182. }
  183. };
  184. #endif
  185. #endif
  186. }
  187. IInputStream& NPrivate::StdInStream() noexcept {
  188. return *SingletonWithPriority<TGetLine, 4>();
  189. }
  190. // implementation of >> operator
  191. // helper functions
  192. static inline bool IsStdDelimiter(char c) {
  193. return (c == '\0') || (c == ' ') || (c == '\r') || (c == '\n') || (c == '\t');
  194. }
  195. static void ReadUpToDelimiter(IInputStream& i, TString& s) {
  196. char c;
  197. while (i.ReadChar(c)) { // skip delimiters
  198. if (!IsStdDelimiter(c)) {
  199. s += c;
  200. break;
  201. }
  202. }
  203. while (i.ReadChar(c) && !IsStdDelimiter(c)) { // read data (with trailing delimiter)
  204. s += c;
  205. }
  206. }
  207. // specialization for string-related stuff
  208. template <>
  209. void In<TString>(IInputStream& i, TString& s) {
  210. s.resize(0);
  211. ReadUpToDelimiter(i, s);
  212. }
  213. template <>
  214. void In<TUtf16String>(IInputStream& i, TUtf16String& w) {
  215. TString s;
  216. ReadUpToDelimiter(i, s);
  217. if (s.empty()) {
  218. w.erase();
  219. } else {
  220. w = UTF8ToWide(s);
  221. }
  222. }
  223. // specialization for char types
  224. #define SPEC_FOR_CHAR(T) \
  225. template <> \
  226. void In<T>(IInputStream & i, T & t) { \
  227. i.ReadChar((char&)t); \
  228. }
  229. SPEC_FOR_CHAR(char)
  230. SPEC_FOR_CHAR(unsigned char)
  231. SPEC_FOR_CHAR(signed char)
  232. #undef SPEC_FOR_CHAR
  233. // specialization for number types
  234. #define SPEC_FOR_NUMBER(T) \
  235. template <> \
  236. void In<T>(IInputStream & i, T & t) { \
  237. char buf[128]; \
  238. size_t pos = 0; \
  239. while (i.ReadChar(buf[0])) { \
  240. if (!IsStdDelimiter(buf[0])) { \
  241. ++pos; \
  242. break; \
  243. } \
  244. } \
  245. while (i.ReadChar(buf[pos]) && !IsStdDelimiter(buf[pos]) && pos < 127) { \
  246. ++pos; \
  247. } \
  248. t = FromString<T, char>(buf, pos); \
  249. }
  250. SPEC_FOR_NUMBER(signed short)
  251. SPEC_FOR_NUMBER(signed int)
  252. SPEC_FOR_NUMBER(signed long int)
  253. SPEC_FOR_NUMBER(signed long long int)
  254. SPEC_FOR_NUMBER(unsigned short)
  255. SPEC_FOR_NUMBER(unsigned int)
  256. SPEC_FOR_NUMBER(unsigned long int)
  257. SPEC_FOR_NUMBER(unsigned long long int)
  258. SPEC_FOR_NUMBER(float)
  259. SPEC_FOR_NUMBER(double)
  260. SPEC_FOR_NUMBER(long double)
  261. #undef SPEC_FOR_NUMBER