CalculateLineAndColumn calculates the 0-based line number and 0-based column (character offset) for a given byte offset in the statement.
(statement string, byteOffset int)
| 3 | // CalculateLineAndColumn calculates the 0-based line number and 0-based column (character offset) |
| 4 | // for a given byte offset in the statement. |
| 5 | func CalculateLineAndColumn(statement string, byteOffset int) (line, column int) { |
| 6 | if byteOffset > len(statement) { |
| 7 | byteOffset = len(statement) |
| 8 | } |
| 9 | // Range over string iterates over runes (code points), not bytes. |
| 10 | // \r\n is treated as a single line break; standalone \r is a line break. |
| 11 | s := statement[:byteOffset] |
| 12 | for i, r := range s { |
| 13 | switch r { |
| 14 | case '\r': |
| 15 | // \r\n is one line break; standalone \r is also a line break. |
| 16 | // In both cases, increment line here. For \r\n, the \n case |
| 17 | // below will see that the previous char was \r and skip. |
| 18 | line++ |
| 19 | column = 0 |
| 20 | case '\n': |
| 21 | if i > 0 && s[i-1] == '\r' { |
| 22 | // Already counted by the \r above. |
| 23 | continue |
| 24 | } |
| 25 | line++ |
| 26 | column = 0 |
| 27 | default: |
| 28 | column++ |
| 29 | } |
| 30 | } |
| 31 | return line, column |
| 32 | } |
no outgoing calls