Added class KPath. Convenient wrapper for a fixed-sized path buffer.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9541 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2004-10-27 21:41:16 +00:00
parent 42b568aeb5
commit d68a188e6d
2 changed files with 287 additions and 0 deletions

View File

@ -0,0 +1,54 @@
// KPath.h
//
// A simple class wrapping a path. Has a fixed-sized buffer.
#ifndef _K_PATH_H
#define _K_PATH_H
#include <KernelExport.h>
namespace BPrivate {
namespace DiskDevice {
class KPath {
public:
KPath(int32 bufferSize = B_PATH_NAME_LENGTH);
KPath(const char* path, int32 bufferSize = B_PATH_NAME_LENGTH);
KPath(const KPath& other);
~KPath();
status_t SetTo(const char *path, int32 bufferSize = B_PATH_NAME_LENGTH);
status_t InitCheck() const;
status_t SetPath(const char *path);
const char* Path() const;
int32 Length() const;
int32 BufferSize() const;
char *LockBuffer();
void UnlockBuffer();
status_t Append(const char *component);
KPath& operator=(const KPath& other);
KPath& operator=(const char* path);
bool operator==(const KPath& other) const;
bool operator==(const char* path) const;
bool operator!=(const KPath& other) const;
bool operator!=(const char* path) const;
private:
char* fBuffer;
int32 fBufferSize;
int32 fPathLength;
bool fLocked;
};
} // namespace DiskDevice
} // namespace BPrivate
using BPrivate::DiskDevice::KPath;
#endif _K_PATH_H

View File

@ -0,0 +1,233 @@
// KPath.cpp
#include <stdlib.h>
#include <string.h>
#include <KPath.h>
// debugging
#define DBG(x)
//#define DBG(x) x
#define OUT dprintf
// constructor
KPath::KPath(int32 bufferSize)
: fBuffer(NULL),
fBufferSize(0),
fPathLength(0),
fLocked(false)
{
SetTo(NULL, bufferSize);
}
// constructor
KPath::KPath(const char* path, int32 bufferSize)
: fBuffer(NULL),
fBufferSize(0),
fPathLength(0),
fLocked(false)
{
SetTo(path, bufferSize);
}
// copy constructor
KPath::KPath(const KPath& other)
: fBuffer(NULL),
fBufferSize(0),
fPathLength(0),
fLocked(false)
{
*this = other;
}
// destructor
KPath::~KPath()
{
free(fBuffer);
}
// SetTo
status_t
KPath::SetTo(const char* path, int32 bufferSize)
{
if (bufferSize <= 0)
bufferSize = B_PATH_NAME_LENGTH;
// free the previous buffer, if the buffer size differs
if (fBuffer && fBufferSize != bufferSize) {
free(fBuffer);
fBuffer = NULL;
fBufferSize = 0;
}
fPathLength = 0;
fLocked = false;
// allocate buffer
if (!fBuffer)
fBuffer = (char*)malloc(bufferSize);
if (!fBuffer)
return B_NO_MEMORY;
if (fBuffer) {
fBufferSize = bufferSize;
fBuffer[0] = '\0';
}
return SetPath(path);
}
// InitCheck
status_t
KPath::InitCheck() const
{
return (fBuffer ? B_OK : B_NO_MEMORY);
}
// SetPath
status_t
KPath::SetPath(const char *path)
{
if (!fBuffer)
return B_NO_INIT;
if (path) {
int32 len = strlen(path);
if (len >= fBufferSize)
return B_BUFFER_OVERFLOW;
memcpy(fBuffer, path, len + 1);
fPathLength = len;
} else {
fBuffer[0] = '\0';
fPathLength = 0;
}
return B_OK;
}
// Path
const char*
KPath::Path() const
{
return fBuffer;
}
// Length
int32
KPath::Length() const
{
return fPathLength;
}
// BufferSize
int32
KPath::BufferSize() const
{
return fBufferSize;
}
// LockBuffer
char *
KPath::LockBuffer()
{
if (!fBuffer || fLocked)
return NULL;
fLocked = true;
return fBuffer;
}
// UnlockBuffer
void
KPath::UnlockBuffer()
{
if (!fLocked) {
DBG(OUT("KPath::UnlockBuffer(): ERROR: Buffer not locked!\n"));
return;
}
fLocked = false;
fPathLength = strnlen(fBuffer, fBufferSize);
if (fPathLength == fBufferSize) {
DBG(OUT("KPath::UnlockBuffer(): WARNING: Unterminated buffer!\n"));
fPathLength--;
fBuffer[fPathLength] = '\0';
}
}
// Append
status_t
KPath::Append(const char *component)
{
// check initialization and parameter
if (!fBuffer)
return B_NO_INIT;
if (!component)
return B_BAD_VALUE;
// get componentn length
int32 componentLen = strlen(component);
if (componentLen < 1)
return B_OK;
// if our current path is empty, we just copy the supplied one
if (fPathLength == 0) {
if (componentLen >= fBufferSize)
return B_BUFFER_OVERFLOW;
memcpy(fBuffer, component, componentLen + 1);
fPathLength = componentLen;
return B_OK;
}
// compute the result path len
bool insertSlash = (fBuffer[fPathLength - 1] != '/'
&& component[0] != '/');
int32 resultPathLen = fPathLength + componentLen + (insertSlash ? 1 : 0);
if (resultPathLen >= fBufferSize)
return B_BUFFER_OVERFLOW;
// compose the result path
if (insertSlash)
fBuffer[fPathLength++] = '/';
memcpy(fBuffer + fPathLength, component, componentLen + 1);
fPathLength = resultPathLen;
return B_OK;
}
// =
KPath&
KPath::operator=(const KPath& other)
{
SetTo(other.fBuffer, other.fBufferSize);
return *this;
}
// =
KPath&
KPath::operator=(const char* path)
{
SetTo(path);
return *this;
}
// ==
bool
KPath::operator==(const KPath& other) const
{
if (!fBuffer)
return (!other.fBuffer);
return (other.fBuffer
&& fPathLength == other.fPathLength
&& strcmp(fBuffer, other.fBuffer) == 0);
}
// ==
bool
KPath::operator==(const char* path) const
{
if (!fBuffer)
return (!path);
return (path && strcmp(fBuffer, path) == 0);
}
// !=
bool
KPath::operator!=(const KPath& other) const
{
return !(*this == other);
}
// !=
bool
KPath::operator!=(const char* path) const
{
return !(*this == path);
}