gotype/symbols.go (72 lines of code) (raw):

// Licensed to Elasticsearch B.V. under one or more contributor // license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright // ownership. Elasticsearch B.V. licenses this file to you under // the Apache License, Version 2.0 (the "License"); you may // not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package gotype type symbolCache struct { m map[string]*symbol lst symbolList max int } type symbol struct { value string prev *symbol next *symbol } type symbolList symbol func (c *symbolCache) init(max int) { c.max = max c.m = make(map[string]*symbol, max) c.lst = symbolList{} c.lst.prev = (*symbol)(&c.lst) c.lst.next = (*symbol)(&c.lst) } func (c *symbolCache) enabled() bool { return c.m != nil } func (c *symbolCache) get(in []byte) string { if !c.enabled() { return string(in) } if sym := c.lookup(bytes2Str(in)); sym != nil { return sym.value } str := string(in) c.add(str) return str } func (c *symbolCache) lookup(value string) *symbol { sym := c.m[value] if sym != nil { removeLst(sym) c.lst.append(sym) } return sym } func (c *symbolCache) add(value string) { if len(c.m) == c.max { old := c.lst.pop() delete(c.m, old.value) } sym := &symbol{value: value} c.m[value] = sym c.lst.append(sym) } func (l *symbolList) empty() bool { s := (*symbol)(l) return s.next == s && s.prev == s } func (l *symbolList) append(sym *symbol) { head := (*symbol)(l) sym.prev = head.prev sym.next = head head.prev.next = sym head.prev = sym } func (l *symbolList) pop() (sym *symbol) { if !l.empty() { sym = l.next removeLst(sym) } return } func removeLst(s *symbol) { s.prev.next = s.next s.next.prev = s.prev }