srcfile.go 1.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. package goja
  2. import (
  3. "fmt"
  4. "sort"
  5. "strings"
  6. )
  7. type Position struct {
  8. Line, Col int
  9. }
  10. type SrcFile struct {
  11. name string
  12. src string
  13. lineOffsets []int
  14. lastScannedOffset int
  15. }
  16. func NewSrcFile(name, src string) *SrcFile {
  17. return &SrcFile{
  18. name: name,
  19. src: src,
  20. }
  21. }
  22. func (f *SrcFile) Position(offset int) Position {
  23. var line int
  24. if offset > f.lastScannedOffset {
  25. f.scanTo(offset)
  26. line = len(f.lineOffsets) - 1
  27. } else {
  28. if len(f.lineOffsets) > 0 {
  29. line = sort.SearchInts(f.lineOffsets, offset)
  30. } else {
  31. line = -1
  32. }
  33. }
  34. if line >= 0 {
  35. if f.lineOffsets[line] > offset {
  36. line--
  37. }
  38. }
  39. var lineStart int
  40. if line >= 0 {
  41. lineStart = f.lineOffsets[line]
  42. }
  43. return Position{
  44. Line: line + 2,
  45. Col: offset - lineStart + 1,
  46. }
  47. }
  48. func (f *SrcFile) scanTo(offset int) {
  49. o := f.lastScannedOffset
  50. for o < offset {
  51. p := strings.Index(f.src[o:], "\n")
  52. if p == -1 {
  53. o = len(f.src)
  54. break
  55. }
  56. o = o + p + 1
  57. f.lineOffsets = append(f.lineOffsets, o)
  58. }
  59. f.lastScannedOffset = o
  60. }
  61. func (p Position) String() string {
  62. return fmt.Sprintf("%d:%d", p.Line, p.Col)
  63. }