2 * Copyright 2004-2007, Ingo Weinhold, bonefish@users.sf.net.
3 * Distributed under the terms of the MIT License.
6 /** A simple class wrapping a path. Has a fixed-sized buffer. */
12 #include "fssh_string.h"
18 //#define TRACE(x) dprintf x
21 KPath::KPath(fssh_size_t bufferSize
)
28 SetTo(NULL
, bufferSize
);
32 KPath::KPath(const char* path
, bool normalize
, fssh_size_t bufferSize
)
39 SetTo(path
, normalize
, bufferSize
);
43 KPath::KPath(const KPath
& other
)
61 KPath::SetTo(const char* path
, bool normalize
, fssh_size_t bufferSize
)
64 bufferSize
= FSSH_B_PATH_NAME_LENGTH
;
66 // free the previous buffer, if the buffer size differs
67 if (fBuffer
&& fBufferSize
!= bufferSize
) {
77 fBuffer
= (char*)malloc(bufferSize
);
79 return FSSH_B_NO_MEMORY
;
81 fBufferSize
= bufferSize
;
84 return SetPath(path
, normalize
);
89 KPath::InitCheck() const
91 return fBuffer
? FSSH_B_OK
: FSSH_B_NO_MEMORY
;
96 KPath::SetPath(const char *path
, bool normalize
)
99 return FSSH_B_NO_INIT
;
104 fssh_status_t error
= vfs_normalize_path(path
, fBuffer
, fBufferSize
,
106 if (error
!= FSSH_B_OK
) {
110 fPathLength
= fssh_strlen(fBuffer
);
112 // don't normalize path
113 fssh_size_t length
= fssh_strlen(path
);
114 if (length
>= fBufferSize
)
115 return FSSH_B_BUFFER_OVERFLOW
;
117 fssh_memcpy(fBuffer
, path
, length
+ 1);
118 fPathLength
= length
;
119 _ChopTrailingSlashes();
139 if (!fBuffer
|| fLocked
)
148 KPath::UnlockBuffer()
151 TRACE(("KPath::UnlockBuffer(): ERROR: Buffer not locked!\n"));
155 fPathLength
= fssh_strnlen(fBuffer
, fBufferSize
);
156 if (fPathLength
== fBufferSize
) {
157 TRACE(("KPath::UnlockBuffer(): WARNING: Unterminated buffer!\n"));
159 fBuffer
[fPathLength
] = '\0';
161 _ChopTrailingSlashes();
171 // only "/" has trailing slashes -- then we have to return the complete
172 // buffer, as we have to do in case there are no slashes at all
173 if (fPathLength
!= 1 || fBuffer
[0] != '/') {
174 for (int32_t i
= fPathLength
- 1; i
>= 0; i
--) {
175 if (fBuffer
[i
] == '/')
176 return fBuffer
+ i
+ 1;
184 KPath::ReplaceLeaf(const char *newLeaf
)
186 const char *leaf
= Leaf();
188 return FSSH_B_NO_INIT
;
190 int32_t leafIndex
= leaf
- fBuffer
;
191 // chop off the current leaf (don't replace "/", though)
192 if (leafIndex
!= 0 || fBuffer
[leafIndex
- 1]) {
193 fBuffer
[leafIndex
] = '\0';
194 fPathLength
= leafIndex
;
195 _ChopTrailingSlashes();
198 // if a leaf was given, append it
200 return Append(newLeaf
);
206 KPath::Append(const char *component
, bool isComponent
)
208 // check initialization and parameter
210 return FSSH_B_NO_INIT
;
212 return FSSH_B_BAD_VALUE
;
213 if (fPathLength
== 0)
214 return SetPath(component
);
216 // get component length
217 fssh_size_t componentLength
= fssh_strlen(component
);
218 if (componentLength
< 1)
221 // if our current path is empty, we just copy the supplied one
222 // compute the result path len
223 bool insertSlash
= isComponent
&& fBuffer
[fPathLength
- 1] != '/'
224 && component
[0] != '/';
225 fssh_size_t resultPathLength
= fPathLength
+ componentLength
+ (insertSlash
? 1 : 0);
226 if (resultPathLength
>= fBufferSize
)
227 return FSSH_B_BUFFER_OVERFLOW
;
229 // compose the result path
231 fBuffer
[fPathLength
++] = '/';
232 fssh_memcpy(fBuffer
+ fPathLength
, component
, componentLength
+ 1);
233 fPathLength
= resultPathLength
;
239 KPath::operator=(const KPath
& other
)
241 SetTo(other
.fBuffer
, other
.fBufferSize
);
247 KPath::operator=(const char* path
)
255 KPath::operator==(const KPath
& other
) const
258 return !other
.fBuffer
;
260 return (other
.fBuffer
261 && fPathLength
== other
.fPathLength
262 && fssh_strcmp(fBuffer
, other
.fBuffer
) == 0);
267 KPath::operator==(const char* path
) const
272 return path
&& !fssh_strcmp(fBuffer
, path
);
277 KPath::operator!=(const KPath
& other
) const
279 return !(*this == other
);
284 KPath::operator!=(const char* path
) const
286 return !(*this == path
);
291 KPath::_ChopTrailingSlashes()
294 while (fPathLength
> 1 && fBuffer
[fPathLength
- 1] == '/')
295 fBuffer
[--fPathLength
] = '\0';