xref: /haiku/src/add-ons/kernel/file_systems/netfs/server/Path.cpp (revision 2b76973fa2401f7a5edf68e6470f3d3210cbcff3)
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
11 Path::Path()
12 	: fBuffer(NULL),
13 	  fBufferSize(0),
14 	  fLength(0)
15 {
16 }
17 
18 // destructor
19 Path::~Path()
20 {
21 	free(fBuffer);
22 }
23 
24 // SetTo
25 status_t
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
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*
106 Path::GetPath() const
107 {
108 	return (fLength == 0 ? NULL : fBuffer);
109 }
110 
111 // GetLength
112 int32
113 Path::GetLength() const
114 {
115 	return fLength;
116 }
117 
118 // _Resize
119 status_t
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