This is all the code for the backing store for BMessage (BMessageBody &
BMessageField) for the "template madness" version. Also included is BDataBuffer which is a little reference counting raw data container. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2955 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,390 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) 2001-2002, OpenBeOS
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the "Software"),
|
||||
// to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Software, and to permit persons to whom the
|
||||
// Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// File Name: MessageBody.cpp
|
||||
// Author(s): Erik Jaesler ([email protected])
|
||||
// Description: BMessageBody handles data storage and retrieval for
|
||||
// BMessage.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Standard Includes -----------------------------------------------------------
|
||||
#include <stdio.h>
|
||||
|
||||
// System Includes -------------------------------------------------------------
|
||||
#include <TypeConstants.h>
|
||||
|
||||
// Project Includes ------------------------------------------------------------
|
||||
#include <MessageBody.h>
|
||||
|
||||
// Local Includes --------------------------------------------------------------
|
||||
|
||||
// Local Defines ---------------------------------------------------------------
|
||||
|
||||
// Globals ---------------------------------------------------------------------
|
||||
|
||||
namespace BPrivate {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
BMessageBody::BMessageBody()
|
||||
: fFlattenedSize(0)
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
BMessageBody::BMessageBody(const BMessageBody &rhs)
|
||||
{
|
||||
*this = rhs;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
BMessageBody::~BMessageBody()
|
||||
{
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
BMessageBody& BMessageBody::operator=(const BMessageBody &rhs)
|
||||
{
|
||||
if (this != &rhs)
|
||||
{
|
||||
fData = rhs.fData;
|
||||
fFlattenedSize = rhs.fFlattenedSize;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
status_t BMessageBody::GetInfo(type_code typeRequested, int32 which,
|
||||
char** name, type_code* typeReturned,
|
||||
int32* count) const
|
||||
{
|
||||
TMsgDataMap::const_iterator i = fData.begin();
|
||||
int32 index = 0;
|
||||
for (index = 0; i != fData.end(); ++i)
|
||||
{
|
||||
if (B_ANY_TYPE == typeRequested && i->second->Type() == typeRequested)
|
||||
{
|
||||
++index;
|
||||
if (index == which)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We couldn't find any appropriate data
|
||||
if (i == fData.end())
|
||||
{
|
||||
// TODO: research
|
||||
// Which gets returned on an empty message with
|
||||
// typeRequested == B_ANY_TYPE?
|
||||
if (index)
|
||||
{
|
||||
// TODO: research
|
||||
// Is B_NAME_NOT_FOUND ever really returned from this function, as
|
||||
// the BeBook claims?
|
||||
return B_BAD_INDEX;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (count) *count = 0;
|
||||
return B_BAD_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: BC Break
|
||||
// Change 'name' parameter to const char*
|
||||
*name = const_cast<char*>(i->first.c_str());
|
||||
*typeReturned = i->second->Type();
|
||||
if (count) *count = i->second->CountItems();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
status_t BMessageBody::GetInfo(const char* name, type_code* type,
|
||||
int32* c) const
|
||||
{
|
||||
status_t err;
|
||||
BMessageField* BMF = FindData(name, B_ANY_TYPE, err);
|
||||
if (BMF)
|
||||
{
|
||||
*type = BMF->Type();
|
||||
if (c)
|
||||
{
|
||||
*c = BMF->CountItems();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c)
|
||||
{
|
||||
*c = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
status_t BMessageBody::GetInfo(const char* name, type_code* type,
|
||||
bool* fixed_size) const
|
||||
{
|
||||
status_t err;
|
||||
BMessageField* BMF = FindData(name, B_ANY_TYPE, err);
|
||||
if (BMF)
|
||||
{
|
||||
*type = BMF->Type();
|
||||
*fixed_size = BMF->FixedSize();
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int32 BMessageBody::CountNames(type_code type) const
|
||||
{
|
||||
if (type == B_ANY_TYPE)
|
||||
{
|
||||
return fData.size();
|
||||
}
|
||||
|
||||
int32 count = 0;
|
||||
for (TMsgDataMap::const_iterator i = fData.begin(); i != fData.end(); ++i)
|
||||
{
|
||||
if (type == B_ANY_TYPE || i->second->Type() == type)
|
||||
{
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool BMessageBody::IsEmpty() const
|
||||
{
|
||||
return fData.empty();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void BMessageBody::PrintToStream() const
|
||||
{
|
||||
// TODO: implement
|
||||
for (TMsgDataMap::const_iterator i = fData.begin(); i != fData.end(); ++i)
|
||||
{
|
||||
i->second->PrintToStream(i->first.c_str());
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
status_t BMessageBody::Rename(const char* old_entry, const char* new_entry)
|
||||
{
|
||||
TMsgDataMap::iterator i = fData.find(old_entry);
|
||||
if (i == fData.end())
|
||||
{
|
||||
return B_NAME_NOT_FOUND;
|
||||
}
|
||||
fData.erase(new_entry);
|
||||
fData[new_entry] = i->second;
|
||||
fData.erase(old_entry);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
ssize_t BMessageBody::FlattenedSize() const
|
||||
{
|
||||
ssize_t size = 1; // For MSG_LAST_ENTRY
|
||||
|
||||
for (TMsgDataMap::const_iterator i = fData.begin(); i != fData.end(); ++i)
|
||||
{
|
||||
size += i->second->FlattenedSize();
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
status_t BMessageBody::Flatten(BDataIO* stream) const
|
||||
{
|
||||
status_t err = B_OK;
|
||||
|
||||
for (TMsgDataMap::const_iterator i = fData.begin();
|
||||
i != fData.end() && !err;
|
||||
++i)
|
||||
{
|
||||
err = i->second->Flatten(*stream);
|
||||
}
|
||||
|
||||
if (!err)
|
||||
{
|
||||
err = stream->Write("", 1); // For MSG_LAST_ENTRY
|
||||
if (err >= 0)
|
||||
err = B_OK;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
status_t BMessageBody::Unflatten(const char* flat_buffer)
|
||||
{
|
||||
// TODO: implement
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
status_t BMessageBody::Unflatten(BDataIO* stream)
|
||||
{
|
||||
// TODO: implement
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
status_t BMessageBody::AddData(const char* name, type_code type,
|
||||
const void* data, ssize_t numBytes,
|
||||
bool is_fixed_size, int32 /* count */)
|
||||
{
|
||||
/**
|
||||
@note The same logic applies here are in AddFlat(): is_fixed_size and
|
||||
count aren't useful to us because dynamically adding items isn't
|
||||
an issue. Nevertheless, we keep is_fixed_size to set flags
|
||||
appropriately when flattening the message.
|
||||
*/
|
||||
|
||||
// TODO: test
|
||||
// In particular, we want to see what happens if is_fixed_size == true and
|
||||
// the user attempts to add something bigger or smaller. We may need to
|
||||
// enforce the size thing.
|
||||
return B_ERROR;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
status_t BMessageBody::RemoveData(const char* name, int32 index)
|
||||
{
|
||||
if (index < 0)
|
||||
{
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
status_t err = B_OK;
|
||||
BMessageField* BMF = FindData(name, B_ANY_TYPE, err);
|
||||
if (BMF)
|
||||
{
|
||||
if (index < BMF->CountItems())
|
||||
{
|
||||
BMF->RemoveItem(index);
|
||||
if (!BMF->CountItems())
|
||||
{
|
||||
RemoveName(name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
err = B_BAD_INDEX;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
status_t BMessageBody::RemoveName(const char* name)
|
||||
{
|
||||
return fData.erase(name) ? B_OK : B_NAME_NOT_FOUND;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
status_t BMessageBody::MakeEmpty()
|
||||
{
|
||||
fData.clear();
|
||||
return B_OK;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
#if 0
|
||||
void* BMessageBody::operator new(size_t size)
|
||||
{
|
||||
return ::new BMessageBody;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void BMessageBody::operator delete(void* ptr, size_t size)
|
||||
{
|
||||
::delete(ptr);
|
||||
}
|
||||
#endif
|
||||
//------------------------------------------------------------------------------
|
||||
bool BMessageBody::HasData(const char* name, type_code t, int32 n) const
|
||||
{
|
||||
if (n < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
status_t err;
|
||||
BMessageField* BMF = FindData(name, t, err);
|
||||
if (!BMF)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (n >= BMF->CountItems())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
status_t BMessageBody::FindData(const char *name, type_code type, int32 index,
|
||||
const void **data, ssize_t *numBytes) const
|
||||
{
|
||||
status_t err;
|
||||
*data = NULL;
|
||||
BMessageField* Field = FindData(name, type, err);
|
||||
if (!err)
|
||||
{
|
||||
*data = Field->DataAt(index, numBytes);
|
||||
// TODO: verify
|
||||
if (!*data)
|
||||
{
|
||||
err = B_BAD_INDEX;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
BMessageField* BMessageBody::FindData(const char* name, type_code type,
|
||||
status_t& err) const
|
||||
{
|
||||
BMessageField* Item = NULL;
|
||||
err = B_OK;
|
||||
|
||||
TMsgDataMap::const_iterator i = fData.find(name);
|
||||
if (i == fData.end())
|
||||
{
|
||||
err = B_NAME_NOT_FOUND;
|
||||
}
|
||||
else
|
||||
{
|
||||
Item = i->second;
|
||||
if (Item->Type() != type)
|
||||
{
|
||||
err = B_BAD_TYPE;
|
||||
Item = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return Item;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} // namespace BPrivate
|
||||
|
||||
/*
|
||||
* $Log $
|
||||
*
|
||||
* $Id $
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// MessageField.cpp
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Standard Includes -----------------------------------------------------------
|
||||
|
||||
// System Includes -------------------------------------------------------------
|
||||
#include <ByteOrder.h>
|
||||
|
||||
// Project Includes ------------------------------------------------------------
|
||||
#include "MessageField.h"
|
||||
|
||||
// Local Includes --------------------------------------------------------------
|
||||
|
||||
// Local Defines ---------------------------------------------------------------
|
||||
|
||||
// Globals ---------------------------------------------------------------------
|
||||
|
||||
namespace BPrivate {
|
||||
|
||||
const char* BMessageField::sNullData = "\0\0\0\0\0\0\0\0";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void BMessageField::PrintToStream(const char* name) const
|
||||
{
|
||||
int32 type = B_BENDIAN_TO_HOST_INT32(Type());
|
||||
printf(" entry %14s, type='%.4s', c=%2ld, ",
|
||||
name, (char*)&type, CountItems());
|
||||
|
||||
for (int32 i = 0; i < CountItems(); ++i)
|
||||
{
|
||||
if (i)
|
||||
{
|
||||
printf(" ");
|
||||
}
|
||||
PrintDataItem(i);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} // namespace BPrivate
|
||||
|
||||
/*
|
||||
* $Log $
|
||||
*
|
||||
* $Id $
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// MessageUtils.cpp
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Standard Includes -----------------------------------------------------------
|
||||
|
||||
// System Includes -------------------------------------------------------------
|
||||
|
||||
// Project Includes ------------------------------------------------------------
|
||||
#include <MessageUtils.h>
|
||||
|
||||
// Local Includes --------------------------------------------------------------
|
||||
|
||||
// Local Defines ---------------------------------------------------------------
|
||||
|
||||
// Globals ---------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
uint32 _checksum_(const uchar* buf, int32 size)
|
||||
{
|
||||
uint32 sum = 0;
|
||||
uint32 temp = 0;
|
||||
|
||||
while (size > 3) {
|
||||
#if defined(__INTEL__)
|
||||
sum += B_SWAP_INT32(*(int*)buf);
|
||||
#else
|
||||
sum += *(int*)buf;
|
||||
#endif
|
||||
|
||||
buf += 4;
|
||||
size -= 4;
|
||||
}
|
||||
|
||||
while (size > 0) {
|
||||
temp = (temp << 8) + *buf++;
|
||||
size -= 1;
|
||||
sum += temp;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int32 TChecksumHelper::CheckSum()
|
||||
{
|
||||
return _checksum_(fBuffer, fBufPtr - fBuffer);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* $Log $
|
||||
*
|
||||
* $Id $
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -3,6 +3,7 @@ APP_KIT_SOURCE =
|
||||
AppMisc.cpp
|
||||
AppServerLink.cpp
|
||||
Cursor.cpp
|
||||
DataBuffer.cpp
|
||||
Clipboard.cpp
|
||||
Handler.cpp
|
||||
InitTerminateLibBe.cpp
|
||||
@@ -10,10 +11,13 @@ APP_KIT_SOURCE =
|
||||
Looper.cpp
|
||||
LooperList.cpp
|
||||
Message.cpp
|
||||
MessageBody.cpp
|
||||
MessageField.cpp
|
||||
MessageFilter.cpp
|
||||
MessageQueue.cpp
|
||||
MessageRunner.cpp
|
||||
Messenger.cpp
|
||||
MessageUtils.cpp
|
||||
PropertyInfo.cpp
|
||||
PortLink.cpp
|
||||
RegistrarDefs.cpp
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// DataBuffer.cpp
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Standard Includes -----------------------------------------------------------
|
||||
#include <string.h>
|
||||
|
||||
// System Includes -------------------------------------------------------------
|
||||
|
||||
// Project Includes ------------------------------------------------------------
|
||||
#include <DataBuffer.h>
|
||||
|
||||
// Local Includes --------------------------------------------------------------
|
||||
|
||||
// Local Defines ---------------------------------------------------------------
|
||||
|
||||
// Globals ---------------------------------------------------------------------
|
||||
|
||||
namespace BPrivate {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
BDataBuffer::BDataBuffer(size_t len)
|
||||
{
|
||||
BDataReference::Create(len, fDataRef);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
BDataBuffer::BDataBuffer(void* data, size_t len)
|
||||
{
|
||||
BDataReference::Create(data, len, fDataRef);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
BDataBuffer::BDataBuffer(const BDataBuffer& rhs)
|
||||
{
|
||||
*this = rhs;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
BDataBuffer::~BDataBuffer()
|
||||
{
|
||||
if (fDataRef)
|
||||
{
|
||||
fDataRef->Release(fDataRef);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
BDataBuffer& BDataBuffer::operator=(const BDataBuffer& rhs)
|
||||
{
|
||||
if (this != &rhs)
|
||||
{
|
||||
rhs.fDataRef->Acquire(fDataRef);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
size_t BDataBuffer::BufferSize() const
|
||||
{
|
||||
return fDataRef->Size();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
const void* BDataBuffer::Buffer()
|
||||
{
|
||||
return (const void*)fDataRef->Data();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void BDataBuffer::BDataReference::Create(void* data, size_t len,
|
||||
BDataReference*& ref)
|
||||
{
|
||||
BDataReference* temp = new BDataReference(data, len);
|
||||
temp->Acquire(ref);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void BDataBuffer::BDataReference::Create(size_t len, BDataReference*& ref)
|
||||
{
|
||||
BDataReference* temp = new BDataReference(len);
|
||||
temp->Acquire(ref);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void BDataBuffer::BDataReference::Acquire(BDataReference*& ref)
|
||||
{
|
||||
ref = this;
|
||||
++count;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void BDataBuffer::BDataReference::Release(BDataReference*& ref)
|
||||
{
|
||||
ref = NULL;
|
||||
--count;
|
||||
if (count <= 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
BDataBuffer::BDataReference::BDataReference(void* data, size_t len)
|
||||
: data(NULL), size(len), count(0)
|
||||
{
|
||||
data = new char[len];
|
||||
memcpy((void*)data, data, len);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
BDataBuffer::BDataReference::BDataReference(size_t len)
|
||||
: data(NULL), size(len), count(0)
|
||||
{
|
||||
data = new char[len];
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
BDataBuffer::BDataReference::~BDataReference()
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
delete[] data;
|
||||
data = NULL;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
} // namespace BPrivate
|
||||
|
||||
/*
|
||||
* $Log $
|
||||
*
|
||||
* $Id $
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -9,4 +9,5 @@ SUPPORT_KIT_SOURCE =
|
||||
StopWatch.cpp
|
||||
String.cpp
|
||||
string_helper.cpp
|
||||
# StreamIO.cpp
|
||||
;
|
||||
|
||||
Reference in New Issue
Block a user