2d690920ac
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12360 a95241bf-73f2-0310-859d-f6bbb57e9c96
153 lines
3.1 KiB
C++
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;
|
|
}
|
|
|