xref: /aosp_15_r20/external/spdx-tools/tvloader/parser2v1/util.go (revision ba677afa8f67bb56cbc794f4d0e378e0da058e16)
1// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2
3package parser2v1
4
5import (
6	"fmt"
7	"strings"
8
9	"github.com/spdx/tools-golang/spdx/common"
10)
11
12// used to extract key / value from embedded substrings
13// returns subkey, subvalue, nil if no error, or "", "", error otherwise
14func extractSubs(value string) (string, string, error) {
15	// parse the value to see if it's a valid subvalue format
16	sp := strings.SplitN(value, ":", 2)
17	if len(sp) == 1 {
18		return "", "", fmt.Errorf("invalid subvalue format for %s (no colon found)", value)
19	}
20
21	subkey := strings.TrimSpace(sp[0])
22	subvalue := strings.TrimSpace(sp[1])
23
24	return subkey, subvalue, nil
25}
26
27// used to extract DocumentRef and SPDXRef values from an SPDX Identifier
28// which can point either to this document or to a different one
29func extractDocElementID(value string) (common.DocElementID, error) {
30	docRefID := ""
31	idStr := value
32
33	// check prefix to see if it's a DocumentRef ID
34	if strings.HasPrefix(idStr, "DocumentRef-") {
35		// extract the part that comes between "DocumentRef-" and ":"
36		strs := strings.Split(idStr, ":")
37		// should be exactly two, part before and part after
38		if len(strs) < 2 {
39			return common.DocElementID{}, fmt.Errorf("no colon found although DocumentRef- prefix present")
40		}
41		if len(strs) > 2 {
42			return common.DocElementID{}, fmt.Errorf("more than one colon found")
43		}
44
45		// trim the prefix and confirm non-empty
46		docRefID = strings.TrimPrefix(strs[0], "DocumentRef-")
47		if docRefID == "" {
48			return common.DocElementID{}, fmt.Errorf("document identifier has nothing after prefix")
49		}
50		// and use remainder for element ID parsing
51		idStr = strs[1]
52	}
53
54	// check prefix to confirm it's got the right prefix for element IDs
55	if !strings.HasPrefix(idStr, "SPDXRef-") {
56		return common.DocElementID{}, fmt.Errorf("missing SPDXRef- prefix for element identifier")
57	}
58
59	// make sure no colons are present
60	if strings.Contains(idStr, ":") {
61		// we know this means there was no DocumentRef- prefix, because
62		// we would have handled multiple colons above if it was
63		return common.DocElementID{}, fmt.Errorf("invalid colon in element identifier")
64	}
65
66	// trim the prefix and confirm non-empty
67	eltRefID := strings.TrimPrefix(idStr, "SPDXRef-")
68	if eltRefID == "" {
69		return common.DocElementID{}, fmt.Errorf("element identifier has nothing after prefix")
70	}
71
72	// we're good
73	return common.DocElementID{DocumentRefID: docRefID, ElementRefID: common.ElementID(eltRefID)}, nil
74}
75
76// used to extract SPDXRef values only from an SPDX Identifier which can point
77// to this document only. Use extractDocElementID for parsing IDs that can
78// refer either to this document or a different one.
79func extractElementID(value string) (common.ElementID, error) {
80	// check prefix to confirm it's got the right prefix for element IDs
81	if !strings.HasPrefix(value, "SPDXRef-") {
82		return common.ElementID(""), fmt.Errorf("missing SPDXRef- prefix for element identifier")
83	}
84
85	// make sure no colons are present
86	if strings.Contains(value, ":") {
87		return common.ElementID(""), fmt.Errorf("invalid colon in element identifier")
88	}
89
90	// trim the prefix and confirm non-empty
91	eltRefID := strings.TrimPrefix(value, "SPDXRef-")
92	if eltRefID == "" {
93		return common.ElementID(""), fmt.Errorf("element identifier has nothing after prefix")
94	}
95
96	// we're good
97	return common.ElementID(eltRefID), nil
98}
99