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:
ejakowatz
2003-03-19 07:58:17 +00:00
parent 8eb9c15d4f
commit b1055b4c2d
10 changed files with 1725 additions and 0 deletions
+390
View File
@@ -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 $
*
*/
+50
View File
@@ -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 $
*
*/
+57
View File
@@ -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 $
*
*/
+4
View File
@@ -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
+129
View File
@@ -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 $
*
*/
+1
View File
@@ -9,4 +9,5 @@ SUPPORT_KIT_SOURCE =
StopWatch.cpp
String.cpp
string_helper.cpp
# StreamIO.cpp
;