haiku/src/system/kernel/disk_device_manager/UserDataWriter.cpp
Axel Dörfler 2d690920ac Renamed system/core to system/kernel.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12360 a95241bf-73f2-0310-859d-f6bbb57e9c96
2005-04-13 13:22:10 +00:00

153 lines
3.1 KiB
C++

// UserDataWriter.cpp
#include <util/kernel_cpp.h>
#include <ddm_userland_interface.h>
#include <Vector.h>
#include "UserDataWriter.h"
using namespace std;
typedef uint8 *addr;
// RelocationEntryList
struct UserDataWriter::RelocationEntryList : Vector<addr*> {};
// constructor
UserDataWriter::UserDataWriter()
: fBuffer(NULL),
fBufferSize(0),
fAllocatedSize(0),
fRelocationEntries(NULL)
{
}
// constructor
UserDataWriter::UserDataWriter(user_disk_device_data *buffer,
size_t bufferSize)
: fBuffer(NULL),
fBufferSize(0),
fAllocatedSize(0),
fRelocationEntries(NULL)
{
SetTo(buffer, bufferSize);
}
// destructor
UserDataWriter::~UserDataWriter()
{
delete fRelocationEntries;
}
// SetTo
status_t
UserDataWriter::SetTo(user_disk_device_data *buffer, size_t bufferSize)
{
Unset();
fBuffer = buffer;
fBufferSize = bufferSize;
fAllocatedSize = 0;
if (fBuffer && fBufferSize > 0) {
fRelocationEntries = new(nothrow) RelocationEntryList;
if (!fRelocationEntries)
return B_NO_MEMORY;
}
return B_OK;
}
// Unset
void
UserDataWriter::Unset()
{
delete fRelocationEntries;
fBuffer = NULL;
fBufferSize = 0;
fAllocatedSize = 0;
fRelocationEntries = NULL;
}
// AllocateData
void *
UserDataWriter::AllocateData(size_t size, size_t align)
{
// handles size == 0 gracefully
// get a properly aligned offset
size_t offset = fAllocatedSize;
if (align > 1)
offset = (fAllocatedSize + align - 1) / align * align;
// get the result pointer
void *result = NULL;
if (fBuffer && offset + size <= fBufferSize)
result = (uint8*)fBuffer + offset;
// always update the allocated size, even if there wasn't enough space
fAllocatedSize = offset + size;
return result;
}
// AllocatePartitionData
user_partition_data *
UserDataWriter::AllocatePartitionData(size_t childCount)
{
return (user_partition_data*)AllocateData(
sizeof(user_partition_data)
+ sizeof(user_partition_data*) * ((int32)childCount - 1),
sizeof(int));
}
// AllocateDeviceData
user_disk_device_data *
UserDataWriter::AllocateDeviceData(size_t childCount)
{
return (user_disk_device_data*)AllocateData(
sizeof(user_disk_device_data)
+ sizeof(user_partition_data*) * ((int32)childCount - 1),
sizeof(int));
}
// PlaceString
char *
UserDataWriter::PlaceString(const char *str)
{
if (!str)
return NULL;
size_t len = strlen(str) + 1;
char *data = (char*)AllocateData(len);
if (data)
memcpy(data, str, len);
return data;
}
// AllocatedSize
size_t
UserDataWriter::AllocatedSize() const
{
return fAllocatedSize;
}
// AddRelocationEntry
status_t
UserDataWriter::AddRelocationEntry(void *address)
{
if (fRelocationEntries && (addr)address >= (addr)fBuffer
&& (addr)address < (addr)fBuffer + fBufferSize - sizeof(void*)) {
return fRelocationEntries->PushBack((addr*)address);
}
return B_ERROR;
}
// Relocate
status_t
UserDataWriter::Relocate(void *address)
{
if (!fRelocationEntries || !fBuffer)
return B_BAD_VALUE;
int32 count = fRelocationEntries->Count();
for (int32 i = 0; i < count; i++) {
addr *entry = fRelocationEntries->ElementAt(i);
if (*entry)
*entry += (addr)address - (addr)fBuffer;
}
return B_OK;
}