| 8179 | |
| 8180 | public: |
| 8181 | class iterator { |
| 8182 | friend Column; |
| 8183 | |
| 8184 | Column const& m_column; |
| 8185 | size_t m_stringIndex = 0; |
| 8186 | size_t m_pos = 0; |
| 8187 | |
| 8188 | size_t m_len = 0; |
| 8189 | size_t m_end = 0; |
| 8190 | bool m_suffix = false; |
| 8191 | |
| 8192 | iterator(Column const& column, size_t stringIndex) |
| 8193 | : m_column(column), |
| 8194 | m_stringIndex(stringIndex) {} |
| 8195 | |
| 8196 | auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; } |
| 8197 | |
| 8198 | auto isBoundary(size_t at) const -> bool { |
| 8199 | assert(at > 0); |
| 8200 | assert(at <= line().size()); |
| 8201 | |
| 8202 | return at == line().size() || |
| 8203 | (isWhitespace(line()[at]) && !isWhitespace(line()[at - 1])) || |
| 8204 | isBreakableBefore(line()[at]) || |
| 8205 | isBreakableAfter(line()[at - 1]); |
| 8206 | } |
| 8207 | |
| 8208 | void calcLength() { |
| 8209 | assert(m_stringIndex < m_column.m_strings.size()); |
| 8210 | |
| 8211 | m_suffix = false; |
| 8212 | auto width = m_column.m_width - indent(); |
| 8213 | m_end = m_pos; |
| 8214 | if (line()[m_pos] == '\n') { |
| 8215 | ++m_end; |
| 8216 | } |
| 8217 | while (m_end < line().size() && line()[m_end] != '\n') |
| 8218 | ++m_end; |
| 8219 | |
| 8220 | if (m_end < m_pos + width) { |
| 8221 | m_len = m_end - m_pos; |
| 8222 | } else { |
| 8223 | size_t len = width; |
| 8224 | while (len > 0 && !isBoundary(m_pos + len)) |
| 8225 | --len; |
| 8226 | while (len > 0 && isWhitespace(line()[m_pos + len - 1])) |
| 8227 | --len; |
| 8228 | |
| 8229 | if (len > 0) { |
| 8230 | m_len = len; |
| 8231 | } else { |
| 8232 | m_suffix = true; |
| 8233 | m_len = width - 1; |
| 8234 | } |
| 8235 | } |
| 8236 | } |
| 8237 | |
| 8238 | auto indent() const -> size_t { |