xref: /aosp_15_r20/external/bazelbuild-rules_android/src/tools/ak/res/path.go (revision 9e965d6fece27a77de5377433c2f7e6999b8cc0b)
1// Copyright 2018 The Bazel Authors. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//    http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package res
16
17import (
18	"errors"
19	"fmt"
20	"path"
21	"strings"
22)
23
24// ErrNotResPath the provided path does not seem to point to a resource file
25var ErrNotResPath = errors.New("Not a resource path")
26
27// ErrSkipResPath the provided path does needs to be skipped.
28var ErrSkipResPath = errors.New("resource path that does needs to be skipped")
29
30// PathInfo contains all information about a resource that can be derived from its location on the filesystem.
31type PathInfo struct {
32	Path      string
33	ResDir    string
34	TypeDir   string
35	Type      Type
36	Qualifier string
37	Density   Density
38}
39
40// ParsePath converts a path string into a PathInfo object if the string points to a resource file.
41func ParsePath(p string) (PathInfo, error) {
42	parent := path.Dir(p)
43	resDir := path.Dir(parent)
44	typeDir := path.Base(parent)
45
46	if strings.HasPrefix(path.Base(p), ".") {
47		return PathInfo{}, ErrSkipResPath
48	}
49
50	resType, err := ParseValueOrType(strings.Split(typeDir, "-")[0])
51	qualifier := extractQualifier(typeDir)
52	if err != nil {
53		return PathInfo{}, ErrNotResPath
54	}
55	var density Density
56	for _, q := range strings.Split(qualifier, "-") {
57		var err error
58		density, err = ParseDensity(q)
59		if err != nil {
60			return PathInfo{}, err
61		}
62		if density != UnspecifiedDensity {
63			break
64		}
65	}
66	return PathInfo{
67		Path:      p,
68		ResDir:    resDir,
69		TypeDir:   typeDir,
70		Type:      resType,
71		Qualifier: qualifier,
72		Density:   density,
73	}, nil
74}
75
76// MakePathInfo converts a path string into a PathInfo object.
77func MakePathInfo(p string) (*PathInfo, error) {
78	pi, err := ParsePath(p)
79	if err != nil {
80		return nil, fmt.Errorf("ParsePath failed to parse %q: %v", p, err)
81	}
82	return &pi, nil
83}
84
85// MakePathInfos converts a list of path strings into a list of PathInfo objects.
86func MakePathInfos(paths []string) ([]*PathInfo, error) {
87	pis := make([]*PathInfo, 0, len(paths))
88	for _, p := range paths {
89		if strings.HasPrefix(path.Base(p), ".") {
90			continue
91		}
92		pi, err := MakePathInfo(p)
93		if err != nil {
94			return nil, err
95		}
96		pis = append(pis, pi)
97	}
98	return pis, nil
99}
100
101func extractQualifier(s string) string {
102	base := path.Base(s)
103	parts := strings.SplitN(base, "-", 2)
104	if len(parts) > 1 {
105		return parts[1]
106	}
107	return ""
108}
109