| 8412 | |
| 8413 | public: |
| 8414 | class iterator { |
| 8415 | friend Column; |
| 8416 | |
| 8417 | Column const& m_column; |
| 8418 | size_t m_stringIndex = 0; |
| 8419 | size_t m_pos = 0; |
| 8420 | |
| 8421 | size_t m_len = 0; |
| 8422 | size_t m_end = 0; |
| 8423 | bool m_suffix = false; |
| 8424 | |
| 8425 | iterator(Column const& column, size_t stringIndex) |
| 8426 | : m_column(column), |
| 8427 | m_stringIndex(stringIndex) {} |
| 8428 | |
| 8429 | auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; } |
| 8430 | |
| 8431 | auto isBoundary(size_t at) const -> bool { |
| 8432 | assert(at > 0); |
| 8433 | assert(at <= line().size()); |
| 8434 | |
| 8435 | return at == line().size() || |
| 8436 | (isWhitespace(line()[at]) && !isWhitespace(line()[at - 1])) || |
| 8437 | isBreakableBefore(line()[at]) || |
| 8438 | isBreakableAfter(line()[at - 1]); |
| 8439 | } |
| 8440 | |
| 8441 | void calcLength() { |
| 8442 | assert(m_stringIndex < m_column.m_strings.size()); |
| 8443 | |
| 8444 | m_suffix = false; |
| 8445 | auto width = m_column.m_width - indent(); |
| 8446 | m_end = m_pos; |
| 8447 | if (line()[m_pos] == '\n') { |
| 8448 | ++m_end; |
| 8449 | } |
| 8450 | while (m_end < line().size() && line()[m_end] != '\n') |
| 8451 | ++m_end; |
| 8452 | |
| 8453 | if (m_end < m_pos + width) { |
| 8454 | m_len = m_end - m_pos; |
| 8455 | } else { |
| 8456 | size_t len = width; |
| 8457 | while (len > 0 && !isBoundary(m_pos + len)) |
| 8458 | --len; |
| 8459 | while (len > 0 && isWhitespace(line()[m_pos + len - 1])) |
| 8460 | --len; |
| 8461 | |
| 8462 | if (len > 0) { |
| 8463 | m_len = len; |
| 8464 | } else { |
| 8465 | m_suffix = true; |
| 8466 | m_len = width - 1; |
| 8467 | } |
| 8468 | } |
| 8469 | } |
| 8470 | |
| 8471 | auto indent() const -> size_t { |