// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package stringtab

import (
	
	
	
	
)

// This package implements string table writer and reader utilities,
// for use in emitting and reading/decoding coverage meta-data and
// counter-data files.

// Writer implements a string table writing utility.
type Writer struct {
	stab   map[string]uint32
	strs   []string
	tmp    []byte
	frozen bool
}

// InitWriter initializes a stringtab.Writer.
func ( *Writer) () {
	.stab = make(map[string]uint32)
	.tmp = make([]byte, 64)
}

// Nentries returns the number of strings interned so far.
func ( *Writer) () uint32 {
	return uint32(len(.strs))
}

// Lookup looks up string 's' in the writer's table, adding
// a new entry if need be, and returning an index into the table.
func ( *Writer) ( string) uint32 {
	if ,  := .stab[];  {
		return 
	}
	if .frozen {
		panic("internal error: string table previously frozen")
	}
	 := uint32(len(.strs))
	.stab[] = 
	.strs = append(.strs, )
	return 
}

// Size computes the memory in bytes needed for the serialized
// version of a stringtab.Writer.
func ( *Writer) () uint32 {
	 := uint32(0)
	.tmp = .tmp[:0]
	.tmp = uleb128.AppendUleb128(.tmp, uint(len(.strs)))
	 += uint32(len(.tmp))
	for ,  := range .strs {
		.tmp = .tmp[:0]
		 := uint(len())
		.tmp = uleb128.AppendUleb128(.tmp, )
		 += uint32(len(.tmp)) + uint32()
	}
	return 
}

// Write writes the string table in serialized form to the specified
// io.Writer.
func ( *Writer) ( io.Writer) error {
	 := func( uint) error {
		.tmp = .tmp[:0]
		.tmp = uleb128.AppendUleb128(.tmp, )
		if ,  := .Write(.tmp);  != nil {
			return fmt.Errorf("writing string table: %v", )
		} else if  != len(.tmp) {
			return fmt.Errorf("short write emitting stringtab uleb")
		}
		return nil
	}
	if  := (uint(len(.strs)));  != nil {
		return 
	}
	for ,  := range .strs {
		if  := (uint(len()));  != nil {
			return 
		}
		if ,  := .Write([]byte());  != nil {
			return fmt.Errorf("writing string table: %v", )
		} else if  != len([]byte()) {
			return fmt.Errorf("short write emitting stringtab")
		}
	}
	return nil
}

// Freeze sends a signal to the writer that no more additions are
// allowed, only lookups of existing strings (if a lookup triggers
// addition, a panic will result). Useful as a mechanism for
// "finalizing" a string table prior to writing it out.
func ( *Writer) () {
	.frozen = true
}

// Reader is a helper for reading a string table previously
// serialized by a Writer.Write call.
type Reader struct {
	r    *slicereader.Reader
	strs []string
}

// NewReader creates a stringtab.Reader to read the contents
// of a string table from 'r'.
func ( *slicereader.Reader) *Reader {
	 := &Reader{
		r: ,
	}
	return 
}

// Read reads/decodes a string table using the reader provided.
func ( *Reader) () {
	 := int(.r.ReadULEB128())
	.strs = make([]string, 0, )
	for  := 0;  < ; ++ {
		 := .r.ReadULEB128()
		.strs = append(.strs, .r.ReadString(int64()))
	}
}

// Entries returns the number of decoded entries in a string table.
func ( *Reader) () int {
	return len(.strs)
}

// Get returns string 'idx' within the string table.
func ( *Reader) ( uint32) string {
	return .strs[]
}