github.com/CycloneDX/sbom-utility@v0.16.0/schema/bom_query.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  /*
     3   * Licensed to the Apache Software Foundation (ASF) under one or more
     4   * contributor license agreements.  See the NOTICE file distributed with
     5   * this work for additional information regarding copyright ownership.
     6   * The ASF licenses this file to You under the Apache License, Version 2.0
     7   * (the "License"); you may not use this file except in compliance with
     8   * the License.  You may obtain a copy of the License at
     9   *
    10   *     http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   * Unless required by applicable law or agreed to in writing, software
    13   * distributed under the License is distributed on an "AS IS" BASIS,
    14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15   * See the License for the specific language governing permissions and
    16   * limitations under the License.
    17   */
    18  
    19  package schema
    20  
    21  import (
    22  	"bytes"
    23  	"encoding/gob"
    24  	"strconv"
    25  
    26  	"github.com/CycloneDX/sbom-utility/common"
    27  )
    28  
    29  // Note: Golang supports the RE2 regular exp. engine which does not support many
    30  // features such as lookahead, lookbehind, etc.
    31  // See: https://en.wikipedia.org/wiki/Comparison_of_regular_expression_engines
    32  func whereFilterMatch(mapObject map[string]interface{}, whereFilters []common.WhereFilter) (match bool, err error) {
    33  	var buf bytes.Buffer
    34  	var key string
    35  
    36  	// create a byte encoder
    37  	enc := gob.NewEncoder(&buf)
    38  
    39  	for _, filter := range whereFilters {
    40  
    41  		key = filter.Key
    42  		value, present := mapObject[key]
    43  		getLogger().Debugf("testing object map[%s]: `%v`", key, value)
    44  
    45  		if !present {
    46  			match = false
    47  			err = getLogger().Errorf("key `%s` not found ib object map", key)
    48  			break
    49  		}
    50  
    51  		// Reset the encoder'a byte buffer on each iteration and
    52  		// convert the value (an interface{}) to []byte we can use on regex. eval.
    53  		buf.Reset()
    54  
    55  		// Do not encode nil pointer values; replace with empty string
    56  		if value == nil {
    57  			value = ""
    58  		}
    59  
    60  		// Handle non-string data types in the map by converting them to string
    61  		switch data := value.(type) {
    62  		case string:
    63  			value = data
    64  		case bool:
    65  			value = strconv.FormatBool(data)
    66  		case int:
    67  			value = strconv.Itoa(data)
    68  		case float64:
    69  			// NOTE: JSON Unmarshal() always decodes JSON Numbers as "float64" type
    70  			value = strconv.FormatFloat(data, 'f', -1, 64)
    71  		default:
    72  			getLogger().Errorf("unhandled datatype. key=%s, value=`%v`, type=`%T`", key, data, data)
    73  		}
    74  
    75  		err = enc.Encode(value)
    76  
    77  		if err != nil {
    78  			err = getLogger().Errorf("Unable to convert value: `%v`, to []byte", value)
    79  			return
    80  		}
    81  
    82  		// Test that the field value matches the regex supplied in the current filter
    83  		// Note: the regex compilation is performed during command param. processing
    84  		if match = filter.ValueRegEx.Match(buf.Bytes()); !match {
    85  			break
    86  		}
    87  	}
    88  
    89  	return
    90  }