2025-10-15 10:12:44 +03:00

69 lines
1.8 KiB
Go

package encoder
import (
"strings"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/ast"
)
type stringTable struct {
fileText string
otherStrings *strings.Builder
// offsets are pos/end pairs
offsets []uint32
}
func newStringTable(fileText string, stringCount int) *stringTable {
builder := &strings.Builder{}
return &stringTable{
fileText: fileText,
otherStrings: builder,
offsets: make([]uint32, 0, stringCount*2),
}
}
func (t *stringTable) add(text string, kind ast.Kind, pos int, end int) uint32 {
index := uint32(len(t.offsets))
if kind == ast.KindSourceFile {
t.offsets = append(t.offsets, uint32(pos), uint32(end))
return index
}
length := len(text)
if end-pos > 0 {
// pos includes leading trivia, but we can usually infer the actual start of the
// string from the kind and end
endOffset := 0
if kind == ast.KindStringLiteral || kind == ast.KindTemplateTail || kind == ast.KindNoSubstitutionTemplateLiteral {
endOffset = 1
}
end = end - endOffset
start := end - length
fileSlice := t.fileText[start:end]
if fileSlice == text {
t.offsets = append(t.offsets, uint32(start), uint32(end))
return index
}
}
// no exact match, so we need to add it to the string table
offset := len(t.fileText) + t.otherStrings.Len()
t.otherStrings.WriteString(text)
t.offsets = append(t.offsets, uint32(offset), uint32(offset+length))
return index
}
func (t *stringTable) encode() []byte {
result := make([]byte, 0, t.encodedLength())
result = appendUint32s(result, t.offsets...)
result = append(result, t.fileText...)
result = append(result, t.otherStrings.String()...)
return result
}
func (t *stringTable) stringLength() int {
return len(t.fileText) + t.otherStrings.Len()
}
func (t *stringTable) encodedLength() int {
return len(t.offsets)*4 + len(t.fileText) + t.otherStrings.Len()
}