From b1055b4c2d670294fda455547a84928d9ba18eaa Mon Sep 17 00:00:00 2001 From: ejakowatz Date: Wed, 19 Mar 2003 07:58:17 +0000 Subject: [PATCH] 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 --- headers/private/app/MessageBody.h | 237 +++++++++++ headers/private/app/MessageField.h | 584 ++++++++++++++++++++++++++++ headers/private/app/MessageUtils.h | 197 ++++++++++ headers/private/shared/DataBuffer.h | 76 ++++ src/kits/app/MessageBody.cpp | 390 +++++++++++++++++++ src/kits/app/MessageField.cpp | 50 +++ src/kits/app/MessageUtils.cpp | 57 +++ src/kits/app/app.src | 4 + src/kits/support/DataBuffer.cpp | 129 ++++++ src/kits/support/support.src | 1 + 10 files changed, 1725 insertions(+) create mode 100644 headers/private/app/MessageBody.h create mode 100644 headers/private/app/MessageField.h create mode 100644 headers/private/app/MessageUtils.h create mode 100644 headers/private/shared/DataBuffer.h create mode 100644 src/kits/app/MessageBody.cpp create mode 100644 src/kits/app/MessageField.cpp create mode 100644 src/kits/app/MessageUtils.cpp create mode 100644 src/kits/support/DataBuffer.cpp diff --git a/headers/private/app/MessageBody.h b/headers/private/app/MessageBody.h new file mode 100644 index 0000000000..5fc8c8bbc0 --- /dev/null +++ b/headers/private/app/MessageBody.h @@ -0,0 +1,237 @@ +//------------------------------------------------------------------------------ +// 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.h +// Author(s): Erik Jaesler (erik@cgsoftware.com) +// Description: BMessageBody handles data storage and retrieval for +// BMessage. +//------------------------------------------------------------------------------ + +#ifndef MESSAGEBODY_H +#define MESSAGEBODY_H +#include +// Standard Includes ----------------------------------------------------------- +#include +#include +#include + +// System Includes ------------------------------------------------------------- +#include +#include +#include +#include +//#include +#include +#include + +// Project Includes ------------------------------------------------------------ + +// Local Includes -------------------------------------------------------------- + +// Local Defines --------------------------------------------------------------- + +// Globals --------------------------------------------------------------------- + +enum { B_FLATTENABLE_TYPE = 'FLAT' }; + +namespace BPrivate { + +class BMessageBody +{ +public: + BMessageBody(); + BMessageBody(const BMessageBody& rhs); + ~BMessageBody(); + + BMessageBody& operator=(const BMessageBody& rhs); + +// Statistics and misc info + status_t GetInfo(type_code typeRequested, int32 which, char **name, + type_code *typeReturned, int32 *count = NULL) const; + + status_t GetInfo(const char *name, type_code *type, int32 *c = 0) const; + status_t GetInfo(const char *name, type_code *type, bool *fixed_size) const; + + int32 CountNames(type_code type) const; + bool IsEmpty() const; + bool IsSystem() const; + bool IsReply() const; + void PrintToStream() const; + + status_t Rename(const char *old_entry, const char *new_entry); + +// Flattening data + ssize_t FlattenedSize() const; + status_t Flatten(BDataIO *stream) const; + status_t Unflatten(const char *flat_buffer); + status_t Unflatten(BDataIO *stream); + +// Removing data + status_t RemoveData(const char *name, int32 index = 0); + status_t RemoveName(const char *name); + status_t MakeEmpty(); + + bool HasData(const char* name, type_code t, int32 n) const; + + template + status_t AddData(const char* name, const T1& data, type_code type); + status_t FindData(const char* name, type_code type, int32 index, + const void** data, ssize_t* numBytes) const; + template + status_t FindData(const char* name, int32 index, T1* data, type_code type); + template + status_t ReplaceData(const char* name, int32 index, const T1& data, type_code type); + +#if 0 + void *operator new(size_t size); + void operator delete(void *ptr, size_t size); +#endif + +private: + BMessageField* FindData(const char *name, type_code type, + status_t& err) const; + + typedef std::map TMsgDataMap; + TMsgDataMap fData; + ssize_t fFlattenedSize; +}; +//------------------------------------------------------------------------------ +template +status_t BMessageBody::AddData(const char *name, const T1 &data, type_code type) +{ + // The flattened message format in R5 only allows 1 byte + // for the length of field names + if (strlen(name) > 255) return B_BAD_VALUE; + + status_t err = B_OK; + BMessageField* BMF = FindData(name, type, err); + + // Reset err; we just want the variable + err = B_OK; + + if (!BMF) + { + BMF = new(nothrow) BMessageFieldImpl(name, type); + if (BMF) + { + fData[name] = BMF; + } + else + { + err = B_NO_MEMORY; + } + } + + if (!err) + { + BMessageFieldImpl* RItem = + dynamic_cast*>(BMF); + if (!RItem) + { + debugger("\n\n\tyou \033[44;1;37mB\033[41;1;37me\033[m screwed\n\n"); + } + RItem->AddItem(data); + } + + return err; +} +//------------------------------------------------------------------------------ +template +status_t BMessageBody::FindData(const char *name, int32 index, T1 *data, + type_code type) +{ + status_t err = B_OK; + if (index < 0) + { + err = B_BAD_INDEX; + } + else + { + BMessageField* Item = FindData(name, type, err); + if (Item) + { + BMessageFieldImpl* RItem = + dynamic_cast*>(Item); + if (!RItem) + { + debugger("\n\n\tyou \033[44;1;37mB\033[41;1;37me" + "\033[m screwed\n\n"); + } + if (index < RItem->CountItems()) + { + *data = RItem->Data()[index]; + } + else + { + err = B_BAD_INDEX; + } + } + } + + return err; +} +//------------------------------------------------------------------------------ +template +status_t BMessageBody::ReplaceData(const char *name, int32 index, + const T1 &data, type_code type) +{ + status_t err = B_OK; + if (index < 0) + { + err = B_BAD_INDEX; + } + else + { + BMessageField* Item = FindData(name, type, err); + if (Item) + { + BMessageFieldImpl* RItem = + dynamic_cast*>(Item); + if (!RItem) + { + debugger("\n\n\tyou \033[44;1;37mB\033[41;1;37me\033[m screwed\n\n"); + } + if (index < RItem->Data().Size()) + { + RItem->Data()[index] = data; + } + else + { + err = B_BAD_INDEX; + } + } + } + + return err; +} +//------------------------------------------------------------------------------ + +} // namespace BPrivate + +#endif //MESSAGEBODY_H + +/* + * $Log $ + * + * $Id $ + * + */ + diff --git a/headers/private/app/MessageField.h b/headers/private/app/MessageField.h new file mode 100644 index 0000000000..6ffacc3e70 --- /dev/null +++ b/headers/private/app/MessageField.h @@ -0,0 +1,584 @@ +//------------------------------------------------------------------------------ +// 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: MessageField.h +// Author(s): Erik Jaesler (erik@cgsoftware.com) +// Description: BMessageField contains and manages the data for indiviual +// named field in BMessageBody +//------------------------------------------------------------------------------ + +#ifndef MESSAGEFIELD_H +#define MESSAGEFIELD_H + +// Standard Includes ----------------------------------------------------------- +#include +#include +#include +#include + +// System Includes ------------------------------------------------------------- +#include +#include +#include +#include +#include +#include + +// Project Includes ------------------------------------------------------------ +#include + +// Local Includes -------------------------------------------------------------- + +// Local Defines --------------------------------------------------------------- +// flags for each entry (the bitfield is 1 byte) +#define MSG_FLAG_VALID 0x01 +#define MSG_FLAG_MINI_DATA 0x02 +#define MSG_FLAG_FIXED_SIZE 0x04 +#define MSG_FLAG_SINGLE_ITEM 0x08 +#define MSG_FLAG_ALL 0x0F + +#define MSG_LAST_ENTRY 0x0 + +// Globals --------------------------------------------------------------------- +namespace BPrivate { + +class BMessageField +{ + public: + static const char* sNullData; + + BMessageField(const std::string& name, type_code t) + : fName(name), fType(t) + {;} + virtual const std::string& Name() const { return fName; } + virtual type_code Type() const { return fType; } + virtual bool FixedSize() const { return true; } + virtual ssize_t FlattenedSize() const { return 0; } + virtual status_t Flatten(BDataIO& stream) const = 0; + virtual ssize_t CountItems() const { return 0; } + virtual void RemoveItem(ssize_t index) = 0; + virtual void PrintToStream(const char* name) const; + virtual const void* DataAt(int32 index, ssize_t* size) const = 0; + + protected: + virtual void PrintDataItem(int32 index) const = 0; + + private: + type_code fType; + std::string fName; +}; + +//------------------------------------------------------------------------------ +template +struct BMessageFieldStoragePolicy +{ + class Store + { + public: + // Compiler-generated versions should be just fine + #if 0 + Store(); + Store(const Store& rhs); + ~Store(); + Store& operator=(const Store& rhs); + #endif + inline size_t Size() const { return fData.size(); } + inline T& operator[](uint index) { return fData[index]; } + inline const T& operator[](uint index) const { return fData[index]; } + inline void Add(const T& data) { fData.push_back(data); } + inline void Remove(uint index) { fData.erase(fData.begin() + index); } + + private: + std::vector fData; + }; +}; +//------------------------------------------------------------------------------ +template +struct BMessageFieldSizePolicy +{ + typedef typename BMessageFieldStoragePolicy::Store Store; + + inline static size_t Size(const T&) { return sizeof (T); } + inline static size_t Size(const Store& data) + { + return sizeof (T) * data.Size(); + } + inline static bool Fixed() { return true; } +}; +//------------------------------------------------------------------------------ +template +struct BMessageFieldPrintPolicy +{ + static void PrintData(const T& data) {;} +}; +//------------------------------------------------------------------------------ +template +struct BMessageFieldFlattenPolicy +{ + typedef BMessageFieldSizePolicy SizePolicy; + + inline static status_t Flatten(BDataIO& stream, const T& data) + { + return stream.Write((const void*)&data, SizePolicy::Size(data)); + } +}; +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +template +< + class T1, + class StoragePolicy = BMessageFieldStoragePolicy, + class SizePolicy = BMessageFieldSizePolicy, + class PrintPolicy = BMessageFieldPrintPolicy, + class FlattenPolicy = BMessageFieldFlattenPolicy +> +class BMessageFieldImpl : public BMessageField +{ + public: + typedef typename StoragePolicy::Store StorageType; + + BMessageFieldImpl(const std::string& name, type_code type) + : BMessageField(name, type), + fMaxSize(0), + fFlags(MSG_FLAG_ALL) + {;} + + virtual bool FixedSize() const + { return fFlags & MSG_FLAG_FIXED_SIZE; } + virtual ssize_t FlattenedSize() const; + virtual status_t Flatten(BDataIO& stream) const; + virtual ssize_t CountItems() const { return fData.Size(); } + virtual void AddItem(const T1& data); + virtual void RemoveItem(ssize_t index) + { fData.Remove(index); }; + + virtual const void* DataAt(int32 index, ssize_t* size) const; + StorageType& Data() { return fData; } + + protected: + virtual void PrintDataItem(int32 index) const; + + private: + StorageType fData; + size_t fMaxSize; + uchar fFlags; +}; +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +template +< + class T1, + class StoragePolicy, + class SizePolicy, + class PrintPolicy, + class FlattenPolicy +> +ssize_t +BMessageFieldImpl:: +FlattenedSize() const +{ + ssize_t size = 0; + + // Mandatory stuff + size += 1; // field flags byte + size += sizeof (type_code); // field type bytes + if (!(fFlags & MSG_FLAG_SINGLE_ITEM)) // item count byte + ++size; + ++size; // data length byte + ++size; // name length byte + size += Name().length(); // name length + + size += SizePolicy::Size(fData); // data length and item size bytes + + return size; +} +//------------------------------------------------------------------------------ +template +< + class T1, + class StoragePolicy, + class SizePolicy, + class PrintPolicy, + class FlattenPolicy +> +status_t +BMessageFieldImpl:: +Flatten(BDataIO& stream) const +{ + status_t err = B_OK; + type_code type = Type(); + uint8 count = fData.Size(); + uint8 size = SizePolicy::Size(fData); + uint8 nameLen = Name().length(); + + err = stream.Write(&fFlags, 1); + + // Field type_code + if (err >= 0) + err = stream.Write(&type, sizeof (type_code)); + + // Item count, if more than one + if (err >= 0 && !(fFlags & MSG_FLAG_SINGLE_ITEM)) + err = stream.Write(&count, 1); + + // Data length + if (err >= 0) + err = stream.Write(&size, 1); + + // Name length + if (err >= 0) + err = stream.Write(&nameLen, 1); + + // Name + if (err >= 0) + err = stream.Write(Name().c_str(), Name().length()); + + // Actual data items + for (uint32 i = 0; i < fData.Size() && err >= 0; ++i) + { + err = FlattenPolicy::Flatten(stream, fData[i]); + } + + if (err >= 0) + err = B_OK; + return err; +} +//------------------------------------------------------------------------------ +template +< + class T1, + class StoragePolicy, + class SizePolicy, + class PrintPolicy, + class FlattenPolicy +> +void +BMessageFieldImpl:: +AddItem(const T1& data) +{ + fData.Add(data); + + if (fMaxSize) + { + if ((fFlags & MSG_FLAG_FIXED_SIZE) && + (!SizePolicy::Fixed() || + fMaxSize != SizePolicy::Size(data))) + { + fMaxSize = max(SizePolicy::Size(data), fMaxSize); + fFlags &= ~MSG_FLAG_FIXED_SIZE; + } + } + else + { + if (!SizePolicy::Fixed()) + { + fFlags &= ~MSG_FLAG_FIXED_SIZE; + } + fMaxSize = SizePolicy::Size(data); + } + + if (fData.Size() > 256 || fMaxSize > 256) + fFlags &= ~MSG_FLAG_MINI_DATA; + + if (fData.Size() > 1) + fFlags &= ~MSG_FLAG_SINGLE_ITEM; +} +//------------------------------------------------------------------------------ +template +< + class T1, + class StoragePolicy, + class SizePolicy, + class PrintPolicy, + class FlattenPolicy +> +const void* +BMessageFieldImpl:: +DataAt(int32 index, ssize_t* size) const +{ + if (index > CountItems()) + return NULL; + + *size = SizePolicy::Size(fData[index]); + const T1& ref = fData[index]; + const T1* data = &ref; + + return (const void*)data; +} +//------------------------------------------------------------------------------ +template +< + class T1, + class StoragePolicy, + class SizePolicy, + class PrintPolicy, + class FlattenPolicy +> +void +BMessageFieldImpl:: +PrintDataItem(int32 index) const +{ + if (index && FixedSize()) + { + std::printf(" "); + } + else + { + std::printf("size=%2ld, ", SizePolicy::Size(fData[index])); + } + std::printf("data[%ld]: ", index); + PrintPolicy::PrintData(fData[index]); +} +//------------------------------------------------------------------------------ + + +// Print policy specializations ------------------------------------------------ +template<> struct BMessageFieldPrintPolicy +{ + static void PrintData(const bool& b) { std::printf("%d", int(b)); } +}; +template<> struct BMessageFieldPrintPolicy +{ + static void PrintData(const int8& i) + { std::printf("0x%X (%d, '%c')", int(i), int(i), char(i)); } +}; +template<> struct BMessageFieldPrintPolicy +{ + static void PrintData(const int16& i) + { std::printf("0x%X (%d, '%c')", i, i, char(i)); } +}; +template<> struct BMessageFieldPrintPolicy +{ + static void PrintData(const int32& i) + { std::printf("0x%lX (%ld, '%c')", i, i, char(i)); } +}; +template<> struct BMessageFieldPrintPolicy +{ + static void PrintData(const int64& i) + { std::printf("0x%LX (%Ld, '%c')", i, i, char(i)); } +}; +template<> struct BMessageFieldPrintPolicy +{ + static void PrintData(const float& f) { std::printf("%.4f", f); } +}; +template<> struct BMessageFieldPrintPolicy +{ + static void PrintData(const double& d) { std::printf("%.8lf", d); } +}; +template<> struct BMessageFieldPrintPolicy +{ + static void PrintData(const BString& s) { std::printf("\"%s\"", s.String()); } +}; +template<> struct BMessageFieldPrintPolicy +{ + static void PrintData(const BPoint& p) { std::printf("BPoint(x:%.1f, y:%.1f)", p.x, p.y); } +}; +template<> struct BMessageFieldPrintPolicy +{ + static void PrintData(const BRect& r) + { std::printf("BRect(l:%.1f, t:%.1f, r:%.1f, b:%.1f)", r.left, r.top, r.right, r.bottom); } +}; +template<> struct BMessageFieldPrintPolicy +{ + static void PrintData(const entry_ref& ref) + { + std::printf("device=%ld, directory=%Ld, name=\"%s\", path=\"%s\"", + ref.device, ref.directory, ref.name, BPath(&ref).Path()); + } +}; +// Storage policy specializations ---------------------------------------------- +template<> +struct BMessageFieldStoragePolicy +{ + class Store + { + private: + struct Boolean + { + Boolean() : data(bool()) {;} + Boolean(bool b) : data(b) {;} + bool data; + }; + + public: + inline size_t Size() const + { return fData.size(); } + inline bool& operator[](uint index) + { return fData[index].data; } + inline const bool& operator[](uint index) const + { return fData[index].data; } + void Add(const bool& data) + { + fData.push_back(data); + } + void Remove(uint index) + { + fData.erase(fData.begin() + index); + } + + private: + std::vector fData; + }; +}; +// Size policy specializations ------------------------------------------------- +template<> struct BMessageFieldSizePolicy +{ + typedef BMessageFieldStoragePolicy::Store Store; + + inline static size_t Size(const BString& s) { return s.Length() + 1; } + inline static size_t Size(const Store& data) + { + size_t size = 0; + size_t temp; + for (uint32 i = 0; i < data.Size(); ++i) + { + temp = Size(data[i]) + 4; // Four extra bytes for size info + // Calculate padding + temp += 8 - (temp % 8); + size += temp; + } + + return size; + } + inline static bool Fixed() { return false; } +}; +//------------------------------------------------------------------------------ +template<> struct BMessageFieldSizePolicy +{ + typedef BMessageFieldStoragePolicy::Store Store; + + inline static size_t Size(const BDataBuffer& db) + { return db.BufferSize(); } + inline static size_t Size(const Store& data) + { + size_t size = 0; + size_t temp; + for (uint32 i = 0; i < data.Size(); ++i) + { + temp = Size(data[i]) + 4; // Four extra bytes for size info + // Calculate padding + temp += 8 - (temp % 8); + size += temp; + } + + return size; + } + inline static bool Fixed() { return false; } +}; +//------------------------------------------------------------------------------ +template<> struct BMessageFieldSizePolicy +{ + typedef BMessageFieldStoragePolicy::Store Store; + + inline static size_t Size(const BMessage* msg) + { return msg->FlattenedSize(); } + inline static size_t Size(const Store& data) + { + size_t size = 0; + size_t temp; + for (uint32 i = 0; i < data.Size(); ++i) + { + temp = Size(data[i]) + 4; // Four extra bytes for size info + // Calculate padding + temp += 8 - (temp % 8); + size += temp; + } + + return size; + } + inline static bool Fixed() { return false; } +}; +// Flatten policy specializations ---------------------------------------------- +template<> +struct BMessageFieldFlattenPolicy +{ + typedef BMessageFieldSizePolicy SizePolicy; + + static status_t Flatten(BDataIO& stream, const BString& data) + { + size_t size = SizePolicy::Size(data); + status_t err = stream.Write(&size, 4); + + if (err >= 0) + err = stream.Write((const void*)data.String(), size); + + if (err >= 0) + { + // Pad data to 8-byte boundary + size += 4; // Account for the stored size of size + size %= 8; + if (size) + { + err = stream.Write(&BMessageField::sNullData[size], 8 - (size)); + } + } + + if (err >= 0) + err = B_OK; + return err; + } +}; +//------------------------------------------------------------------------------ +template<> +struct BMessageFieldFlattenPolicy +{ + typedef BMessageFieldSizePolicy SizePolicy; + + static status_t Flatten(BDataIO& stream, const BMessage* data) + { + size_t size = SizePolicy::Size(data); + status_t err = stream.Write(&size, 4); + + if (err >= 0) + err = data->Flatten(&stream); + + if (err >= 0) + { + // Pad data to 8-byte boundary + size += 4; // Account for the stored size of size + size %= 8; + if (size) + { + err = stream.Write(&BMessageField::sNullData[size], 8 - (size)); + } + } + + if (err >= 0) + err = B_OK; + return err; + } +}; +//------------------------------------------------------------------------------ + +} // namespace BPrivate + +#endif // MESSAGEFIELD_H + +/* + * $Log $ + * + * $Id $ + * + */ + diff --git a/headers/private/app/MessageUtils.h b/headers/private/app/MessageUtils.h new file mode 100644 index 0000000000..0d747c3a43 --- /dev/null +++ b/headers/private/app/MessageUtils.h @@ -0,0 +1,197 @@ +//------------------------------------------------------------------------------ +// MessageUtils.h +// +//------------------------------------------------------------------------------ + +#ifndef MESSAGEUTILS_H +#define MESSAGEUTILS_H + +// Standard Includes ----------------------------------------------------------- + +// System Includes ------------------------------------------------------------- +#include +#include +#include +#include +#include +#include + +// Project Includes ------------------------------------------------------------ + +// Local Includes -------------------------------------------------------------- + +// Local Defines --------------------------------------------------------------- + +// Globals --------------------------------------------------------------------- + +uint32 _checksum_(const uchar *buf, int32 size); + +//------------------------------------------------------------------------------ +// _set_message_target_ +/*! \brief Sets the target of a message. + + \param message The message. + \param token The target handler token. + \param preferred Indicates whether to use the looper's preferred handler. +*/ +inline +void +_set_message_target_(BMessage *message, int32 token, bool preferred) +{ + message->fTarget = token; + message->fPreferred = preferred; +} +//------------------------------------------------------------------------------ +// _set_message_reply_ +/*! \brief Sets a message's reply target. + + \param message The message. + \param messenger The reply messenger. +*/ +inline +void +_set_message_reply_(BMessage *message, BMessenger messenger) +{ + message->fReplyTo.port = messenger.fPort; + message->fReplyTo.target = messenger.fHandlerToken; + message->fReplyTo.team = messenger.fTeam; + message->fReplyTo.preferred = messenger.fPreferredTarget; +} +//------------------------------------------------------------------------------ +inline int32 _get_message_target_(BMessage *msg) +{ + return msg->fTarget; +} +//------------------------------------------------------------------------------ +inline bool _use_preferred_target_(BMessage *msg) +{ + return msg->fPreferred; +} +//------------------------------------------------------------------------------ +inline status_t normalize_err(status_t err) +{ + return err >= 0 ? B_OK : err; +} +//------------------------------------------------------------------------------ +template +inline void byte_swap(T& /*data*/) +{ + // Specialize for data types which actually swap +} +//------------------------------------------------------------------------------ +inline void write_helper(BDataIO* stream, const void* data, size_t size, + status_t& err) +{ + err = normalize_err(stream->Write(data, size)); +} +//------------------------------------------------------------------------------ +// Will the template madness never cease?? +template +inline status_t write_helper(BDataIO* stream, T& data, status_t& err) +{ + return normalize_err(stream->Write((const void*)data, sizeof (T))); +} +//------------------------------------------------------------------------------ +class TReadHelper +{ + public: + TReadHelper(BDataIO* stream) + : fStream(stream), err(B_OK), fSwap(false) + { + ; + } + + TReadHelper(BDataIO* stream, bool swap) + : fStream(stream), err(B_OK), fSwap(swap) + { + ; + } + + template inline void operator()(T& data) + { + err = normalize_err(fStream->Read((void*)&data, sizeof (T))); + if (err) + throw err; + + if (IsSwapping()) + { + byte_swap(data); + } + } + + template inline void operator()(T data, size_t len) + { + err = normalize_err(fStream->Read((void*)data, len)); + if (err) + throw err; + } + + status_t Status() { return err; } + void SetSwap(bool yesNo) { fSwap = yesNo; } + bool IsSwapping() { return fSwap; } + + private: + BDataIO* fStream; + status_t err; + bool fSwap; +}; +//------------------------------------------------------------------------------ +class TChecksumHelper +{ + public: + TChecksumHelper(uchar* buffer) : fBuffer(buffer), fBufPtr(buffer) {;} + + template inline void Cache(T& data) + { + *((T*)fBufPtr) = data; + fBufPtr += sizeof (T); + } + + int32 CheckSum(); + + private: + uchar* fBuffer; + uchar* fBufPtr; +}; +//------------------------------------------------------------------------------ +template inline status_t read_helper(BDataIO* stream, T& data) +{ + return normalize_err(stream->Read((void*)&data, sizeof (T))); +} +//------------------------------------------------------------------------------ +template<> inline void byte_swap(double& data) +{ + data = __swap_double(data); +} +template<> inline void byte_swap(float& data) +{ + data = __swap_float(data); +} +template<> inline void byte_swap(int64& data) +{ + data = __swap_int64(data); +} +template<> inline void byte_swap(int32& data) +{ + data = __swap_int32(data); +} +template<> inline void byte_swap(int16& data) +{ + data = __swap_int16(data); +} +template<> inline void byte_swap(entry_ref& data) +{ + byte_swap(data.device); + byte_swap(data.directory); +} +//------------------------------------------------------------------------------ + +#endif // MESSAGEUTILS_H + +/* + * $Log $ + * + * $Id $ + * + */ + diff --git a/headers/private/shared/DataBuffer.h b/headers/private/shared/DataBuffer.h new file mode 100644 index 0000000000..4d8abf3844 --- /dev/null +++ b/headers/private/shared/DataBuffer.h @@ -0,0 +1,76 @@ +//------------------------------------------------------------------------------ +// DataBuffer.h +// +//------------------------------------------------------------------------------ + +#ifndef DATABUFFER_H +#define DATABUFFER_H + +// Standard Includes ----------------------------------------------------------- + +// System Includes ------------------------------------------------------------- +#include + +// Project Includes ------------------------------------------------------------ + +// Local Includes -------------------------------------------------------------- + +// Local Defines --------------------------------------------------------------- + +// Globals --------------------------------------------------------------------- + +namespace BPrivate { + +class BDataBuffer +{ + public: + BDataBuffer(size_t len); + BDataBuffer(void* data, size_t len); + BDataBuffer(const BDataBuffer& rhs); + ~BDataBuffer(); + + BDataBuffer& operator=(const BDataBuffer& rhs); + + size_t BufferSize() const; + const void* Buffer(); + + private: + class BDataReference + { + public: + void Acquire(BDataReference*& ref); + void Release(BDataReference*& ref); + + char* Data() { return data; } + size_t Size() const { return size; } + int32 Count() { return count; } + + static void Create(void* data, size_t len, BDataReference*& ref); + static void Create(size_t len, BDataReference*& ref); + + private: + BDataReference(void* data, size_t len); + BDataReference(size_t len); + ~BDataReference(); + + char* data; + size_t size; + int32 count; + }; + + BDataBuffer(); // No default construction allowed! + + BDataReference* fDataRef; +}; + +} // namespace BPrivate + +#endif // DATABUFFER_H + +/* + * $Log $ + * + * $Id $ + * + */ + diff --git a/src/kits/app/MessageBody.cpp b/src/kits/app/MessageBody.cpp new file mode 100644 index 0000000000..6836a53479 --- /dev/null +++ b/src/kits/app/MessageBody.cpp @@ -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 (erik@cgsoftware.com) +// Description: BMessageBody handles data storage and retrieval for +// BMessage. +//------------------------------------------------------------------------------ + +// Standard Includes ----------------------------------------------------------- +#include + +// System Includes ------------------------------------------------------------- +#include + +// Project Includes ------------------------------------------------------------ +#include + +// 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(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 $ + * + */ + diff --git a/src/kits/app/MessageField.cpp b/src/kits/app/MessageField.cpp new file mode 100644 index 0000000000..e7eead9b88 --- /dev/null +++ b/src/kits/app/MessageField.cpp @@ -0,0 +1,50 @@ +//------------------------------------------------------------------------------ +// MessageField.cpp +// +//------------------------------------------------------------------------------ + +// Standard Includes ----------------------------------------------------------- + +// System Includes ------------------------------------------------------------- +#include + +// 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 $ + * + */ + diff --git a/src/kits/app/MessageUtils.cpp b/src/kits/app/MessageUtils.cpp new file mode 100644 index 0000000000..9c64687fd3 --- /dev/null +++ b/src/kits/app/MessageUtils.cpp @@ -0,0 +1,57 @@ +//------------------------------------------------------------------------------ +// MessageUtils.cpp +// +//------------------------------------------------------------------------------ + +// Standard Includes ----------------------------------------------------------- + +// System Includes ------------------------------------------------------------- + +// Project Includes ------------------------------------------------------------ +#include + +// 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 $ + * + */ + diff --git a/src/kits/app/app.src b/src/kits/app/app.src index 8a71cf35a2..39b6d918a2 100644 --- a/src/kits/app/app.src +++ b/src/kits/app/app.src @@ -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 diff --git a/src/kits/support/DataBuffer.cpp b/src/kits/support/DataBuffer.cpp new file mode 100644 index 0000000000..c2dc7c84b1 --- /dev/null +++ b/src/kits/support/DataBuffer.cpp @@ -0,0 +1,129 @@ +//------------------------------------------------------------------------------ +// DataBuffer.cpp +// +//------------------------------------------------------------------------------ + +// Standard Includes ----------------------------------------------------------- +#include + +// System Includes ------------------------------------------------------------- + +// Project Includes ------------------------------------------------------------ +#include + +// 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 $ + * + */ + diff --git a/src/kits/support/support.src b/src/kits/support/support.src index 7f5027beb2..8100f669a4 100644 --- a/src/kits/support/support.src +++ b/src/kits/support/support.src @@ -9,4 +9,5 @@ SUPPORT_KIT_SOURCE = StopWatch.cpp String.cpp string_helper.cpp +# StreamIO.cpp ;