1 /*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <androidfw/PathUtils.h>
18
19 #include <utils/Compat.h>
20
21 namespace android {
22
getPathLeaf(const String8 & str)23 String8 getPathLeaf(const String8& str) {
24 const char* cp;
25 const char*const buf = str.c_str();
26
27 cp = strrchr(buf, OS_PATH_SEPARATOR);
28 if (cp == nullptr)
29 return str;
30 else
31 return String8(cp+1);
32 }
33
getPathDir(const String8 & str8)34 String8 getPathDir(const String8& str8) {
35 const char* cp;
36 const char*const str = str8.c_str();
37
38 cp = strrchr(str, OS_PATH_SEPARATOR);
39 if (cp == nullptr)
40 return String8();
41 else
42 return String8(str, cp - str);
43 }
44
findExtension(const String8 & str8)45 static char* findExtension(const String8& str8) {
46 const char* lastSlash;
47 const char* lastDot;
48 const char* const str = str8.c_str();
49
50 // only look at the filename
51 lastSlash = strrchr(str, OS_PATH_SEPARATOR);
52 if (lastSlash == nullptr)
53 lastSlash = str;
54 else
55 lastSlash++;
56
57 // find the last dot
58 lastDot = strrchr(lastSlash, '.');
59 if (lastDot == nullptr)
60 return nullptr;
61
62 // looks good, ship it
63 return const_cast<char*>(lastDot);
64 }
65
getPathExtension(const String8 & str)66 String8 getPathExtension(const String8& str) {
67 char* ext;
68
69 ext = findExtension(str);
70 if (ext != nullptr)
71 return String8(ext);
72 else
73 return String8();
74 }
75
getBasePath(const String8 & str8)76 String8 getBasePath(const String8& str8) {
77 char* ext;
78 const char* const str = str8.c_str();
79
80 ext = findExtension(str8);
81 if (ext == nullptr)
82 return str8;
83 else
84 return String8(str, ext - str);
85 }
86
setPathName(String8 & s,const char * name)87 static void setPathName(String8& s, const char* name) {
88 size_t len = strlen(name);
89 char* buf = s.lockBuffer(len);
90
91 memcpy(buf, name, len);
92
93 // remove trailing path separator, if present
94 if (len > 0 && buf[len - 1] == OS_PATH_SEPARATOR) len--;
95 buf[len] = '\0';
96
97 s.unlockBuffer(len);
98 }
99
appendPath(String8 & str,const char * name)100 String8& appendPath(String8& str, const char* name) {
101 // TODO: The test below will fail for Win32 paths. Fix later or ignore.
102 if (name[0] != OS_PATH_SEPARATOR) {
103 if (*name == '\0') {
104 // nothing to do
105 return str;
106 }
107
108 size_t len = str.length();
109 if (len == 0) {
110 // no existing filename, just use the new one
111 setPathName(str, name);
112 return str;
113 }
114
115 // make room for oldPath + '/' + newPath
116 int newlen = strlen(name);
117
118 char* buf = str.lockBuffer(len+1+newlen);
119
120 // insert a '/' if needed
121 if (buf[len-1] != OS_PATH_SEPARATOR)
122 buf[len++] = OS_PATH_SEPARATOR;
123
124 memcpy(buf+len, name, newlen+1);
125 len += newlen;
126
127 str.unlockBuffer(len);
128 return str;
129 } else {
130 setPathName(str, name);
131 return str;
132 }
133 }
134
135 } // namespace android
136