15a1d355fSStephan Aßmus// Path.cpp
25a1d355fSStephan Aßmus
35a1d355fSStephan Aßmus#include <stdlib.h>
45a1d355fSStephan Aßmus#include <string.h>
55a1d355fSStephan Aßmus
65a1d355fSStephan Aßmus#include <StorageDefs.h>
75a1d355fSStephan Aßmus
85a1d355fSStephan Aßmus#include "Path.h"
95a1d355fSStephan Aßmus
105a1d355fSStephan Aßmus// constructor
115a1d355fSStephan AßmusPath::Path()
125a1d355fSStephan Aßmus	: fBuffer(NULL),
135a1d355fSStephan Aßmus	  fBufferSize(0),
145a1d355fSStephan Aßmus	  fLength(0)
155a1d355fSStephan Aßmus{
165a1d355fSStephan Aßmus}
175a1d355fSStephan Aßmus
185a1d355fSStephan Aßmus// destructor
195a1d355fSStephan AßmusPath::~Path()
205a1d355fSStephan Aßmus{
215a1d355fSStephan Aßmus	free(fBuffer);
225a1d355fSStephan Aßmus}
235a1d355fSStephan Aßmus
245a1d355fSStephan Aßmus// SetTo
255a1d355fSStephan Aßmusstatus_t
265a1d355fSStephan AßmusPath::SetTo(const char* path, const char* leaf)
275a1d355fSStephan Aßmus{
285a1d355fSStephan Aßmus	if (!path)
295a1d355fSStephan Aßmus		return B_BAD_VALUE;
305a1d355fSStephan Aßmus
315a1d355fSStephan Aßmus	// get the base path len
325a1d355fSStephan Aßmus	int32 len = strlen(path);
335a1d355fSStephan Aßmus	if (len == 0)
345a1d355fSStephan Aßmus		return B_BAD_VALUE;
355a1d355fSStephan Aßmus
365a1d355fSStephan Aßmus	// get leaf len and check, if a separator needs to be inserted
375a1d355fSStephan Aßmus	bool insertSeparator = false;
385a1d355fSStephan Aßmus	int32 leafLen = 0;
395a1d355fSStephan Aßmus	if (leaf) {
405a1d355fSStephan Aßmus		leafLen = strlen(leaf);
415a1d355fSStephan Aßmus		if (leafLen > 0)
425a1d355fSStephan Aßmus			insertSeparator = (path[len - 1] != '/' && leaf[0] != '/');
435a1d355fSStephan Aßmus	}
445a1d355fSStephan Aßmus
455a1d355fSStephan Aßmus	// compute the resulting length and resize the buffer
465a1d355fSStephan Aßmus	int32 wholeLen = len + leafLen + (insertSeparator ? 1 : 0);
475a1d355fSStephan Aßmus	status_t error = _Resize(wholeLen + 1);
485a1d355fSStephan Aßmus	if (error != B_OK)
495a1d355fSStephan Aßmus		return error;
505a1d355fSStephan Aßmus
515a1d355fSStephan Aßmus	// copy path
525a1d355fSStephan Aßmus	memcpy(fBuffer, path, len);
535a1d355fSStephan Aßmus
545a1d355fSStephan Aßmus	// insert separator
555a1d355fSStephan Aßmus	if (insertSeparator)
565a1d355fSStephan Aßmus		fBuffer[len++] = '/';
575a1d355fSStephan Aßmus
585a1d355fSStephan Aßmus	// append leaf
595a1d355fSStephan Aßmus	if (leafLen > 0)
605a1d355fSStephan Aßmus		memcpy(fBuffer + len, leaf, leafLen);
615a1d355fSStephan Aßmus
625a1d355fSStephan Aßmus	// null terminate
635a1d355fSStephan Aßmus	fBuffer[wholeLen] = '\0';
645a1d355fSStephan Aßmus	fLength = wholeLen;
655a1d355fSStephan Aßmus	return B_OK;
665a1d355fSStephan Aßmus}
675a1d355fSStephan Aßmus
685a1d355fSStephan Aßmus// Append
695a1d355fSStephan Aßmusstatus_t
705a1d355fSStephan AßmusPath::Append(const char* leaf)
715a1d355fSStephan Aßmus{
725a1d355fSStephan Aßmus	if (!leaf)
735a1d355fSStephan Aßmus		return B_BAD_VALUE;
745a1d355fSStephan Aßmus
755a1d355fSStephan Aßmus	if (fLength == 0)
765a1d355fSStephan Aßmus		return SetTo(leaf);
775a1d355fSStephan Aßmus
785a1d355fSStephan Aßmus	// get the leaf len
795a1d355fSStephan Aßmus	int32 leafLen = strlen(leaf);
805a1d355fSStephan Aßmus	if (leafLen == 0)
815a1d355fSStephan Aßmus		return B_BAD_VALUE;
825a1d355fSStephan Aßmus
835a1d355fSStephan Aßmus	// check, if we need a separator
845a1d355fSStephan Aßmus	bool insertSeparator = (fBuffer[fLength - 1] != '/' && leaf[0] != '/');
855a1d355fSStephan Aßmus
865a1d355fSStephan Aßmus	// compute the resulting length and resize the buffer
875a1d355fSStephan Aßmus	int32 wholeLen = fLength + leafLen + (insertSeparator ? 1 : 0);
885a1d355fSStephan Aßmus	status_t error = _Resize(wholeLen + 1);
895a1d355fSStephan Aßmus	if (error != B_OK)
905a1d355fSStephan Aßmus		return error;
915a1d355fSStephan Aßmus
925a1d355fSStephan Aßmus	// insert separator
935a1d355fSStephan Aßmus	if (insertSeparator)
945a1d355fSStephan Aßmus		fBuffer[fLength++] = '/';
955a1d355fSStephan Aßmus
965a1d355fSStephan Aßmus	// append leaf
975a1d355fSStephan Aßmus	if (leafLen > 0)
985a1d355fSStephan Aßmus		memcpy(fBuffer + fLength, leaf, leafLen + 1);
995a1d355fSStephan Aßmus
1005a1d355fSStephan Aßmus	fLength = wholeLen;
1015a1d355fSStephan Aßmus	return B_OK;
1025a1d355fSStephan Aßmus}
1035a1d355fSStephan Aßmus
1045a1d355fSStephan Aßmus// GetPath
1055a1d355fSStephan Aßmusconst char*
1065a1d355fSStephan AßmusPath::GetPath() const
1075a1d355fSStephan Aßmus{
1085a1d355fSStephan Aßmus	return (fLength == 0 ? NULL : fBuffer);
1095a1d355fSStephan Aßmus}
1105a1d355fSStephan Aßmus
1115a1d355fSStephan Aßmus// GetLength
1125a1d355fSStephan Aßmusint32
1135a1d355fSStephan AßmusPath::GetLength() const
1145a1d355fSStephan Aßmus{
1155a1d355fSStephan Aßmus	return fLength;
1165a1d355fSStephan Aßmus}
1175a1d355fSStephan Aßmus
1185a1d355fSStephan Aßmus// _Resize
1195a1d355fSStephan Aßmusstatus_t
1205a1d355fSStephan AßmusPath::_Resize(int32 minLen)
1215a1d355fSStephan Aßmus{
1225a1d355fSStephan Aßmus	// align to multiples of B_PATH_NAME_LENGTH
1235a1d355fSStephan Aßmus	minLen = (minLen + B_PATH_NAME_LENGTH - 1)
1245a1d355fSStephan Aßmus		/ B_PATH_NAME_LENGTH * B_PATH_NAME_LENGTH;
1255a1d355fSStephan Aßmus
1265a1d355fSStephan Aßmus	if (minLen != fBufferSize) {
1275a1d355fSStephan Aßmus		char* buffer = (char*)realloc(fBuffer, minLen);
1285a1d355fSStephan Aßmus		if (!buffer)
1295a1d355fSStephan Aßmus			return B_NO_MEMORY;
1305a1d355fSStephan Aßmus
1315a1d355fSStephan Aßmus		fBuffer = buffer;
1325a1d355fSStephan Aßmus		fBufferSize = minLen;
1335a1d355fSStephan Aßmus	}
1345a1d355fSStephan Aßmus
1355a1d355fSStephan Aßmus	return B_OK;
1365a1d355fSStephan Aßmus}
137