| 5085 | |
| 5086 | public: |
| 5087 | class iterator { |
| 5088 | friend Column; |
| 5089 | |
| 5090 | Column const &m_column; |
| 5091 | size_t m_stringIndex = 0; |
| 5092 | size_t m_pos = 0; |
| 5093 | |
| 5094 | size_t m_len = 0; |
| 5095 | size_t m_end = 0; |
| 5096 | bool m_suffix = false; |
| 5097 | |
| 5098 | iterator(Column const &column, size_t stringIndex) : m_column(column), m_stringIndex(stringIndex) { |
| 5099 | } |
| 5100 | |
| 5101 | auto line() const -> std::string const & { |
| 5102 | return m_column.m_strings[m_stringIndex]; |
| 5103 | } |
| 5104 | |
| 5105 | auto isBoundary(size_t at) const -> bool { |
| 5106 | assert(at > 0); |
| 5107 | assert(at <= line().size()); |
| 5108 | |
| 5109 | return at == line().size() || (isWhitespace(line()[at]) && !isWhitespace(line()[at - 1])) || |
| 5110 | isBreakableBefore(line()[at]) || isBreakableAfter(line()[at - 1]); |
| 5111 | } |
| 5112 | |
| 5113 | void calcLength() { |
| 5114 | assert(m_stringIndex < m_column.m_strings.size()); |
| 5115 | |
| 5116 | m_suffix = false; |
| 5117 | auto width = m_column.m_width - indent(); |
| 5118 | m_end = m_pos; |
| 5119 | while (m_end < line().size() && line()[m_end] != '\n') |
| 5120 | ++m_end; |
| 5121 | |
| 5122 | if (m_end < m_pos + width) { |
| 5123 | m_len = m_end - m_pos; |
| 5124 | } else { |
| 5125 | size_t len = width; |
| 5126 | while (len > 0 && !isBoundary(m_pos + len)) |
| 5127 | --len; |
| 5128 | while (len > 0 && isWhitespace(line()[m_pos + len - 1])) |
| 5129 | --len; |
| 5130 | |
| 5131 | if (len > 0) { |
| 5132 | m_len = len; |
| 5133 | } else { |
| 5134 | m_suffix = true; |
| 5135 | m_len = width - 1; |
| 5136 | } |
| 5137 | } |
| 5138 | } |
| 5139 | |
| 5140 | auto indent() const -> size_t { |
| 5141 | auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos; |
| 5142 | return initial == std::string::npos ? m_column.m_indent : initial; |
| 5143 | } |
| 5144 | |