// Copyright 2018 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 xeddata import ( "sort" "strings" ) // PatternSet wraps instruction PATTERN properties providing set operations on them. type PatternSet map[string]bool // NewPatternSet decodes pattern string into PatternSet. func NewPatternSet(pattern string) PatternSet { pset := make(PatternSet) for _, f := range strings.Fields(pattern) { pset[f] = true } return pset } // PatternAliases is extendable map of pattern keys aliases. // Maps human-readable key to XED property. // // Used in PatternSet.Is. var PatternAliases = map[string]string{ "VEX": "VEXVALID=1", "EVEX": "VEXVALID=2", "XOP": "VEXVALID=3", "MemOnly": "MOD!=3", "RegOnly": "MOD=3", } // String returns pattern printer representation. // All properties are sorted. func (pset PatternSet) String() string { var keys []string for k := range pset { keys = append(keys, k) } sort.Strings(keys) return strings.Join(keys, " ") } // Is reports whether set contains key k. // In contrast with direct pattern set lookup, it does // check if PatternAliases[k] is available to be used instead of k in lookup. func (pset PatternSet) Is(k string) bool { if alias := PatternAliases[k]; alias != "" { return pset[alias] } return pset[k] } // Replace inserts newKey if oldKey is defined. // oldKey is removed if insertion is performed. func (pset PatternSet) Replace(oldKey, newKey string) { if pset[oldKey] { pset[newKey] = true delete(pset, oldKey) } } // Index returns index from keys of first matching key. // Returns -1 if does not contain any of given keys. func (pset PatternSet) Index(keys ...string) int { for i, k := range keys { if pset[k] { return i } } return -1 } // Match is like MatchOrDefault("", keyval...). func (pset PatternSet) Match(keyval ...string) string { return pset.MatchOrDefault("", keyval...) } // MatchOrDefault returns first matching key associated value. // Returns defaultValue if no match is found. // // Keyval structure can be described as {"k1", "v1", ..., "kN", "vN"}. func (pset PatternSet) MatchOrDefault(defaultValue string, keyval ...string) string { for i := 0; i < len(keyval); i += 2 { key := keyval[i+0] val := keyval[i+1] if pset[key] { return val } } return defaultValue }