File indexing completed on 2024-04-28 05:41:19
0001 /* 0002 SPDX-FileCopyrightText: 2014-2017 Milian Wolff <mail@milianw.de> 0003 0004 SPDX-License-Identifier: LGPL-2.1-or-later 0005 */ 0006 0007 #ifndef LINEREADER_H 0008 #define LINEREADER_H 0009 0010 #include <cstdint> 0011 #include <istream> 0012 #include <string> 0013 0014 /** 0015 * Optimized class to speed up reading of the potentially big data files. 0016 * 0017 * sscanf or istream are just slow when reading plain hex numbers. The 0018 * below does all we need and thus far less than what the generic functions 0019 * are capable of. We are not locale aware e.g. 0020 */ 0021 class LineReader 0022 { 0023 public: 0024 LineReader() 0025 { 0026 m_line.reserve(1024); 0027 } 0028 0029 bool getLine(std::istream& in) 0030 { 0031 if (!in.good()) { 0032 return false; 0033 } 0034 std::getline(in, m_line); 0035 m_it = m_line.cbegin(); 0036 if (m_line.length() > 2) { 0037 m_it += 2; 0038 } else { 0039 m_it = m_line.cend(); 0040 } 0041 return true; 0042 } 0043 0044 char mode() const 0045 { 0046 return m_line.empty() ? '#' : m_line[0]; 0047 } 0048 0049 const std::string& line() const 0050 { 0051 return m_line; 0052 } 0053 0054 template <typename T> 0055 bool readHex(T& in) 0056 { 0057 auto it = m_it; 0058 const auto end = m_line.cend(); 0059 if (it == end) { 0060 return false; 0061 } 0062 0063 T hex = 0; 0064 do { 0065 const char c = *it; 0066 if ('0' <= c && c <= '9') { 0067 hex *= 16; 0068 hex += c - '0'; 0069 } else if ('a' <= c && c <= 'f') { 0070 hex *= 16; 0071 hex += c - 'a' + 10; 0072 } else if (c == ' ') { 0073 ++it; 0074 break; 0075 } else { 0076 fprintf(stderr, "unexpected non-hex char: %d %zx\n", c, std::distance(m_line.cbegin(), it)); 0077 return false; 0078 } 0079 ++it; 0080 } while (it != end); 0081 0082 in = hex; 0083 m_it = it; 0084 return true; 0085 } 0086 0087 bool operator>>(int64_t& hex) 0088 { 0089 return readHex(hex); 0090 } 0091 0092 bool operator>>(uint64_t& hex) 0093 { 0094 return readHex(hex); 0095 } 0096 0097 bool operator>>(uint32_t& hex) 0098 { 0099 return readHex(hex); 0100 } 0101 0102 bool operator>>(int& hex) 0103 { 0104 return readHex(hex); 0105 } 0106 0107 void setExpectedSizedStrings(bool expectSizedStrings) 0108 { 0109 m_expectSizedStrings = expectSizedStrings; 0110 } 0111 0112 bool operator>>(std::string& str) 0113 { 0114 if (m_expectSizedStrings) { 0115 uint64_t size = 0; 0116 if (!(*this >> size) || size > static_cast<uint64_t>(std::distance(m_it, m_line.cend()))) { 0117 return false; 0118 } 0119 auto start = m_it; 0120 m_it += size; 0121 str.assign(start, m_it); 0122 if (m_it != m_line.cend()) { 0123 // eat trailing whitespace 0124 ++m_it; 0125 } 0126 return true; 0127 } 0128 0129 auto it = m_it; 0130 const auto end = m_line.cend(); 0131 while (it != end && *it != ' ') { 0132 ++it; 0133 } 0134 if (it != m_it) { 0135 str = std::string(m_it, it); 0136 if (*it == ' ') { 0137 ++it; 0138 } 0139 m_it = it; 0140 return true; 0141 } else { 0142 return false; 0143 } 0144 } 0145 0146 bool operator>>(bool& flag) 0147 { 0148 if (m_it != m_line.cend()) { 0149 flag = *m_it; 0150 m_it++; 0151 if (*m_it == ' ') { 0152 ++m_it; 0153 } 0154 return true; 0155 } else { 0156 return false; 0157 } 0158 } 0159 0160 private: 0161 bool m_expectSizedStrings = false; 0162 std::string m_line; 0163 std::string::const_iterator m_it; 0164 }; 0165 0166 #endif // LINEREADER_H