1 // Path.cpp
2
3 #include <stdlib.h>
4 #include <string.h>
5
6 #include <StorageDefs.h>
7
8 #include "Path.h"
9
10 // constructor
Path()11 Path::Path()
12 : fBuffer(NULL),
13 fBufferSize(0),
14 fLength(0)
15 {
16 }
17
18 // destructor
~Path()19 Path::~Path()
20 {
21 free(fBuffer);
22 }
23
24 // SetTo
25 status_t
SetTo(const char * path,const char * leaf)26 Path::SetTo(const char* path, const char* leaf)
27 {
28 if (!path)
29 return B_BAD_VALUE;
30
31 // get the base path len
32 int32 len = strlen(path);
33 if (len == 0)
34 return B_BAD_VALUE;
35
36 // get leaf len and check, if a separator needs to be inserted
37 bool insertSeparator = false;
38 int32 leafLen = 0;
39 if (leaf) {
40 leafLen = strlen(leaf);
41 if (leafLen > 0)
42 insertSeparator = (path[len - 1] != '/' && leaf[0] != '/');
43 }
44
45 // compute the resulting length and resize the buffer
46 int32 wholeLen = len + leafLen + (insertSeparator ? 1 : 0);
47 status_t error = _Resize(wholeLen + 1);
48 if (error != B_OK)
49 return error;
50
51 // copy path
52 memcpy(fBuffer, path, len);
53
54 // insert separator
55 if (insertSeparator)
56 fBuffer[len++] = '/';
57
58 // append leaf
59 if (leafLen > 0)
60 memcpy(fBuffer + len, leaf, leafLen);
61
62 // null terminate
63 fBuffer[wholeLen] = '\0';
64 fLength = wholeLen;
65 return B_OK;
66 }
67
68 // Append
69 status_t
Append(const char * leaf)70 Path::Append(const char* leaf)
71 {
72 if (!leaf)
73 return B_BAD_VALUE;
74
75 if (fLength == 0)
76 return SetTo(leaf);
77
78 // get the leaf len
79 int32 leafLen = strlen(leaf);
80 if (leafLen == 0)
81 return B_BAD_VALUE;
82
83 // check, if we need a separator
84 bool insertSeparator = (fBuffer[fLength - 1] != '/' && leaf[0] != '/');
85
86 // compute the resulting length and resize the buffer
87 int32 wholeLen = fLength + leafLen + (insertSeparator ? 1 : 0);
88 status_t error = _Resize(wholeLen + 1);
89 if (error != B_OK)
90 return error;
91
92 // insert separator
93 if (insertSeparator)
94 fBuffer[fLength++] = '/';
95
96 // append leaf
97 if (leafLen > 0)
98 memcpy(fBuffer + fLength, leaf, leafLen + 1);
99
100 fLength = wholeLen;
101 return B_OK;
102 }
103
104 // GetPath
105 const char*
GetPath() const106 Path::GetPath() const
107 {
108 return (fLength == 0 ? NULL : fBuffer);
109 }
110
111 // GetLength
112 int32
GetLength() const113 Path::GetLength() const
114 {
115 return fLength;
116 }
117
118 // _Resize
119 status_t
_Resize(int32 minLen)120 Path::_Resize(int32 minLen)
121 {
122 // align to multiples of B_PATH_NAME_LENGTH
123 minLen = (minLen + B_PATH_NAME_LENGTH - 1)
124 / B_PATH_NAME_LENGTH * B_PATH_NAME_LENGTH;
125
126 if (minLen != fBufferSize) {
127 char* buffer = (char*)realloc(fBuffer, minLen);
128 if (!buffer)
129 return B_NO_MEMORY;
130
131 fBuffer = buffer;
132 fBufferSize = minLen;
133 }
134
135 return B_OK;
136 }
137