116 lines
4.0 KiB
Go
116 lines
4.0 KiB
Go
// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
|
|
|
|
package parser2v3
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/spdx/tools-golang/spdx/common"
|
|
)
|
|
|
|
// used to extract key / value from embedded substrings
|
|
// returns subkey, subvalue, nil if no error, or "", "", error otherwise
|
|
func extractSubs(value string) (string, string, error) {
|
|
// parse the value to see if it's a valid subvalue format
|
|
sp := strings.SplitN(value, ":", 2)
|
|
if len(sp) == 1 {
|
|
return "", "", fmt.Errorf("invalid subvalue format for %s (no colon found)", value)
|
|
}
|
|
|
|
subkey := strings.TrimSpace(sp[0])
|
|
subvalue := strings.TrimSpace(sp[1])
|
|
|
|
return subkey, subvalue, nil
|
|
}
|
|
|
|
// used to extract DocumentRef and SPDXRef values from an SPDX Identifier
|
|
// which can point either to this document or to a different one
|
|
func extractDocElementID(value string) (common.DocElementID, error) {
|
|
docRefID := ""
|
|
idStr := value
|
|
|
|
// check prefix to see if it's a DocumentRef ID
|
|
if strings.HasPrefix(idStr, "DocumentRef-") {
|
|
// extract the part that comes between "DocumentRef-" and ":"
|
|
strs := strings.Split(idStr, ":")
|
|
// should be exactly two, part before and part after
|
|
if len(strs) < 2 {
|
|
return common.DocElementID{}, fmt.Errorf("no colon found although DocumentRef- prefix present")
|
|
}
|
|
if len(strs) > 2 {
|
|
return common.DocElementID{}, fmt.Errorf("more than one colon found")
|
|
}
|
|
|
|
// trim the prefix and confirm non-empty
|
|
docRefID = strings.TrimPrefix(strs[0], "DocumentRef-")
|
|
if docRefID == "" {
|
|
return common.DocElementID{}, fmt.Errorf("document identifier has nothing after prefix")
|
|
}
|
|
// and use remainder for element ID parsing
|
|
idStr = strs[1]
|
|
}
|
|
|
|
// check prefix to confirm it's got the right prefix for element IDs
|
|
if !strings.HasPrefix(idStr, "SPDXRef-") {
|
|
return common.DocElementID{}, fmt.Errorf("missing SPDXRef- prefix for element identifier")
|
|
}
|
|
|
|
// make sure no colons are present
|
|
if strings.Contains(idStr, ":") {
|
|
// we know this means there was no DocumentRef- prefix, because
|
|
// we would have handled multiple colons above if it was
|
|
return common.DocElementID{}, fmt.Errorf("invalid colon in element identifier")
|
|
}
|
|
|
|
// trim the prefix and confirm non-empty
|
|
eltRefID := strings.TrimPrefix(idStr, "SPDXRef-")
|
|
if eltRefID == "" {
|
|
return common.DocElementID{}, fmt.Errorf("element identifier has nothing after prefix")
|
|
}
|
|
|
|
// we're good
|
|
return common.DocElementID{DocumentRefID: docRefID, ElementRefID: common.ElementID(eltRefID)}, nil
|
|
}
|
|
|
|
// used to extract SPDXRef values from an SPDX Identifier, OR "special" strings
|
|
// from a specified set of permitted values. The primary use case for this is
|
|
// the right-hand side of Relationships, where beginning in SPDX 2.3 the values
|
|
// "NONE" and "NOASSERTION" are permitted. If the value does not match one of
|
|
// the specified permitted values, it will fall back to the ordinary
|
|
// DocElementID extractor.
|
|
func extractDocElementSpecial(value string, permittedSpecial []string) (common.DocElementID, error) {
|
|
// check value against special set first
|
|
for _, sp := range permittedSpecial {
|
|
if sp == value {
|
|
return common.DocElementID{SpecialID: sp}, nil
|
|
}
|
|
}
|
|
// not found, fall back to regular search
|
|
return extractDocElementID(value)
|
|
}
|
|
|
|
// used to extract SPDXRef values only from an SPDX Identifier which can point
|
|
// to this document only. Use extractDocElementID for parsing IDs that can
|
|
// refer either to this document or a different one.
|
|
func extractElementID(value string) (common.ElementID, error) {
|
|
// check prefix to confirm it's got the right prefix for element IDs
|
|
if !strings.HasPrefix(value, "SPDXRef-") {
|
|
return common.ElementID(""), fmt.Errorf("missing SPDXRef- prefix for element identifier")
|
|
}
|
|
|
|
// make sure no colons are present
|
|
if strings.Contains(value, ":") {
|
|
return common.ElementID(""), fmt.Errorf("invalid colon in element identifier")
|
|
}
|
|
|
|
// trim the prefix and confirm non-empty
|
|
eltRefID := strings.TrimPrefix(value, "SPDXRef-")
|
|
if eltRefID == "" {
|
|
return common.ElementID(""), fmt.Errorf("element identifier has nothing after prefix")
|
|
}
|
|
|
|
// we're good
|
|
return common.ElementID(eltRefID), nil
|
|
}
|