
plus fixes for the bugs they exposes. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3416 a95241bf-73f2-0310-859d-f6bbb57e9c96
396 lines
9.8 KiB
C++
396 lines
9.8 KiB
C++
//------------------------------------------------------------------------------
|
|
// 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 (erik@cgsoftware.com)
|
|
// 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 (!name || 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;
|
|
if (!name)
|
|
{
|
|
err = B_BAD_VALUE;
|
|
return Item;
|
|
}
|
|
|
|
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 $
|
|
*
|
|
*/
|
|
|