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
11Path::Path()
12	: fBuffer(NULL),
13	  fBufferSize(0),
14	  fLength(0)
15{
16}
17
18// destructor
19Path::~Path()
20{
21	free(fBuffer);
22}
23
24// SetTo
25status_t
26Path::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
69status_t
70Path::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
105const char*
106Path::GetPath() const
107{
108	return (fLength == 0 ? NULL : fBuffer);
109}
110
111// GetLength
112int32
113Path::GetLength() const
114{
115	return fLength;
116}
117
118// _Resize
119status_t
120Path::_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