package gg type ObjectMap map[Object] struct{} // The structure to store objects // with O(1) add, remove and search operations. type Objects struct { // The place to store all the objects. store []Object // Find index by Object. searchMap map[Object] int tagMap map[Tag] ObjectMap // Available nil values in the store. freeIndexes []int } func NewObjects() *Objects { ret := &Objects{} ret.searchMap = map[Object] int {} ret.tagMap = map[Tag]ObjectMap{} return ret } func (objects *Objects) has(object Object) bool { _, ok := objects.searchMap[object] return ok } func (objects *Objects) add(object Object) bool { if objects.has(object) { return false } if len(objects.freeIndexes) > 0 { freeIndex := objects.freeIndexes[0] objects.freeIndexes = objects.freeIndexes[1:] objects.store[freeIndex] = object objects.searchMap[object] = freeIndex } else { objects.store = append(objects.store, object) objects.searchMap[object] = len(objects.store)-1 } return true } func (objects *Objects) remove(object Object) bool { objectIndex, ok := objects.searchMap[object] if !ok { return false } objects.store[objectIndex] = nil objects.freeIndexes = append( objects.freeIndexes, objectIndex, ) return true } func (objects *Objects) FindByTags( t Tag, rest ...Tag, ) []Object { tagMap := objects.tagMap objectMap := tagMap[t] retMap := map[Object]struct{}{} for object := range objectMap { retMap[object] = struct{}{} } for _, tag := range rest { m, ok := tagMap[tag] if !ok { continue } for object := range m { _, ok := m[object] if !ok { delete(retMap, object) } } } ret := []Object{} for object := range retMap { ret = append(ret, object) } return ret } func (objects *Objects) updateObjects(c Context){ for _, object := range objects.store { if object == nil { continue } object.OnUpdate(c) } } func (objects *Objects) updateTags(c Context) { tagMap := objects.tagMap updateMap := make(map[Tag]ObjectMap, len(tagMap)) for _, object := range objects.store { tags := object.GetTags(c) for tag := range tags { tm, ok := updateMap[tag] if ok { tm[object] = struct{}{} } else { updateMap[tag] = ObjectMap{ object: struct{}{}, } } } } objects.tagMap = updateMap }