Removing Message2 and Message3. They did not proof to be good enough so they don't need to take up space either.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15062 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,454 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) 2001-2005, Haiku
|
||||
//
|
||||
// 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: Message.h
|
||||
// Author(s): Erik Jaesler ([email protected])
|
||||
// DarkWyrm <[email protected]>
|
||||
// Description: BMessage class creates objects that store data and that
|
||||
// can be processed in a message loop. BMessage objects
|
||||
// are also used as data containers by the archiving and
|
||||
// the scripting mechanisms.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifndef _MESSAGE_H
|
||||
#define _MESSAGE_H
|
||||
|
||||
#include <BeBuild.h>
|
||||
#include <OS.h>
|
||||
#include <Rect.h>
|
||||
#include <DataIO.h>
|
||||
#include <Flattenable.h>
|
||||
|
||||
#include <AppDefs.h> /* For convenience */
|
||||
#include <TypeConstants.h> /* For convenience */
|
||||
|
||||
class BBlockCache;
|
||||
class BMessenger;
|
||||
class BHandler;
|
||||
class BString;
|
||||
|
||||
// Private or reserved ---------------------------------------------------------
|
||||
extern "C" void _msg_cache_cleanup_();
|
||||
extern "C" int _init_message_();
|
||||
extern "C" int _delete_message_();
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Name lengths and Scripting specifiers ---------------------------------------
|
||||
#define B_FIELD_NAME_LENGTH 255
|
||||
#define B_PROPERTY_NAME_LENGTH 255
|
||||
|
||||
enum
|
||||
{
|
||||
B_NO_SPECIFIER = 0,
|
||||
B_DIRECT_SPECIFIER = 1,
|
||||
B_INDEX_SPECIFIER,
|
||||
B_REVERSE_INDEX_SPECIFIER,
|
||||
B_RANGE_SPECIFIER,
|
||||
B_REVERSE_RANGE_SPECIFIER,
|
||||
B_NAME_SPECIFIER,
|
||||
B_ID_SPECIFIER,
|
||||
|
||||
B_SPECIFIERS_END = 128
|
||||
// app-defined specifiers start at B_SPECIFIERS_END+1
|
||||
};
|
||||
|
||||
namespace BPrivate {
|
||||
class BMessageBody;
|
||||
}
|
||||
|
||||
// BMessage class --------------------------------------------------------------
|
||||
class BMessage
|
||||
{
|
||||
public:
|
||||
uint32 what;
|
||||
|
||||
BMessage();
|
||||
BMessage(uint32 what);
|
||||
BMessage(const BMessage &a_message);
|
||||
virtual ~BMessage();
|
||||
|
||||
BMessage &operator=(const BMessage &msg);
|
||||
|
||||
// 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);
|
||||
|
||||
// Delivery info
|
||||
bool WasDelivered() const;
|
||||
bool IsSourceWaiting() const;
|
||||
bool IsSourceRemote() const;
|
||||
BMessenger ReturnAddress() const;
|
||||
const BMessage *Previous() const;
|
||||
bool WasDropped() const;
|
||||
BPoint DropPoint(BPoint *offset = NULL) const;
|
||||
|
||||
// Replying
|
||||
status_t SendReply(uint32 command, BHandler *reply_to = NULL);
|
||||
status_t SendReply(BMessage *the_reply, BHandler *reply_to = NULL,
|
||||
bigtime_t timeout = B_INFINITE_TIMEOUT);
|
||||
status_t SendReply(BMessage *the_reply, BMessenger reply_to,
|
||||
bigtime_t timeout = B_INFINITE_TIMEOUT);
|
||||
|
||||
status_t SendReply(uint32 command, BMessage *reply_to_reply);
|
||||
status_t SendReply(BMessage *the_reply, BMessage *reply_to_reply,
|
||||
bigtime_t send_timeout = B_INFINITE_TIMEOUT,
|
||||
bigtime_t reply_timeout = B_INFINITE_TIMEOUT);
|
||||
|
||||
// Flattening data
|
||||
ssize_t FlattenedSize() const;
|
||||
status_t Flatten(char *buffer, ssize_t size) const;
|
||||
status_t Flatten(BDataIO *stream, ssize_t *size = NULL) const;
|
||||
status_t Unflatten(const char *flat_buffer);
|
||||
status_t Unflatten(BDataIO *stream);
|
||||
|
||||
|
||||
// Specifiers (scripting)
|
||||
status_t AddSpecifier(const char *property);
|
||||
status_t AddSpecifier(const char *property, int32 index);
|
||||
status_t AddSpecifier(const char *property, int32 index, int32 range);
|
||||
status_t AddSpecifier(const char *property, const char *name);
|
||||
status_t AddSpecifier(const BMessage *specifier);
|
||||
|
||||
status_t SetCurrentSpecifier(int32 index);
|
||||
status_t GetCurrentSpecifier(int32 *index, BMessage *specifier = NULL,
|
||||
int32 *form = NULL, const char **property = NULL) const;
|
||||
bool HasSpecifiers() const;
|
||||
status_t PopSpecifier();
|
||||
|
||||
// Adding data
|
||||
status_t AddRect(const char *name, BRect a_rect);
|
||||
status_t AddPoint(const char *name, BPoint a_point);
|
||||
status_t AddString(const char *name, const char *a_string);
|
||||
status_t AddString(const char *name, const BString& a_string);
|
||||
status_t AddInt8(const char *name, int8 val);
|
||||
status_t AddInt16(const char *name, int16 val);
|
||||
status_t AddInt32(const char *name, int32 val);
|
||||
status_t AddInt64(const char *name, int64 val);
|
||||
status_t AddBool(const char *name, bool a_boolean);
|
||||
status_t AddFloat(const char *name, float a_float);
|
||||
status_t AddDouble(const char *name, double a_double);
|
||||
status_t AddPointer(const char *name, const void *ptr);
|
||||
status_t AddMessenger(const char *name, BMessenger messenger);
|
||||
status_t AddRef(const char *name, const entry_ref *ref);
|
||||
status_t AddMessage(const char *name, const BMessage *msg);
|
||||
status_t AddFlat(const char *name, BFlattenable *obj, int32 count = 1);
|
||||
status_t AddData(const char *name, type_code type, const void *data,
|
||||
ssize_t numBytes, bool is_fixed_size = true, int32 count = 1);
|
||||
|
||||
// Removing data
|
||||
status_t RemoveData(const char *name, int32 index = 0);
|
||||
status_t RemoveName(const char *name);
|
||||
status_t MakeEmpty();
|
||||
|
||||
// Finding data
|
||||
status_t FindRect(const char *name, BRect *rect) const;
|
||||
status_t FindRect(const char *name, int32 index, BRect *rect) const;
|
||||
status_t FindPoint(const char *name, BPoint *pt) const;
|
||||
status_t FindPoint(const char *name, int32 index, BPoint *pt) const;
|
||||
status_t FindString(const char *name, const char **str) const;
|
||||
status_t FindString(const char *name, int32 index, const char **str) const;
|
||||
status_t FindString(const char *name, BString *str) const;
|
||||
status_t FindString(const char *name, int32 index, BString *str) const;
|
||||
status_t FindInt8(const char *name, int8 *value) const;
|
||||
status_t FindInt8(const char *name, int32 index, int8 *val) const;
|
||||
status_t FindInt16(const char *name, int16 *value) const;
|
||||
status_t FindInt16(const char *name, int32 index, int16 *val) const;
|
||||
status_t FindInt32(const char *name, int32 *value) const;
|
||||
status_t FindInt32(const char *name, int32 index, int32 *val) const;
|
||||
status_t FindInt64(const char *name, int64 *value) const;
|
||||
status_t FindInt64(const char *name, int32 index, int64 *val) const;
|
||||
status_t FindBool(const char *name, bool *value) const;
|
||||
status_t FindBool(const char *name, int32 index, bool *value) const;
|
||||
status_t FindFloat(const char *name, float *f) const;
|
||||
status_t FindFloat(const char *name, int32 index, float *f) const;
|
||||
status_t FindDouble(const char *name, double *d) const;
|
||||
status_t FindDouble(const char *name, int32 index, double *d) const;
|
||||
status_t FindPointer(const char *name, void **ptr) const;
|
||||
status_t FindPointer(const char *name, int32 index, void **ptr) const;
|
||||
status_t FindMessenger(const char *name, BMessenger *m) const;
|
||||
status_t FindMessenger(const char *name, int32 index, BMessenger *m) const;
|
||||
status_t FindRef(const char *name, entry_ref *ref) const;
|
||||
status_t FindRef(const char *name, int32 index, entry_ref *ref) const;
|
||||
status_t FindMessage(const char *name, BMessage *msg) const;
|
||||
status_t FindMessage(const char *name, int32 index, BMessage *msg) const;
|
||||
status_t FindFlat(const char *name, BFlattenable *obj) const;
|
||||
status_t FindFlat(const char *name, int32 index, BFlattenable *obj) const;
|
||||
status_t FindData(const char *name, type_code type,
|
||||
const void **data, ssize_t *numBytes) const;
|
||||
status_t FindData(const char *name, type_code type, int32 index,
|
||||
const void **data, ssize_t *numBytes) const;
|
||||
|
||||
// Replacing data
|
||||
status_t ReplaceRect(const char *name, BRect a_rect);
|
||||
status_t ReplaceRect(const char *name, int32 index, BRect a_rect);
|
||||
status_t ReplacePoint(const char *name, BPoint a_point);
|
||||
status_t ReplacePoint(const char *name, int32 index, BPoint a_point);
|
||||
status_t ReplaceString(const char *name, const char *string);
|
||||
status_t ReplaceString(const char *name, int32 index, const char *string);
|
||||
status_t ReplaceString(const char *name, const BString& string);
|
||||
status_t ReplaceString(const char *name, int32 index, const BString& string);
|
||||
status_t ReplaceInt8(const char *name, int8 val);
|
||||
status_t ReplaceInt8(const char *name, int32 index, int8 val);
|
||||
status_t ReplaceInt16(const char *name, int16 val);
|
||||
status_t ReplaceInt16(const char *name, int32 index, int16 val);
|
||||
status_t ReplaceInt32(const char *name, int32 val);
|
||||
status_t ReplaceInt32(const char *name, int32 index, int32 val);
|
||||
status_t ReplaceInt64(const char *name, int64 val);
|
||||
status_t ReplaceInt64(const char *name, int32 index, int64 val);
|
||||
status_t ReplaceBool(const char *name, bool a_bool);
|
||||
status_t ReplaceBool(const char *name, int32 index, bool a_bool);
|
||||
status_t ReplaceFloat(const char *name, float a_float);
|
||||
status_t ReplaceFloat(const char *name, int32 index, float a_float);
|
||||
status_t ReplaceDouble(const char *name, double a_double);
|
||||
status_t ReplaceDouble(const char *name, int32 index, double a_double);
|
||||
status_t ReplacePointer(const char *name, const void *ptr);
|
||||
status_t ReplacePointer(const char *name,int32 index,const void *ptr);
|
||||
status_t ReplaceMessenger(const char *name, BMessenger messenger);
|
||||
status_t ReplaceMessenger(const char *name, int32 index, BMessenger msngr);
|
||||
status_t ReplaceRef( const char *name,const entry_ref *ref);
|
||||
status_t ReplaceRef( const char *name, int32 index, const entry_ref *ref);
|
||||
status_t ReplaceMessage(const char *name, const BMessage *msg);
|
||||
status_t ReplaceMessage(const char *name, int32 index, const BMessage *msg);
|
||||
status_t ReplaceFlat(const char *name, BFlattenable *obj);
|
||||
status_t ReplaceFlat(const char *name, int32 index, BFlattenable *obj);
|
||||
status_t ReplaceData(const char *name, type_code type,
|
||||
const void *data, ssize_t data_size);
|
||||
status_t ReplaceData(const char *name, type_code type, int32 index,
|
||||
const void *data, ssize_t data_size);
|
||||
|
||||
void *operator new(size_t size);
|
||||
void *operator new(size_t, void* p);
|
||||
void operator delete(void *ptr, size_t size);
|
||||
|
||||
// Private, reserved, or obsolete ----------------------------------------------
|
||||
bool HasRect(const char *, int32 n = 0) const;
|
||||
bool HasPoint(const char *, int32 n = 0) const;
|
||||
bool HasString(const char *, int32 n = 0) const;
|
||||
bool HasInt8(const char *, int32 n = 0) const;
|
||||
bool HasInt16(const char *, int32 n = 0) const;
|
||||
bool HasInt32(const char *, int32 n = 0) const;
|
||||
bool HasInt64(const char *, int32 n = 0) const;
|
||||
bool HasBool(const char *, int32 n = 0) const;
|
||||
bool HasFloat(const char *, int32 n = 0) const;
|
||||
bool HasDouble(const char *, int32 n = 0) const;
|
||||
bool HasPointer(const char *, int32 n = 0) const;
|
||||
bool HasMessenger(const char *, int32 n = 0) const;
|
||||
bool HasRef(const char *, int32 n = 0) const;
|
||||
bool HasMessage(const char *, int32 n = 0) const;
|
||||
bool HasFlat(const char *, const BFlattenable *) const;
|
||||
bool HasFlat(const char *,int32 ,const BFlattenable *) const;
|
||||
bool HasData(const char *, type_code , int32 n = 0) const;
|
||||
BRect FindRect(const char *, int32 n = 0) const;
|
||||
BPoint FindPoint(const char *, int32 n = 0) const;
|
||||
const char *FindString(const char *, int32 n = 0) const;
|
||||
int8 FindInt8(const char *, int32 n = 0) const;
|
||||
int16 FindInt16(const char *, int32 n = 0) const;
|
||||
int32 FindInt32(const char *, int32 n = 0) const;
|
||||
int64 FindInt64(const char *, int32 n = 0) const;
|
||||
bool FindBool(const char *, int32 n = 0) const;
|
||||
float FindFloat(const char *, int32 n = 0) const;
|
||||
double FindDouble(const char *, int32 n = 0) const;
|
||||
|
||||
class Private;
|
||||
|
||||
private:
|
||||
class Header;
|
||||
|
||||
friend class BMessageQueue;
|
||||
friend class BMessenger;
|
||||
friend class BApplication;
|
||||
friend class Header;
|
||||
friend class Private;
|
||||
|
||||
friend inline void _set_message_target_(BMessage *, int32, bool);
|
||||
friend inline void _set_message_reply_(BMessage *, BMessenger);
|
||||
friend inline int32 _get_message_target_(BMessage *);
|
||||
friend inline bool _use_preferred_target_(BMessage *);
|
||||
|
||||
// deprecated
|
||||
BMessage(BMessage *a_message);
|
||||
|
||||
virtual void _ReservedMessage1();
|
||||
virtual void _ReservedMessage2();
|
||||
virtual void _ReservedMessage3();
|
||||
|
||||
void init_data();
|
||||
status_t flatten_target_info(BDataIO *stream,
|
||||
ssize_t size,
|
||||
uchar flags) const;
|
||||
status_t real_flatten(char *result, ssize_t size) const;
|
||||
status_t real_flatten(BDataIO *stream, ssize_t *size) const;
|
||||
char *stack_flatten(char *stack_ptr,
|
||||
ssize_t stack_size,
|
||||
bool incl_reply,
|
||||
ssize_t *size = NULL) const;
|
||||
|
||||
status_t _UnflattenKMessage(const char *buffer);
|
||||
|
||||
ssize_t calc_size(uchar flags) const;
|
||||
ssize_t calc_hdr_size(uchar flags) const;
|
||||
status_t nfind_data( const char *name,
|
||||
type_code type,
|
||||
int32 index,
|
||||
const void **data,
|
||||
ssize_t *data_size) const;
|
||||
status_t copy_data( const char *name,
|
||||
type_code type,
|
||||
int32 index,
|
||||
void *data,
|
||||
ssize_t data_size) const;
|
||||
|
||||
status_t _send_(port_id port,
|
||||
int32 token,
|
||||
bool preferred,
|
||||
bigtime_t timeout,
|
||||
bool reply_required,
|
||||
BMessenger &reply_to) const;
|
||||
status_t send_message(port_id port,
|
||||
team_id port_owner,
|
||||
int32 token,
|
||||
bool preferred,
|
||||
BMessage *reply,
|
||||
bigtime_t send_timeout,
|
||||
bigtime_t reply_timeout) const;
|
||||
static status_t _SendFlattenedMessage(void *data, int32 size,
|
||||
port_id port, int32 token, bool preferred,
|
||||
bigtime_t timeout);
|
||||
|
||||
static void _StaticInit();
|
||||
static void _StaticCleanup();
|
||||
static void _StaticCacheCleanup();
|
||||
|
||||
enum { sNumReplyPorts = 3 };
|
||||
static port_id sReplyPorts[sNumReplyPorts];
|
||||
static long sReplyPortInUse[sNumReplyPorts];
|
||||
static int32 sGetCachedReplyPort();
|
||||
|
||||
static BBlockCache *sMsgCache;
|
||||
|
||||
struct dyn_array {
|
||||
int32 fLogicalBytes;
|
||||
int32 fPhysicalBytes;
|
||||
int32 fChunkSize;
|
||||
int32 fCount;
|
||||
int32 fEntryHdrSize;
|
||||
};
|
||||
|
||||
struct entry_hdr : public dyn_array {
|
||||
entry_hdr *fNext;
|
||||
uint32 fType;
|
||||
uchar fNameLength;
|
||||
char fName[1];
|
||||
};
|
||||
|
||||
struct var_chunk {
|
||||
int32 fDataSize;
|
||||
char fData[1];
|
||||
};
|
||||
|
||||
entry_hdr *entry_find(const char *name, uint32 type,status_t *result=NULL) const;
|
||||
void entry_remove(entry_hdr *entry);
|
||||
|
||||
void *da_create(int32 header_size, int32 chunk_size,
|
||||
bool fixed, int32 nchunks);
|
||||
status_t da_add_data(dyn_array **da, const void *data, int32 size);
|
||||
void *da_find_data(dyn_array *da, int32 index,
|
||||
int32 *size = NULL) const;
|
||||
status_t da_delete_data(dyn_array **pda, int32 index);
|
||||
status_t da_replace_data(dyn_array **pda, int32 index,
|
||||
const void *data, int32 dsize);
|
||||
int32 da_calc_size(int32 hdr_size, int32 chunksize,
|
||||
bool is_fixed, int32 nchunks) const;
|
||||
void *da_grow(dyn_array **pda, int32 increase);
|
||||
void da_dump(dyn_array *da);
|
||||
|
||||
int32 da_chunk_hdr_size() const
|
||||
{ return sizeof(int32); }
|
||||
int32 da_chunk_size(var_chunk *v) const
|
||||
{ return (v->fDataSize + da_chunk_hdr_size() + 7) & ~7; }
|
||||
var_chunk *da_first_chunk(dyn_array *da) const
|
||||
{ return (var_chunk *) da_start_of_data(da); }
|
||||
var_chunk *da_next_chunk(var_chunk *v) const
|
||||
{ return (var_chunk *) (((char*) v) + da_chunk_size(v)); }
|
||||
var_chunk *da_chunk_ptr(void *data) const
|
||||
{ return (var_chunk*) (((char *) data) - da_chunk_hdr_size()); }
|
||||
|
||||
int32 da_pad_8(int32 val) const
|
||||
{ return (val + 7) & ~7; }
|
||||
int32 da_total_size(dyn_array *da) const
|
||||
{ return (int32)sizeof(dyn_array) + da->fEntryHdrSize +
|
||||
da->fPhysicalBytes; }
|
||||
int32 da_total_logical_size(dyn_array *da) const
|
||||
{ return (int32)sizeof(dyn_array) + da->fEntryHdrSize +
|
||||
da->fLogicalBytes; }
|
||||
char *da_start_of_data(dyn_array *da) const
|
||||
{ return ((char *) da) + (sizeof(dyn_array) +
|
||||
da->fEntryHdrSize); }
|
||||
bool da_is_mini_data(dyn_array *da) const
|
||||
{ return ((da->fLogicalBytes <= (int32) UCHAR_MAX) &&
|
||||
(da->fCount <= (int32) UCHAR_MAX));}
|
||||
void da_swap_var_sized(dyn_array *da);
|
||||
void da_swap_fixed_sized(dyn_array *da);
|
||||
|
||||
BMessage *link;
|
||||
int32 fTarget;
|
||||
BMessage *fOriginal;
|
||||
uint32 fChangeCount;
|
||||
int32 fCurSpecifier;
|
||||
uint32 fPtrOffset;
|
||||
|
||||
// ejaesler: Stealing one for my whacky BMessageBody l33tness
|
||||
uint32 _reserved[2];
|
||||
BPrivate::BMessageBody* fBody;
|
||||
|
||||
BMessage::entry_hdr *fEntries;
|
||||
|
||||
struct reply_to_info {
|
||||
port_id port;
|
||||
int32 target;
|
||||
team_id team;
|
||||
bool preferred;
|
||||
} fReplyTo;
|
||||
|
||||
bool fPreferred;
|
||||
bool fReplyRequired;
|
||||
bool fReplyDone;
|
||||
bool fIsReply;
|
||||
bool fWasDelivered;
|
||||
bool fReadOnly;
|
||||
bool fHasSpecifiers;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#endif // _MESSAGE_H
|
||||
@@ -1,368 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// Copyright (c) 2001-2005, Haiku
|
||||
//
|
||||
// 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: Message.h
|
||||
// Author(s): Erik Jaesler ([email protected])
|
||||
// DarkWyrm <[email protected]>
|
||||
// Description: BMessage class creates objects that store data and that
|
||||
// can be processed in a message loop. BMessage objects
|
||||
// are also used as data containers by the archiving and
|
||||
// the scripting mechanisms.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifndef _MESSAGE_H
|
||||
#define _MESSAGE_H
|
||||
|
||||
#include <BeBuild.h>
|
||||
#include <OS.h>
|
||||
#include <Rect.h>
|
||||
#include <DataIO.h>
|
||||
#include <Flattenable.h>
|
||||
|
||||
#include <AppDefs.h> /* For convenience */
|
||||
#include <TypeConstants.h> /* For convenience */
|
||||
|
||||
class BBlockCache;
|
||||
class BMessenger;
|
||||
class BHandler;
|
||||
class BString;
|
||||
|
||||
// Private or reserved ---------------------------------------------------------
|
||||
extern "C" void _msg_cache_cleanup_();
|
||||
extern "C" int _init_message_();
|
||||
extern "C" int _delete_message_();
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Name lengths and Scripting specifiers ---------------------------------------
|
||||
#define B_FIELD_NAME_LENGTH 255
|
||||
#define B_PROPERTY_NAME_LENGTH 255
|
||||
|
||||
enum
|
||||
{
|
||||
B_NO_SPECIFIER = 0,
|
||||
B_DIRECT_SPECIFIER = 1,
|
||||
B_INDEX_SPECIFIER,
|
||||
B_REVERSE_INDEX_SPECIFIER,
|
||||
B_RANGE_SPECIFIER,
|
||||
B_REVERSE_RANGE_SPECIFIER,
|
||||
B_NAME_SPECIFIER,
|
||||
B_ID_SPECIFIER,
|
||||
|
||||
B_SPECIFIERS_END = 128
|
||||
// app-defined specifiers start at B_SPECIFIERS_END + 1
|
||||
};
|
||||
|
||||
namespace BPrivate {
|
||||
class BMessageBody;
|
||||
}
|
||||
|
||||
// BMessage class --------------------------------------------------------------
|
||||
class BMessage
|
||||
{
|
||||
public:
|
||||
uint32 what;
|
||||
|
||||
BMessage();
|
||||
BMessage(uint32 what);
|
||||
BMessage(const BMessage &a_message);
|
||||
virtual ~BMessage();
|
||||
|
||||
BMessage &operator=(const BMessage &msg);
|
||||
|
||||
// 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);
|
||||
|
||||
// Delivery info
|
||||
bool WasDelivered() const;
|
||||
bool IsSourceWaiting() const;
|
||||
bool IsSourceRemote() const;
|
||||
BMessenger ReturnAddress() const;
|
||||
const BMessage *Previous() const;
|
||||
bool WasDropped() const;
|
||||
BPoint DropPoint(BPoint *offset = NULL) const;
|
||||
|
||||
// Replying
|
||||
status_t SendReply(uint32 command, BHandler *reply_to = NULL);
|
||||
status_t SendReply(BMessage *the_reply, BHandler *reply_to = NULL,
|
||||
bigtime_t timeout = B_INFINITE_TIMEOUT);
|
||||
status_t SendReply(BMessage *the_reply, BMessenger reply_to,
|
||||
bigtime_t timeout = B_INFINITE_TIMEOUT);
|
||||
|
||||
status_t SendReply(uint32 command, BMessage *reply_to_reply);
|
||||
status_t SendReply(BMessage *the_reply, BMessage *reply_to_reply,
|
||||
bigtime_t send_timeout = B_INFINITE_TIMEOUT,
|
||||
bigtime_t reply_timeout = B_INFINITE_TIMEOUT);
|
||||
|
||||
// Flattening data
|
||||
ssize_t FlattenedSize() const;
|
||||
status_t Flatten(char *buffer, ssize_t size) const;
|
||||
status_t Flatten(BDataIO *stream, ssize_t *size = NULL) const;
|
||||
status_t Unflatten(const char *flat_buffer);
|
||||
status_t Unflatten(BDataIO *stream);
|
||||
|
||||
|
||||
// Specifiers (scripting)
|
||||
status_t AddSpecifier(const char *property);
|
||||
status_t AddSpecifier(const char *property, int32 index);
|
||||
status_t AddSpecifier(const char *property, int32 index, int32 range);
|
||||
status_t AddSpecifier(const char *property, const char *name);
|
||||
status_t AddSpecifier(const BMessage *specifier);
|
||||
|
||||
status_t SetCurrentSpecifier(int32 index);
|
||||
status_t GetCurrentSpecifier(int32 *index, BMessage *specifier = NULL,
|
||||
int32 *form = NULL, const char **property = NULL) const;
|
||||
bool HasSpecifiers() const;
|
||||
status_t PopSpecifier();
|
||||
|
||||
// Adding data
|
||||
status_t AddRect(const char *name, BRect a_rect);
|
||||
status_t AddPoint(const char *name, BPoint a_point);
|
||||
status_t AddString(const char *name, const char *a_string);
|
||||
status_t AddString(const char *name, const BString& a_string);
|
||||
status_t AddInt8(const char *name, int8 val);
|
||||
status_t AddInt16(const char *name, int16 val);
|
||||
status_t AddInt32(const char *name, int32 val);
|
||||
status_t AddInt64(const char *name, int64 val);
|
||||
status_t AddBool(const char *name, bool a_boolean);
|
||||
status_t AddFloat(const char *name, float a_float);
|
||||
status_t AddDouble(const char *name, double a_double);
|
||||
status_t AddPointer(const char *name, const void *ptr);
|
||||
status_t AddMessenger(const char *name, BMessenger messenger);
|
||||
status_t AddRef(const char *name, const entry_ref *ref);
|
||||
status_t AddMessage(const char *name, const BMessage *msg);
|
||||
status_t AddFlat(const char *name, BFlattenable *obj, int32 count = 1);
|
||||
status_t AddData(const char *name, type_code type, const void *data,
|
||||
ssize_t numBytes, bool is_fixed_size = true, int32 count = 1);
|
||||
|
||||
// Removing data
|
||||
status_t RemoveData(const char *name, int32 index = 0);
|
||||
status_t RemoveName(const char *name);
|
||||
status_t MakeEmpty();
|
||||
|
||||
// Finding data
|
||||
status_t FindRect(const char *name, BRect *rect) const;
|
||||
status_t FindRect(const char *name, int32 index, BRect *rect) const;
|
||||
status_t FindPoint(const char *name, BPoint *pt) const;
|
||||
status_t FindPoint(const char *name, int32 index, BPoint *pt) const;
|
||||
status_t FindString(const char *name, const char **str) const;
|
||||
status_t FindString(const char *name, int32 index, const char **str) const;
|
||||
status_t FindString(const char *name, BString *str) const;
|
||||
status_t FindString(const char *name, int32 index, BString *str) const;
|
||||
status_t FindInt8(const char *name, int8 *value) const;
|
||||
status_t FindInt8(const char *name, int32 index, int8 *val) const;
|
||||
status_t FindInt16(const char *name, int16 *value) const;
|
||||
status_t FindInt16(const char *name, int32 index, int16 *val) const;
|
||||
status_t FindInt32(const char *name, int32 *value) const;
|
||||
status_t FindInt32(const char *name, int32 index, int32 *val) const;
|
||||
status_t FindInt64(const char *name, int64 *value) const;
|
||||
status_t FindInt64(const char *name, int32 index, int64 *val) const;
|
||||
status_t FindBool(const char *name, bool *value) const;
|
||||
status_t FindBool(const char *name, int32 index, bool *value) const;
|
||||
status_t FindFloat(const char *name, float *f) const;
|
||||
status_t FindFloat(const char *name, int32 index, float *f) const;
|
||||
status_t FindDouble(const char *name, double *d) const;
|
||||
status_t FindDouble(const char *name, int32 index, double *d) const;
|
||||
status_t FindPointer(const char *name, void **ptr) const;
|
||||
status_t FindPointer(const char *name, int32 index, void **ptr) const;
|
||||
status_t FindMessenger(const char *name, BMessenger *m) const;
|
||||
status_t FindMessenger(const char *name, int32 index, BMessenger *m) const;
|
||||
status_t FindRef(const char *name, entry_ref *ref) const;
|
||||
status_t FindRef(const char *name, int32 index, entry_ref *ref) const;
|
||||
status_t FindMessage(const char *name, BMessage *msg) const;
|
||||
status_t FindMessage(const char *name, int32 index, BMessage *msg) const;
|
||||
status_t FindFlat(const char *name, BFlattenable *obj) const;
|
||||
status_t FindFlat(const char *name, int32 index, BFlattenable *obj) const;
|
||||
status_t FindData(const char *name, type_code type,
|
||||
const void **data, ssize_t *numBytes) const;
|
||||
status_t FindData(const char *name, type_code type, int32 index,
|
||||
const void **data, ssize_t *numBytes) const;
|
||||
|
||||
// Replacing data
|
||||
status_t ReplaceRect(const char *name, BRect a_rect);
|
||||
status_t ReplaceRect(const char *name, int32 index, BRect a_rect);
|
||||
status_t ReplacePoint(const char *name, BPoint a_point);
|
||||
status_t ReplacePoint(const char *name, int32 index, BPoint a_point);
|
||||
status_t ReplaceString(const char *name, const char *string);
|
||||
status_t ReplaceString(const char *name, int32 index, const char *string);
|
||||
status_t ReplaceString(const char *name, const BString& string);
|
||||
status_t ReplaceString(const char *name, int32 index, const BString& string);
|
||||
status_t ReplaceInt8(const char *name, int8 val);
|
||||
status_t ReplaceInt8(const char *name, int32 index, int8 val);
|
||||
status_t ReplaceInt16(const char *name, int16 val);
|
||||
status_t ReplaceInt16(const char *name, int32 index, int16 val);
|
||||
status_t ReplaceInt32(const char *name, int32 val);
|
||||
status_t ReplaceInt32(const char *name, int32 index, int32 val);
|
||||
status_t ReplaceInt64(const char *name, int64 val);
|
||||
status_t ReplaceInt64(const char *name, int32 index, int64 val);
|
||||
status_t ReplaceBool(const char *name, bool a_bool);
|
||||
status_t ReplaceBool(const char *name, int32 index, bool a_bool);
|
||||
status_t ReplaceFloat(const char *name, float a_float);
|
||||
status_t ReplaceFloat(const char *name, int32 index, float a_float);
|
||||
status_t ReplaceDouble(const char *name, double a_double);
|
||||
status_t ReplaceDouble(const char *name, int32 index, double a_double);
|
||||
status_t ReplacePointer(const char *name, const void *ptr);
|
||||
status_t ReplacePointer(const char *name,int32 index,const void *ptr);
|
||||
status_t ReplaceMessenger(const char *name, BMessenger messenger);
|
||||
status_t ReplaceMessenger(const char *name, int32 index, BMessenger msngr);
|
||||
status_t ReplaceRef( const char *name,const entry_ref *ref);
|
||||
status_t ReplaceRef( const char *name, int32 index, const entry_ref *ref);
|
||||
status_t ReplaceMessage(const char *name, const BMessage *msg);
|
||||
status_t ReplaceMessage(const char *name, int32 index, const BMessage *msg);
|
||||
status_t ReplaceFlat(const char *name, BFlattenable *obj);
|
||||
status_t ReplaceFlat(const char *name, int32 index, BFlattenable *obj);
|
||||
status_t ReplaceData(const char *name, type_code type,
|
||||
const void *data, ssize_t data_size);
|
||||
status_t ReplaceData(const char *name, type_code type, int32 index,
|
||||
const void *data, ssize_t data_size);
|
||||
|
||||
void *operator new(size_t size);
|
||||
void *operator new(size_t, void* p);
|
||||
void operator delete(void *ptr, size_t size);
|
||||
|
||||
// Private, reserved, or obsolete ----------------------------------------------
|
||||
bool HasRect(const char *, int32 n = 0) const;
|
||||
bool HasPoint(const char *, int32 n = 0) const;
|
||||
bool HasString(const char *, int32 n = 0) const;
|
||||
bool HasInt8(const char *, int32 n = 0) const;
|
||||
bool HasInt16(const char *, int32 n = 0) const;
|
||||
bool HasInt32(const char *, int32 n = 0) const;
|
||||
bool HasInt64(const char *, int32 n = 0) const;
|
||||
bool HasBool(const char *, int32 n = 0) const;
|
||||
bool HasFloat(const char *, int32 n = 0) const;
|
||||
bool HasDouble(const char *, int32 n = 0) const;
|
||||
bool HasPointer(const char *, int32 n = 0) const;
|
||||
bool HasMessenger(const char *, int32 n = 0) const;
|
||||
bool HasRef(const char *, int32 n = 0) const;
|
||||
bool HasMessage(const char *, int32 n = 0) const;
|
||||
bool HasFlat(const char *, const BFlattenable *) const;
|
||||
bool HasFlat(const char *,int32 ,const BFlattenable *) const;
|
||||
bool HasData(const char *, type_code , int32 n = 0) const;
|
||||
BRect FindRect(const char *, int32 n = 0) const;
|
||||
BPoint FindPoint(const char *, int32 n = 0) const;
|
||||
const char *FindString(const char *, int32 n = 0) const;
|
||||
int8 FindInt8(const char *, int32 n = 0) const;
|
||||
int16 FindInt16(const char *, int32 n = 0) const;
|
||||
int32 FindInt32(const char *, int32 n = 0) const;
|
||||
int64 FindInt64(const char *, int32 n = 0) const;
|
||||
bool FindBool(const char *, int32 n = 0) const;
|
||||
float FindFloat(const char *, int32 n = 0) const;
|
||||
double FindDouble(const char *, int32 n = 0) const;
|
||||
|
||||
class Private;
|
||||
|
||||
private:
|
||||
class Header;
|
||||
|
||||
friend class BMessageQueue;
|
||||
friend class BMessenger;
|
||||
friend class BApplication;
|
||||
friend class Header;
|
||||
friend class Private;
|
||||
|
||||
friend inline void _set_message_target_(BMessage *, int32, bool);
|
||||
friend inline void _set_message_reply_(BMessage *, BMessenger);
|
||||
friend inline int32 _get_message_target_(BMessage *);
|
||||
friend inline bool _use_preferred_target_(BMessage *);
|
||||
|
||||
// deprecated
|
||||
BMessage(BMessage *a_message);
|
||||
|
||||
virtual void _ReservedMessage1();
|
||||
virtual void _ReservedMessage2();
|
||||
virtual void _ReservedMessage3();
|
||||
|
||||
void init_data();
|
||||
status_t real_flatten(char *result, ssize_t size) const;
|
||||
status_t real_flatten(BDataIO *stream, ssize_t *size) const;
|
||||
char *stack_flatten(char *stack_ptr,
|
||||
ssize_t stack_size, bool incl_reply,
|
||||
ssize_t *size = NULL) const;
|
||||
|
||||
status_t _UnflattenKMessage(const char *buffer);
|
||||
|
||||
ssize_t calc_hdr_size() const;
|
||||
|
||||
status_t _send_(port_id port, int32 token,
|
||||
bool preferred, bigtime_t timeout,
|
||||
bool reply_required,
|
||||
BMessenger &reply_to) const;
|
||||
status_t send_message(port_id port, team_id port_owner,
|
||||
int32 token, bool preferred,
|
||||
BMessage *reply,
|
||||
bigtime_t send_timeout,
|
||||
bigtime_t reply_timeout) const;
|
||||
|
||||
static status_t _SendFlattenedMessage(void *data, int32 size,
|
||||
port_id port, int32 token, bool preferred,
|
||||
bigtime_t timeout);
|
||||
|
||||
static void _StaticInit();
|
||||
static void _StaticCleanup();
|
||||
static void _StaticCacheCleanup();
|
||||
|
||||
enum { sNumReplyPorts = 3 };
|
||||
static port_id sReplyPorts[sNumReplyPorts];
|
||||
static long sReplyPortInUse[sNumReplyPorts];
|
||||
static int32 sGetCachedReplyPort();
|
||||
|
||||
static BBlockCache *sMsgCache;
|
||||
|
||||
BMessage *fUnused1;
|
||||
int32 fTarget;
|
||||
BMessage *fOriginal;
|
||||
uint32 fUnused2;
|
||||
int32 fCurSpecifier;
|
||||
uint32 fReserved[4];
|
||||
|
||||
BPrivate::BMessageBody *fBody;
|
||||
|
||||
struct reply_to_info {
|
||||
port_id port;
|
||||
int32 target;
|
||||
team_id team;
|
||||
bool preferred;
|
||||
} fReplyTo;
|
||||
|
||||
bool fPreferred;
|
||||
bool fReplyRequired;
|
||||
bool fReplyDone;
|
||||
bool fIsReply;
|
||||
bool fWasDelivered;
|
||||
bool fReadOnly;
|
||||
bool fHasSpecifiers;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#endif // _MESSAGE_H
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright 2005, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <[email protected]>
|
||||
*/
|
||||
|
||||
/* BMessageBody handles data storage and retrieval for BMessage. */
|
||||
|
||||
#ifndef _MESSAGE_BODY_H_
|
||||
#define _MESSAGE_BODY_H_
|
||||
|
||||
#include <List.h>
|
||||
#include "MessageField2.h"
|
||||
|
||||
enum {
|
||||
B_FLATTENABLE_TYPE = 'FLAT'
|
||||
};
|
||||
|
||||
namespace BPrivate {
|
||||
|
||||
class BMessageBody {
|
||||
public:
|
||||
BMessageBody();
|
||||
BMessageBody(const BMessageBody &other);
|
||||
~BMessageBody();
|
||||
|
||||
BMessageBody &operator=(const BMessageBody &other);
|
||||
|
||||
status_t GetInfo(type_code typeRequested, int32 which,
|
||||
char **name, type_code *typeFound,
|
||||
int32 *countFound = NULL) const;
|
||||
status_t GetInfo(const char *name, type_code *typeFound,
|
||||
int32 *countFound = NULL) const;
|
||||
status_t GetInfo(const char *name, type_code *typeFound,
|
||||
bool *fixedSize) const;
|
||||
|
||||
int32 CountNames(type_code type) const;
|
||||
bool IsEmpty() const;
|
||||
|
||||
ssize_t FlattenedSize() const;
|
||||
status_t Flatten(BDataIO *stream) const;
|
||||
status_t Unflatten(BDataIO *stream);
|
||||
|
||||
status_t AddData(const char *name, type_code type,
|
||||
size_t length, void **buffer,
|
||||
bool fixedSize = false, int32 count = 1);
|
||||
status_t RemoveData(const char *name, int32 index = 0);
|
||||
|
||||
bool HasData(const char *name, type_code t, int32 n) const;
|
||||
status_t FindData(const char *name, type_code type,
|
||||
int32 index, const void **data,
|
||||
ssize_t *numBytes) const;
|
||||
status_t ReplaceData(const char *name, type_code type,
|
||||
int32 index, size_t length, void **buffer);
|
||||
|
||||
status_t Rename(const char *oldName, const char *newName);
|
||||
status_t RemoveName(const char *name);
|
||||
status_t MakeEmpty();
|
||||
|
||||
void PrintToStream() const;
|
||||
|
||||
// hash table support
|
||||
void HashInsert(BMessageField *field);
|
||||
BMessageField *HashLookup(const char *name) const;
|
||||
BMessageField *HashRemove(const char *name);
|
||||
uint32 HashString(const char *string) const;
|
||||
void HashClear();
|
||||
|
||||
private:
|
||||
status_t InitCommon();
|
||||
BMessageField *AddField(const char *name, type_code type,
|
||||
status_t &error);
|
||||
BMessageField *FindData(const char *name, type_code type,
|
||||
status_t &error) const;
|
||||
|
||||
BList fFieldList;
|
||||
BMessageField **fFieldTable;
|
||||
int32 fFieldTableSize;
|
||||
|
||||
mutable ssize_t fFlattenedSize;
|
||||
};
|
||||
|
||||
} // namespace BPrivate
|
||||
|
||||
#endif // _MESSAGE_BODY_H_
|
||||
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
* Copyright 2005, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <[email protected]>
|
||||
*/
|
||||
|
||||
/* BMessageBody handles data storage and retrieval for BMessage. */
|
||||
|
||||
#ifndef _MESSAGE_BODY_H_
|
||||
#define _MESSAGE_BODY_H_
|
||||
|
||||
#include <List.h>
|
||||
|
||||
enum {
|
||||
B_FLATTENABLE_TYPE = 'FLAT'
|
||||
};
|
||||
|
||||
namespace BPrivate {
|
||||
|
||||
class BMessageField;
|
||||
|
||||
class BMessageBody {
|
||||
public:
|
||||
BMessageBody();
|
||||
BMessageBody(const BMessageBody &other);
|
||||
~BMessageBody();
|
||||
|
||||
BMessageBody &operator=(const BMessageBody &other);
|
||||
|
||||
status_t GetInfo(type_code typeRequested, int32 which,
|
||||
char **name, type_code *typeFound,
|
||||
int32 *countFound = NULL) const;
|
||||
status_t GetInfo(const char *name, type_code *typeFound,
|
||||
int32 *countFound = NULL) const;
|
||||
status_t GetInfo(const char *name, type_code *typeFound,
|
||||
bool *fixedSize) const;
|
||||
|
||||
int32 CountNames(type_code type) const;
|
||||
bool IsEmpty() const;
|
||||
|
||||
ssize_t FlattenedSize() const;
|
||||
status_t Flatten(BDataIO *stream) const;
|
||||
status_t Unflatten(BDataIO *stream, int32 length);
|
||||
|
||||
status_t AddData(const char *name, type_code type,
|
||||
const void *item, ssize_t length,
|
||||
bool fixedSize);
|
||||
status_t AddData(const char *name, type_code type,
|
||||
void **buffer, ssize_t length);
|
||||
status_t ReplaceData(const char *name, type_code type,
|
||||
int32 index, const void *item, ssize_t length);
|
||||
status_t ReplaceData(const char *name, type_code type,
|
||||
int32 index, void **buffer, ssize_t length);
|
||||
|
||||
status_t RemoveData(const char *name, int32 index = 0);
|
||||
|
||||
bool HasData(const char *name, type_code t,
|
||||
int32 index) const;
|
||||
status_t FindData(const char *name, type_code type,
|
||||
int32 index, const void **data,
|
||||
ssize_t *numBytes) const;
|
||||
|
||||
status_t Rename(const char *oldName, const char *newName);
|
||||
status_t RemoveName(const char *name);
|
||||
status_t MakeEmpty();
|
||||
|
||||
void PrintToStream() const;
|
||||
|
||||
// flat buffer management
|
||||
inline uint8 *FlatBuffer() const { return fFlatBuffer; };
|
||||
uint8 *FlatInsert(int32 offset, ssize_t oldLength,
|
||||
ssize_t newLength);
|
||||
void FlatResize(int32 newSize);
|
||||
|
||||
// hash table support
|
||||
void HashInsert(BMessageField *field);
|
||||
BMessageField *HashLookup(const char *name) const;
|
||||
BMessageField *HashRemove(const char *name);
|
||||
uint32 HashString(const char *string) const;
|
||||
void HashClear();
|
||||
|
||||
private:
|
||||
status_t InitCommon();
|
||||
BMessageField *AddData(const char *name, type_code type,
|
||||
status_t &error);
|
||||
BMessageField *FindData(const char *name, type_code type,
|
||||
status_t &error) const;
|
||||
|
||||
BList fFieldList;
|
||||
BMessageField **fFieldTable;
|
||||
int32 fFieldTableSize;
|
||||
|
||||
uint8 *fFlatBuffer;
|
||||
int32 fFlatLength;
|
||||
int32 fFlatAllocated;
|
||||
int32 fBlockSize;
|
||||
};
|
||||
|
||||
} // namespace BPrivate
|
||||
|
||||
#endif // _MESSAGE_BODY_H_
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* Copyright 2005, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <[email protected]>
|
||||
*/
|
||||
|
||||
/* BMessageField contains the data for indiviual named fields in BMessageBody */
|
||||
|
||||
#ifndef _MESSAGE_FIELD_H_
|
||||
#define _MESSAGE_FIELD_H_
|
||||
|
||||
#include <DataIO.h>
|
||||
#include <List.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#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 0x00
|
||||
|
||||
namespace BPrivate {
|
||||
|
||||
typedef struct field_header_s {
|
||||
uint8 flags;
|
||||
type_code type;
|
||||
int32 count;
|
||||
ssize_t dataSize;
|
||||
uint8 nameLength;
|
||||
char name[255];
|
||||
} __attribute__((__packed__)) FieldHeader;
|
||||
|
||||
class BMessageField {
|
||||
public:
|
||||
BMessageField();
|
||||
BMessageField(const char *name, type_code type);
|
||||
BMessageField(uint8 flags, BDataIO *stream);
|
||||
BMessageField(const BMessageField &other);
|
||||
~BMessageField();
|
||||
|
||||
BMessageField &operator=(const BMessageField &other);
|
||||
|
||||
void Flatten(BDataIO *stream);
|
||||
void Unflatten(uint8 flags, BDataIO *stream);
|
||||
|
||||
uint8 Flags() { return fHeader.flags; };
|
||||
|
||||
void SetName(const char *name);
|
||||
const char *Name() const { return fHeader.name; };
|
||||
uint8 NameLength() const { return fHeader.nameLength; };
|
||||
type_code Type() const { return fHeader.type; };
|
||||
|
||||
void *AddItem(size_t length);
|
||||
void *ReplaceItem(int32 index, size_t newLength);
|
||||
void RemoveItem(int32 index);
|
||||
int32 CountItems() const { return fHeader.count; };
|
||||
|
||||
const void *BufferAt(int32 index, ssize_t *size) const;
|
||||
|
||||
void MakeEmpty();
|
||||
|
||||
status_t SetFixedSize(int32 itemSize, int32 count);
|
||||
bool IsFixedSize() const { return fHeader.flags & MSG_FLAG_FIXED_SIZE; };
|
||||
size_t TotalSize() const { return fHeader.dataSize; };
|
||||
|
||||
void PrintToStream() const;
|
||||
|
||||
// hash table support
|
||||
void SetNext(BMessageField *next) { fNext = next; };
|
||||
BMessageField *Next() const { return fNext; };
|
||||
|
||||
private:
|
||||
void ResetHeader(const char *name, type_code type);
|
||||
void FlatResize(int32 offset, size_t oldLength,
|
||||
size_t newLength);
|
||||
|
||||
FieldHeader fHeader;
|
||||
mutable BMallocIO fFlatBuffer;
|
||||
|
||||
// fixed size items
|
||||
int32 fItemSize;
|
||||
|
||||
// variable sized items
|
||||
BList *fOffsets;
|
||||
|
||||
// hash table support
|
||||
BMessageField *fNext;
|
||||
};
|
||||
|
||||
} // namespace BPrivate
|
||||
|
||||
#endif // _MESSAGE_FIELD_H_
|
||||
@@ -1,120 +0,0 @@
|
||||
/*
|
||||
* Copyright 2005, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <[email protected]>
|
||||
*/
|
||||
|
||||
/* BMessageField contains the data for indiviual named fields in BMessageBody */
|
||||
|
||||
#ifndef _MESSAGE_FIELD_H_
|
||||
#define _MESSAGE_FIELD_H_
|
||||
|
||||
#include <List.h>
|
||||
#include <String.h>
|
||||
#include <SupportDefs.h>
|
||||
#include "MessageBody3.h"
|
||||
|
||||
// we only support those
|
||||
#define MSG_FLAG_VALID 0x01
|
||||
#define MSG_FLAG_FIXED_SIZE 0x04
|
||||
#define MSG_FLAG_ALL 0x05
|
||||
|
||||
// these are for R5 compatibility
|
||||
#define MSG_FLAG_MINI_DATA 0x02
|
||||
#define MSG_FLAG_SINGLE_ITEM 0x08
|
||||
|
||||
#define MSG_LAST_ENTRY 0x00
|
||||
|
||||
namespace BPrivate {
|
||||
|
||||
struct field_header_s {
|
||||
uint8 flags;
|
||||
type_code type;
|
||||
int32 count;
|
||||
ssize_t dataSize;
|
||||
uint8 nameLength;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct item_info_s {
|
||||
item_info_s(int32 _offset)
|
||||
: offset(_offset)
|
||||
{
|
||||
}
|
||||
|
||||
item_info_s(int32 _offset, int32 _length)
|
||||
: offset(_offset),
|
||||
length(_length)
|
||||
{
|
||||
}
|
||||
|
||||
int32 offset;
|
||||
int32 length;
|
||||
int32 paddedLength;
|
||||
};
|
||||
|
||||
typedef field_header_s FieldHeader;
|
||||
typedef item_info_s ItemInfo;
|
||||
|
||||
class BMessageField {
|
||||
public:
|
||||
BMessageField(BMessageBody *parent,
|
||||
int32 offset, const char *name,
|
||||
type_code type);
|
||||
|
||||
// only use this constructor to unflatten
|
||||
BMessageField(BMessageBody *parent);
|
||||
int32 Unflatten(int32 offset);
|
||||
|
||||
uint8 Flags() const { return Header()->flags; };
|
||||
status_t SetFixedSize(int32 itemSize);
|
||||
bool FixedSize() const { return fFixedSize; };
|
||||
|
||||
void SetName(const char *newName);
|
||||
const char *Name() const;
|
||||
uint8 NameLength() const { return Header()->nameLength; };
|
||||
type_code Type() const { return Header()->type; };
|
||||
|
||||
void AddItem(const void *item, ssize_t length);
|
||||
uint8 *AddItem(ssize_t length);
|
||||
|
||||
void ReplaceItem(int32 index, const void *newItem,
|
||||
ssize_t length);
|
||||
uint8 *ReplaceItem(int32 index, ssize_t length);
|
||||
|
||||
void *ItemAt(int32 index, ssize_t *size);
|
||||
|
||||
void RemoveItem(int32 index);
|
||||
int32 CountItems() const { return Header()->count; };
|
||||
|
||||
void PrintToStream() const;
|
||||
|
||||
void SetOffset(int32 offset) { fOffset = offset; };
|
||||
int32 Offset() const { return fOffset; };
|
||||
|
||||
// always do MakeEmpty -> RemoveSelf -> delete
|
||||
void MakeEmpty();
|
||||
void RemoveSelf();
|
||||
|
||||
// hash table support
|
||||
void SetNext(BMessageField *next) { fNext = next; };
|
||||
BMessageField *Next() const { return fNext; };
|
||||
|
||||
private:
|
||||
inline FieldHeader *Header() const { return (FieldHeader *)(fParent->FlatBuffer() + fOffset); };
|
||||
|
||||
BMessageBody *fParent;
|
||||
int32 fOffset;
|
||||
int32 fDataOffset;
|
||||
|
||||
bool fFixedSize;
|
||||
int32 fItemSize;
|
||||
BList fItemInfos;
|
||||
|
||||
BMessageField *fNext;
|
||||
};
|
||||
|
||||
} // namespace BPrivate
|
||||
|
||||
#endif // _MESSAGE_FIELD_H_
|
||||
@@ -1,222 +0,0 @@
|
||||
#ifndef MESSAGEUTILS_H
|
||||
#define MESSAGEUTILS_H
|
||||
|
||||
#include <ByteOrder.h>
|
||||
#include <DataIO.h>
|
||||
#include <Entry.h>
|
||||
#include <Message.h>
|
||||
#include <Messenger.h>
|
||||
#include <MessengerPrivate.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
uint32 _checksum_(const uchar *buf, int32 size);
|
||||
|
||||
namespace BPrivate { // Only putting these here because Be did
|
||||
|
||||
status_t entry_ref_flatten(char* buffer, size_t* size, const entry_ref* ref);
|
||||
status_t entry_ref_unflatten(entry_ref* ref, const char* buffer, size_t size);
|
||||
status_t entry_ref_swap(char* buffer, size_t size);
|
||||
|
||||
size_t calc_padding(size_t size, size_t boundary);
|
||||
|
||||
} // namespace BPrivate
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// _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)
|
||||
{
|
||||
BMessenger::Private messengerPrivate(messenger);
|
||||
message->fReplyTo.port = messengerPrivate.Port();
|
||||
message->fReplyTo.target = messengerPrivate.Token();
|
||||
message->fReplyTo.team = messengerPrivate.Team();
|
||||
message->fReplyTo.preferred = messengerPrivate.IsPreferredTarget();
|
||||
}
|
||||
|
||||
|
||||
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<class T>
|
||||
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 error = stream->Write(data, size);
|
||||
if (error < B_OK)
|
||||
throw error;
|
||||
}
|
||||
|
||||
|
||||
class TReadHelper {
|
||||
public:
|
||||
TReadHelper(BDataIO *stream)
|
||||
: fStream(stream),
|
||||
fError(B_OK),
|
||||
fSwap(false)
|
||||
{
|
||||
}
|
||||
|
||||
TReadHelper(BDataIO *stream, bool swap)
|
||||
: fStream(stream),
|
||||
fError(B_OK),
|
||||
fSwap(swap)
|
||||
{
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void operator()(T &data)
|
||||
{
|
||||
fError = fStream->Read((void *)&data, sizeof(T));
|
||||
if (fError < B_OK)
|
||||
throw fError;
|
||||
|
||||
if (IsSwapping())
|
||||
byte_swap(data);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void operator()(T data, size_t len)
|
||||
{
|
||||
fError = fStream->Read((void *)data, len);
|
||||
if (fError < B_OK)
|
||||
throw fError;
|
||||
}
|
||||
|
||||
status_t Status() { return fError; };
|
||||
|
||||
void SetSwap(bool yesNo) { fSwap = yesNo; };
|
||||
bool IsSwapping() { return fSwap; };
|
||||
|
||||
private:
|
||||
BDataIO *fStream;
|
||||
status_t fError;
|
||||
bool fSwap;
|
||||
};
|
||||
|
||||
|
||||
class TChecksumHelper {
|
||||
public:
|
||||
TChecksumHelper(uchar* buffer)
|
||||
: fBuffer(buffer),
|
||||
fBufPtr(buffer)
|
||||
{
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void Cache(const T &data)
|
||||
{
|
||||
*((T*)fBufPtr) = data;
|
||||
fBufPtr += sizeof (T);
|
||||
}
|
||||
|
||||
int32 CheckSum();
|
||||
|
||||
private:
|
||||
uchar *fBuffer;
|
||||
uchar *fBufPtr;
|
||||
};
|
||||
|
||||
|
||||
template<class T>
|
||||
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
|
||||
@@ -1,230 +0,0 @@
|
||||
#ifndef MESSAGEUTILS_H
|
||||
#define MESSAGEUTILS_H
|
||||
|
||||
#include <ByteOrder.h>
|
||||
#include <DataIO.h>
|
||||
#include <Entry.h>
|
||||
#include <Message.h>
|
||||
#include <Messenger.h>
|
||||
#include <MessengerPrivate.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
uint32 _checksum_(const uchar *buf, int32 size);
|
||||
|
||||
namespace BPrivate { // Only putting these here because Be did
|
||||
|
||||
status_t entry_ref_flatten(char* buffer, size_t* size, const entry_ref* ref);
|
||||
status_t entry_ref_unflatten(entry_ref* ref, const char* buffer, size_t size);
|
||||
status_t entry_ref_swap(char* buffer, size_t size);
|
||||
|
||||
size_t calc_padding(size_t size, size_t boundary);
|
||||
|
||||
} // namespace BPrivate
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// _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)
|
||||
{
|
||||
BMessenger::Private messengerPrivate(messenger);
|
||||
message->fReplyTo.port = messengerPrivate.Port();
|
||||
message->fReplyTo.target = messengerPrivate.Token();
|
||||
message->fReplyTo.team = messengerPrivate.Team();
|
||||
message->fReplyTo.preferred = messengerPrivate.IsPreferredTarget();
|
||||
}
|
||||
|
||||
|
||||
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<class T>
|
||||
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 error = stream->Write(data, size);
|
||||
if (error < B_OK)
|
||||
throw error;
|
||||
}
|
||||
|
||||
|
||||
class TReadHelper {
|
||||
public:
|
||||
TReadHelper(BDataIO *stream)
|
||||
: fStream(stream),
|
||||
fError(B_OK),
|
||||
fSwap(false)
|
||||
{
|
||||
}
|
||||
|
||||
TReadHelper(BDataIO *stream, bool swap)
|
||||
: fStream(stream),
|
||||
fError(B_OK),
|
||||
fSwap(swap)
|
||||
{
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void operator()(T &data)
|
||||
{
|
||||
fError = fStream->Read((void *)&data, sizeof(T));
|
||||
if (fError > B_OK) {
|
||||
if (IsSwapping())
|
||||
byte_swap(data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fError == 0)
|
||||
throw B_ERROR;
|
||||
throw fError;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void operator()(T data, size_t len)
|
||||
{
|
||||
fError = fStream->Read((void *)data, len);
|
||||
if (fError > B_OK)
|
||||
return;
|
||||
|
||||
if (fError == 0)
|
||||
throw B_ERROR;
|
||||
throw fError;
|
||||
}
|
||||
|
||||
status_t Status() { return fError; };
|
||||
|
||||
void SetSwap(bool yesNo) { fSwap = yesNo; };
|
||||
bool IsSwapping() { return fSwap; };
|
||||
|
||||
private:
|
||||
BDataIO *fStream;
|
||||
status_t fError;
|
||||
bool fSwap;
|
||||
};
|
||||
|
||||
|
||||
class TChecksumHelper {
|
||||
public:
|
||||
TChecksumHelper(uchar* buffer)
|
||||
: fBuffer(buffer),
|
||||
fBufPtr(buffer)
|
||||
{
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void Cache(const T &data)
|
||||
{
|
||||
*((T*)fBufPtr) = data;
|
||||
fBufPtr += sizeof (T);
|
||||
}
|
||||
|
||||
int32 CheckSum();
|
||||
|
||||
private:
|
||||
uchar *fBuffer;
|
||||
uchar *fBufPtr;
|
||||
};
|
||||
|
||||
|
||||
template<class T>
|
||||
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
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,553 +0,0 @@
|
||||
/*
|
||||
* Copyright 2005, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <[email protected]>
|
||||
*/
|
||||
|
||||
/* BMessageBody handles data storage and retrieval for BMessage. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <TypeConstants.h>
|
||||
#include "MessageBody2.h"
|
||||
#include "MessageUtils2.h"
|
||||
|
||||
namespace BPrivate {
|
||||
|
||||
BMessageBody::BMessageBody()
|
||||
{
|
||||
InitCommon();
|
||||
}
|
||||
|
||||
|
||||
BMessageBody::BMessageBody(const BMessageBody &other)
|
||||
{
|
||||
InitCommon();
|
||||
*this = other;
|
||||
}
|
||||
|
||||
|
||||
BMessageBody::~BMessageBody()
|
||||
{
|
||||
MakeEmpty();
|
||||
delete fFieldTable;
|
||||
}
|
||||
|
||||
|
||||
BMessageBody &
|
||||
BMessageBody::operator=(const BMessageBody &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
MakeEmpty();
|
||||
|
||||
for (int32 index = 0; index < other.fFieldList.CountItems(); index++) {
|
||||
BMessageField *otherField = (BMessageField *)other.fFieldList.ItemAt(index);
|
||||
BMessageField *newField = new BMessageField(*otherField);
|
||||
fFieldList.AddItem((void *)newField);
|
||||
HashInsert(newField);
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageBody::InitCommon()
|
||||
{
|
||||
fFlattenedSize = -1;
|
||||
fFieldTableSize = 100;
|
||||
fFieldTable = new BMessageField *[fFieldTableSize];
|
||||
HashClear();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageBody::GetInfo(type_code typeRequested, int32 which, char **name,
|
||||
type_code *typeReturned, int32 *count) const
|
||||
{
|
||||
int32 index = 0;
|
||||
int32 fieldCount = fFieldList.CountItems();
|
||||
BMessageField *field = NULL;
|
||||
bool found = false;
|
||||
|
||||
for (int32 fieldIndex = 0; fieldIndex < fieldCount; fieldIndex++) {
|
||||
field = (BMessageField *)fFieldList.ItemAt(fieldIndex);
|
||||
|
||||
if (typeRequested == B_ANY_TYPE || field->Type() == typeRequested) {
|
||||
if (index == which) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
// we couldn't find any appropriate data
|
||||
if (!found) {
|
||||
if (count)
|
||||
*count = 0;
|
||||
|
||||
if (index > 0)
|
||||
return B_BAD_INDEX;
|
||||
else
|
||||
return B_BAD_TYPE;
|
||||
}
|
||||
|
||||
// ToDo: BC Break
|
||||
// Change 'name' parameter to const char *
|
||||
|
||||
if (name)
|
||||
*name = const_cast<char *>(field->Name());
|
||||
|
||||
if (typeReturned)
|
||||
*typeReturned = field->Type();
|
||||
|
||||
if (count)
|
||||
*count = field->CountItems();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageBody::GetInfo(const char *name, type_code *typeFound,
|
||||
int32 *countFound) const
|
||||
{
|
||||
status_t error = B_OK;
|
||||
BMessageField *field = FindData(name, B_ANY_TYPE, error);
|
||||
|
||||
if (field) {
|
||||
if (typeFound)
|
||||
*typeFound = field->Type();
|
||||
|
||||
if (countFound)
|
||||
*countFound = field->CountItems();
|
||||
} else {
|
||||
if (countFound)
|
||||
*countFound = 0;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageBody::GetInfo(const char *name, type_code *typeFound, bool *fixedSize) const
|
||||
{
|
||||
status_t error = B_OK;
|
||||
BMessageField *field = FindData(name, B_ANY_TYPE, error);
|
||||
|
||||
if (field) {
|
||||
if (typeFound)
|
||||
*typeFound = field->Type();
|
||||
|
||||
if (fixedSize)
|
||||
*fixedSize = field->IsFixedSize();
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
BMessageBody::CountNames(type_code type) const
|
||||
{
|
||||
if (type == B_ANY_TYPE)
|
||||
return fFieldList.CountItems();
|
||||
|
||||
int32 count = 0;
|
||||
for (int32 index = 0; index < fFieldList.CountItems(); index++) {
|
||||
BMessageField *field = (BMessageField *)fFieldList.ItemAt(index);
|
||||
if (field->Type() == type)
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BMessageBody::IsEmpty() const
|
||||
{
|
||||
return fFieldList.CountItems() == 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BMessageBody::PrintToStream() const
|
||||
{
|
||||
for (int32 index = 0; index < fFieldList.CountItems(); index++) {
|
||||
BMessageField *field = (BMessageField *)fFieldList.ItemAt(index);
|
||||
field->PrintToStream();
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageBody::Rename(const char *oldName, const char *newName)
|
||||
{
|
||||
status_t error = B_OK;
|
||||
BMessageField *field = FindData(oldName, B_ANY_TYPE, error);
|
||||
|
||||
if (!field)
|
||||
return B_NAME_NOT_FOUND;
|
||||
|
||||
field->SetName(newName);
|
||||
HashInsert(HashRemove(oldName));
|
||||
fFlattenedSize = -1;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
BMessageBody::FlattenedSize() const
|
||||
{
|
||||
if (fFlattenedSize > 0)
|
||||
return fFlattenedSize;
|
||||
|
||||
ssize_t size = 1; // for MSG_LAST_ENTRY
|
||||
|
||||
for (int32 index = 0; index < fFieldList.CountItems(); index++) {
|
||||
BMessageField *field = (BMessageField *)fFieldList.ItemAt(index);
|
||||
|
||||
uint8 flags = field->Flags();
|
||||
size += sizeof(flags) + sizeof(type_code);
|
||||
|
||||
// count information
|
||||
if (!(flags & MSG_FLAG_SINGLE_ITEM)) {
|
||||
if (flags & MSG_FLAG_MINI_DATA)
|
||||
size += sizeof(uint8);
|
||||
else
|
||||
size += sizeof(int32);
|
||||
}
|
||||
|
||||
// total size
|
||||
if (flags & MSG_FLAG_MINI_DATA)
|
||||
size += sizeof(uint8);
|
||||
else
|
||||
size += sizeof(size_t);
|
||||
|
||||
// name length byte and name length
|
||||
size += 1 + field->NameLength();
|
||||
|
||||
size += field->TotalSize();
|
||||
}
|
||||
|
||||
// cache the value for next time.
|
||||
// changing the body will reset this.
|
||||
fFlattenedSize = size;
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageBody::Flatten(BDataIO *stream) const
|
||||
{
|
||||
for (int32 index = 0; index < fFieldList.CountItems(); index++)
|
||||
((BMessageField *)fFieldList.ItemAt(index))->Flatten(stream);
|
||||
|
||||
uint8 lastEntry = 0;
|
||||
size_t error = stream->Write(&lastEntry, sizeof(lastEntry));
|
||||
|
||||
if (error > B_OK)
|
||||
return B_OK;
|
||||
else if (error == 0)
|
||||
return B_ERROR;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageBody::Unflatten(BDataIO *stream)
|
||||
{
|
||||
if (!IsEmpty())
|
||||
MakeEmpty();
|
||||
|
||||
BMessageField *newField = NULL;
|
||||
try {
|
||||
TReadHelper reader(stream);
|
||||
|
||||
uint8 flags;
|
||||
reader(flags);
|
||||
|
||||
while (flags != MSG_LAST_ENTRY) {
|
||||
newField = new BMessageField(flags, stream);
|
||||
fFieldList.AddItem(newField);
|
||||
HashInsert(newField);
|
||||
reader(flags);
|
||||
}
|
||||
} catch (status_t &error) {
|
||||
delete newField;
|
||||
return error;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageBody::AddData(const char *name, type_code type, size_t length,
|
||||
void **buffer, bool fixedSize, int32 count)
|
||||
{
|
||||
status_t error = B_OK;
|
||||
BMessageField *newField = AddField(name, type, error);
|
||||
|
||||
if (error < B_OK)
|
||||
return error;
|
||||
|
||||
if (fixedSize) {
|
||||
error = newField->SetFixedSize(length, count);
|
||||
if (error < B_OK)
|
||||
return error;
|
||||
}
|
||||
|
||||
*buffer = newField->AddItem(length);
|
||||
fFlattenedSize = -1;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
BMessageField *
|
||||
BMessageBody::AddField(const char *name, type_code type, status_t &error)
|
||||
{
|
||||
BMessageField *foundField = FindData(name, type, error);
|
||||
|
||||
if (foundField) {
|
||||
error = B_OK;
|
||||
return foundField;
|
||||
}
|
||||
|
||||
if (!foundField && error == B_NAME_NOT_FOUND) {
|
||||
// add a new field if it's not yet present
|
||||
BMessageField *newField = new BMessageField(name, type);
|
||||
fFieldList.AddItem(newField);
|
||||
HashInsert(newField);
|
||||
error = B_OK;
|
||||
return newField;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageBody::ReplaceData(const char *name, type_code type, int32 index,
|
||||
size_t length, void **buffer)
|
||||
{
|
||||
if (type == B_ANY_TYPE)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
status_t error = B_OK;
|
||||
BMessageField *field = FindData(name, type, error);
|
||||
|
||||
if (error < B_OK)
|
||||
return error;
|
||||
|
||||
if (!field)
|
||||
return B_ERROR;
|
||||
|
||||
*buffer = field->ReplaceItem(index, length);
|
||||
fFlattenedSize = -1;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageBody::RemoveData(const char *name, int32 index)
|
||||
{
|
||||
if (index < 0)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
status_t error = B_OK;
|
||||
BMessageField *field = FindData(name, B_ANY_TYPE, error);
|
||||
|
||||
if (field) {
|
||||
if (index < field->CountItems()) {
|
||||
field->RemoveItem(index);
|
||||
fFlattenedSize = -1;
|
||||
|
||||
if (field->CountItems() == 0)
|
||||
RemoveName(name);
|
||||
} else
|
||||
error = B_BAD_INDEX;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageBody::RemoveName(const char *name)
|
||||
{
|
||||
status_t error = B_OK;
|
||||
BMessageField *field = FindData(name, B_ANY_TYPE, error);
|
||||
|
||||
if (field) {
|
||||
fFieldList.RemoveItem(field);
|
||||
fFlattenedSize = -1;
|
||||
HashRemove(name);
|
||||
delete field;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageBody::MakeEmpty()
|
||||
{
|
||||
for (int32 index = 0; index < fFieldList.CountItems(); index++) {
|
||||
BMessageField *field = (BMessageField *)fFieldList.ItemAt(index);
|
||||
delete field;
|
||||
}
|
||||
|
||||
fFieldList.MakeEmpty();
|
||||
fFlattenedSize = -1;
|
||||
HashClear();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BMessageBody::HasData(const char *name, type_code type, int32 n) const
|
||||
{
|
||||
if (!name || n < 0)
|
||||
return false;
|
||||
|
||||
status_t error;
|
||||
BMessageField *field = FindData(name, type, error);
|
||||
|
||||
if (!field)
|
||||
return false;
|
||||
|
||||
if (n >= field->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 error = B_OK;
|
||||
*data = NULL;
|
||||
|
||||
BMessageField *field = FindData(name, type, error);
|
||||
if (error >= B_OK) {
|
||||
if (index >= field->CountItems())
|
||||
return B_BAD_INDEX;
|
||||
|
||||
*data = field->BufferAt(index, numBytes);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
BMessageField *
|
||||
BMessageBody::FindData(const char *name, type_code type, status_t &error) const
|
||||
{
|
||||
if (!name) {
|
||||
error = B_BAD_VALUE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BMessageField *field = HashLookup(name);
|
||||
if (field) {
|
||||
if (type != B_ANY_TYPE && field->Type() != type) {
|
||||
error = B_BAD_TYPE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
error = B_OK;
|
||||
return field;
|
||||
}
|
||||
|
||||
error = B_NAME_NOT_FOUND;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BMessageBody::HashInsert(BMessageField *field)
|
||||
{
|
||||
uint32 index = HashString(field->Name()) % fFieldTableSize;
|
||||
field->SetNext(fFieldTable[index]);
|
||||
fFieldTable[index] = field;
|
||||
}
|
||||
|
||||
|
||||
BMessageField *
|
||||
BMessageBody::HashLookup(const char *name) const
|
||||
{
|
||||
uint32 index = HashString(name) % fFieldTableSize;
|
||||
BMessageField *result = fFieldTable[index];
|
||||
|
||||
while (result) {
|
||||
if (strcmp(result->Name(), name) == 0)
|
||||
return result;
|
||||
|
||||
result = result->Next();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
BMessageField *
|
||||
BMessageBody::HashRemove(const char *name)
|
||||
{
|
||||
uint32 index = HashString(name) % fFieldTableSize;
|
||||
BMessageField *result = fFieldTable[index];
|
||||
BMessageField *last = NULL;
|
||||
|
||||
while (result) {
|
||||
if (strcmp(result->Name(), name) == 0) {
|
||||
if (last)
|
||||
last->SetNext(result->Next());
|
||||
else
|
||||
fFieldTable[index] = result->Next();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
last = result;
|
||||
result = result->Next();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BMessageBody::HashClear()
|
||||
{
|
||||
memset(fFieldTable, 0, fFieldTableSize * sizeof(BMessageField *));
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
BMessageBody::HashString(const char *string) const
|
||||
{
|
||||
char ch;
|
||||
uint32 result = 0;
|
||||
|
||||
while ((ch = *string++) != 0) {
|
||||
result = (result << 7) ^ (result >> 24);
|
||||
result ^= ch;
|
||||
}
|
||||
|
||||
result ^= result << 12;
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace BPrivate
|
||||
@@ -1,654 +0,0 @@
|
||||
/*
|
||||
* Copyright 2005, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <[email protected]>
|
||||
*/
|
||||
|
||||
/* BMessageBody handles data storage and retrieval for BMessage. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include <DataIO.h>
|
||||
#include <TypeConstants.h>
|
||||
#include "MessageBody3.h"
|
||||
#include "MessageField3.h"
|
||||
#include "MessageUtils3.h"
|
||||
|
||||
namespace BPrivate {
|
||||
|
||||
void
|
||||
dump_raw(uint8 *data, int32 length)
|
||||
{
|
||||
int32 index = 0;
|
||||
while (index < length) {
|
||||
for (int32 line = 0; line < 40 && index < length; line++, index++)
|
||||
printf("%02x ", data[index]);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BMessageBody::BMessageBody()
|
||||
{
|
||||
InitCommon();
|
||||
}
|
||||
|
||||
|
||||
BMessageBody::BMessageBody(const BMessageBody &other)
|
||||
{
|
||||
InitCommon();
|
||||
*this = other;
|
||||
}
|
||||
|
||||
|
||||
BMessageBody::~BMessageBody()
|
||||
{
|
||||
MakeEmpty();
|
||||
delete fFieldTable;
|
||||
}
|
||||
|
||||
|
||||
BMessageBody &
|
||||
BMessageBody::operator=(const BMessageBody &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
MakeEmpty();
|
||||
BMemoryIO memoryIO(other.fFlatBuffer, other.fFlatLength);
|
||||
Unflatten(&memoryIO, other.fFlatLength);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageBody::InitCommon()
|
||||
{
|
||||
// use an avarage field size for each block
|
||||
fBlockSize = sizeof(FieldHeader) + 50;
|
||||
fFlatBuffer = (uint8 *)malloc(fBlockSize);
|
||||
fFlatAllocated = fBlockSize;
|
||||
fFlatLength = 0;
|
||||
|
||||
// init hash table
|
||||
fFieldTableSize = 100;
|
||||
fFieldTable = new BMessageField *[fFieldTableSize];
|
||||
HashClear();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageBody::GetInfo(type_code typeRequested, int32 which, char **name,
|
||||
type_code *typeReturned, int32 *count) const
|
||||
{
|
||||
int32 index = 0;
|
||||
int32 fieldCount = fFieldList.CountItems();
|
||||
BMessageField *field = NULL;
|
||||
bool found = false;
|
||||
|
||||
for (int32 fieldIndex = 0; fieldIndex < fieldCount; fieldIndex++) {
|
||||
field = (BMessageField *)fFieldList.ItemAt(fieldIndex);
|
||||
|
||||
if (typeRequested == B_ANY_TYPE || field->Type() == typeRequested) {
|
||||
if (index == which) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
// we couldn't find any appropriate data
|
||||
if (!found) {
|
||||
if (count)
|
||||
*count = 0;
|
||||
|
||||
if (index > 0)
|
||||
return B_BAD_INDEX;
|
||||
else
|
||||
return B_BAD_TYPE;
|
||||
}
|
||||
|
||||
// ToDo: BC Break
|
||||
// Change 'name' parameter to const char *
|
||||
if (name)
|
||||
*name = const_cast<char *>(field->Name());
|
||||
|
||||
if (typeReturned)
|
||||
*typeReturned = field->Type();
|
||||
|
||||
if (count)
|
||||
*count = field->CountItems();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageBody::GetInfo(const char *name, type_code *typeFound,
|
||||
int32 *countFound) const
|
||||
{
|
||||
status_t error = B_ERROR;
|
||||
BMessageField *field = FindData(name, B_ANY_TYPE, error);
|
||||
|
||||
if (field) {
|
||||
if (typeFound)
|
||||
*typeFound = field->Type();
|
||||
|
||||
if (countFound)
|
||||
*countFound = field->CountItems();
|
||||
} else {
|
||||
if (countFound)
|
||||
*countFound = 0;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageBody::GetInfo(const char *name, type_code *typeFound, bool *fixedSize) const
|
||||
{
|
||||
status_t error = B_ERROR;
|
||||
BMessageField *field = FindData(name, B_ANY_TYPE, error);
|
||||
|
||||
if (field) {
|
||||
if (typeFound)
|
||||
*typeFound = field->Type();
|
||||
|
||||
if (fixedSize)
|
||||
*fixedSize = field->FixedSize();
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
BMessageBody::CountNames(type_code type) const
|
||||
{
|
||||
if (type == B_ANY_TYPE)
|
||||
return fFieldList.CountItems();
|
||||
|
||||
int32 count = 0;
|
||||
for (int32 index = 0; index < fFieldList.CountItems(); index++) {
|
||||
BMessageField *field = (BMessageField *)fFieldList.ItemAt(index);
|
||||
if (field->Type() == type)
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BMessageBody::IsEmpty() const
|
||||
{
|
||||
return fFieldList.CountItems() == 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BMessageBody::PrintToStream() const
|
||||
{
|
||||
for (int32 index = 0; index < fFieldList.CountItems(); index++) {
|
||||
BMessageField *field = (BMessageField *)fFieldList.ItemAt(index);
|
||||
field->PrintToStream();
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageBody::Rename(const char *oldName, const char *newName)
|
||||
{
|
||||
status_t error = B_ERROR;
|
||||
BMessageField *field = FindData(oldName, B_ANY_TYPE, error);
|
||||
|
||||
if (!field)
|
||||
return error;
|
||||
|
||||
field->SetName(newName);
|
||||
HashInsert(HashRemove(oldName));
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
BMessageBody::FlattenedSize() const
|
||||
{
|
||||
// one more for the last entry flag
|
||||
return fFlatLength + 1;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageBody::Flatten(BDataIO *stream) const
|
||||
{
|
||||
stream->Write(fFlatBuffer, fFlatLength);
|
||||
|
||||
uint8 lastField = MSG_LAST_ENTRY;
|
||||
status_t error = stream->Write(&lastField, sizeof(lastField));
|
||||
|
||||
if (error < B_OK)
|
||||
return error;
|
||||
if (error == 0)
|
||||
return B_ERROR;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageBody::Unflatten(BDataIO *stream, int32 length)
|
||||
{
|
||||
if (length <= 0)
|
||||
return B_OK;
|
||||
|
||||
FlatResize(length);
|
||||
status_t error = stream->Read(fFlatBuffer, length);
|
||||
|
||||
if (error < B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
int32 offset = 0;
|
||||
uint8 *location = fFlatBuffer;
|
||||
while (offset < error && *location & MSG_FLAG_VALID) {
|
||||
BMessageField *field = new BMessageField(this);
|
||||
int32 fieldLength = field->Unflatten(offset);
|
||||
|
||||
if (fieldLength <= 0) {
|
||||
field->MakeEmpty();
|
||||
delete field;
|
||||
MakeEmpty();
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
location += fieldLength;
|
||||
offset += fieldLength;
|
||||
|
||||
fFieldList.AddItem(field);
|
||||
HashInsert(field);
|
||||
}
|
||||
|
||||
// set the buffer to the actual size
|
||||
FlatResize(offset);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageBody::AddData(const char *name, type_code type, const void *item,
|
||||
ssize_t length, bool fixedSize)
|
||||
{
|
||||
status_t error = B_ERROR;
|
||||
BMessageField *field = AddData(name, type, error);
|
||||
|
||||
if (!field)
|
||||
return error;
|
||||
|
||||
if (fixedSize) {
|
||||
error = field->SetFixedSize(length);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
}
|
||||
|
||||
field->AddItem(item, length);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageBody::AddData(const char *name, type_code type, void **buffer,
|
||||
ssize_t length)
|
||||
{
|
||||
status_t error = B_ERROR;
|
||||
BMessageField *field = AddData(name, type, error);
|
||||
|
||||
if (!field)
|
||||
return error;
|
||||
|
||||
*buffer = field->AddItem(length);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
BMessageField *
|
||||
BMessageBody::AddData(const char *name, type_code type, status_t &error)
|
||||
{
|
||||
if (type == B_ANY_TYPE) {
|
||||
error = B_BAD_VALUE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BMessageField *foundField = FindData(name, type, error);
|
||||
|
||||
if (error < B_OK) {
|
||||
if (error == B_NAME_NOT_FOUND) {
|
||||
// reset the error - we will create the field
|
||||
error = B_OK;
|
||||
} else {
|
||||
// looking for B_BAD_TYPE here in particular, which would indicate
|
||||
// that we tried to add data of type X when we already had data of
|
||||
// type Y with the same name
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundField)
|
||||
return foundField;
|
||||
|
||||
// add a new field if it's not yet present
|
||||
BMessageField *newField = new BMessageField(this, fFlatLength, name, type);
|
||||
|
||||
fFieldList.AddItem(newField);
|
||||
HashInsert(newField);
|
||||
|
||||
return newField;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageBody::ReplaceData(const char *name, type_code type, int32 index,
|
||||
const void *item, ssize_t length)
|
||||
{
|
||||
if (type == B_ANY_TYPE)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
status_t error = B_ERROR;
|
||||
BMessageField *field = FindData(name, type, error);
|
||||
|
||||
if (!field)
|
||||
return error;
|
||||
|
||||
if (field->FixedSize()) {
|
||||
ssize_t itemSize = 0;
|
||||
void *item = field->ItemAt(0, &itemSize);
|
||||
|
||||
if (item && itemSize != length)
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
field->ReplaceItem(index, item, length);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageBody::ReplaceData(const char *name, type_code type, int32 index,
|
||||
void **buffer, ssize_t length)
|
||||
{
|
||||
if (type == B_ANY_TYPE)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
status_t error = B_ERROR;
|
||||
BMessageField *field = FindData(name, type, error);
|
||||
|
||||
if (!field)
|
||||
return error;
|
||||
|
||||
*buffer = field->ReplaceItem(index, length);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageBody::RemoveData(const char *name, int32 index)
|
||||
{
|
||||
if (index < 0)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
status_t error = B_ERROR;
|
||||
BMessageField *field = FindData(name, B_ANY_TYPE, error);
|
||||
|
||||
if (field) {
|
||||
if (index < field->CountItems()) {
|
||||
if (field->CountItems() == 1)
|
||||
RemoveName(name);
|
||||
else
|
||||
field->RemoveItem(index);
|
||||
} else
|
||||
error = B_BAD_INDEX;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageBody::RemoveName(const char *name)
|
||||
{
|
||||
status_t error = B_ERROR;
|
||||
BMessageField *field = FindData(name, B_ANY_TYPE, error);
|
||||
|
||||
if (!field)
|
||||
return error;
|
||||
|
||||
fFieldList.RemoveItem(field);
|
||||
HashRemove(name);
|
||||
field->MakeEmpty();
|
||||
field->RemoveSelf();
|
||||
delete field;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageBody::MakeEmpty()
|
||||
{
|
||||
for (int32 index = 0; index < fFieldList.CountItems(); index++) {
|
||||
BMessageField *field = (BMessageField *)fFieldList.ItemAt(index);
|
||||
field->MakeEmpty();
|
||||
delete field;
|
||||
}
|
||||
|
||||
fFieldList.MakeEmpty();
|
||||
|
||||
free(fFlatBuffer);
|
||||
fFlatBuffer = NULL;
|
||||
fFlatLength = 0;
|
||||
fFlatAllocated = 0;
|
||||
|
||||
HashClear();
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BMessageBody::HasData(const char *name, type_code type, int32 index) const
|
||||
{
|
||||
if (!name || index < 0)
|
||||
return false;
|
||||
|
||||
status_t error = B_ERROR;
|
||||
BMessageField *field = FindData(name, type, error);
|
||||
|
||||
if (!field)
|
||||
return false;
|
||||
|
||||
if (index >= field->CountItems())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageBody::FindData(const char *name, type_code type, int32 index,
|
||||
const void **data, ssize_t *numBytes) const
|
||||
{
|
||||
if (!data)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
status_t error = B_ERROR;
|
||||
*data = NULL;
|
||||
|
||||
BMessageField *field = FindData(name, type, error);
|
||||
if (error >= B_OK) {
|
||||
if (index >= field->CountItems())
|
||||
return B_BAD_INDEX;
|
||||
|
||||
*data = field->ItemAt(index, numBytes);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
BMessageField *
|
||||
BMessageBody::FindData(const char *name, type_code type, status_t &error) const
|
||||
{
|
||||
if (!name) {
|
||||
error = B_BAD_VALUE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BMessageField *field = HashLookup(name);
|
||||
|
||||
if (field) {
|
||||
if (type != B_ANY_TYPE && field->Type() != type) {
|
||||
error = B_BAD_TYPE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
error = B_OK;
|
||||
return field;
|
||||
}
|
||||
|
||||
error = B_NAME_NOT_FOUND;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BMessageBody::FlatResize(int32 newSize)
|
||||
{
|
||||
int32 newLength = (newSize + fBlockSize - 1) / fBlockSize * fBlockSize;
|
||||
if (newLength != fFlatAllocated) {
|
||||
fFlatBuffer = (uint8 *)realloc(fFlatBuffer, newLength);
|
||||
if (newLength > fFlatAllocated)
|
||||
memset(fFlatBuffer + fFlatAllocated, 0, newLength - fFlatAllocated);
|
||||
fFlatAllocated = newLength;
|
||||
}
|
||||
|
||||
fFlatLength = newSize;
|
||||
}
|
||||
|
||||
|
||||
uint8 *
|
||||
BMessageBody::FlatInsert(int32 offset, ssize_t oldLength, ssize_t newLength)
|
||||
{
|
||||
if (oldLength == newLength)
|
||||
return FlatBuffer() + offset;
|
||||
|
||||
ssize_t change = newLength - oldLength;
|
||||
ssize_t bufferLength = fFlatLength;
|
||||
|
||||
if (change > 0) {
|
||||
FlatResize(bufferLength + change);
|
||||
|
||||
// usual case for adds
|
||||
if (offset == bufferLength)
|
||||
return FlatBuffer() + offset;
|
||||
}
|
||||
|
||||
ssize_t length = bufferLength - offset - oldLength;
|
||||
if (length > 0) {
|
||||
uint8 *location = FlatBuffer() + offset;
|
||||
memmove(location + newLength, location + oldLength, length);
|
||||
}
|
||||
|
||||
if (change < 0)
|
||||
FlatResize(bufferLength + change);
|
||||
|
||||
for (int32 index = fFieldList.CountItems() - 1; index >= 0; index--) {
|
||||
BMessageField *field = (BMessageField *)fFieldList.ItemAt(index);
|
||||
if (field->Offset() <= offset)
|
||||
break;
|
||||
|
||||
field->SetOffset(field->Offset() + change);
|
||||
}
|
||||
|
||||
return FlatBuffer() + offset;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BMessageBody::HashInsert(BMessageField *field)
|
||||
{
|
||||
uint32 index = HashString(field->Name()) % fFieldTableSize;
|
||||
field->SetNext(fFieldTable[index]);
|
||||
fFieldTable[index] = field;
|
||||
}
|
||||
|
||||
|
||||
BMessageField *
|
||||
BMessageBody::HashLookup(const char *name) const
|
||||
{
|
||||
uint32 index = HashString(name) % fFieldTableSize;
|
||||
BMessageField *result = fFieldTable[index];
|
||||
|
||||
while (result) {
|
||||
if (strcmp(result->Name(), name) == 0)
|
||||
return result;
|
||||
|
||||
result = result->Next();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
BMessageField *
|
||||
BMessageBody::HashRemove(const char *name)
|
||||
{
|
||||
uint32 index = HashString(name) % fFieldTableSize;
|
||||
BMessageField *result = fFieldTable[index];
|
||||
BMessageField *last = NULL;
|
||||
|
||||
while (result) {
|
||||
if (strcmp(result->Name(), name) == 0) {
|
||||
if (last)
|
||||
last->SetNext(result->Next());
|
||||
else
|
||||
fFieldTable[index] = result->Next();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
last = result;
|
||||
result = result->Next();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BMessageBody::HashClear()
|
||||
{
|
||||
memset(fFieldTable, 0, fFieldTableSize * sizeof(BMessageField *));
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
BMessageBody::HashString(const char *string) const
|
||||
{
|
||||
char ch;
|
||||
uint32 result = 0;
|
||||
|
||||
while ((ch = *string++) != 0) {
|
||||
result = (result << 7) ^ (result >> 24);
|
||||
result ^= ch;
|
||||
}
|
||||
|
||||
result ^= result << 12;
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace BPrivate
|
||||
@@ -1,348 +0,0 @@
|
||||
/*
|
||||
* Copyright 2005, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <[email protected]>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <TypeConstants.h>
|
||||
#include "MessageField2.h"
|
||||
#include "MessageUtils2.h"
|
||||
|
||||
namespace BPrivate {
|
||||
|
||||
inline int32
|
||||
round_to_8(int32 length)
|
||||
{
|
||||
// already includes the + 4 for size_t length field
|
||||
return (length + 11) & ~7;
|
||||
}
|
||||
|
||||
|
||||
BMessageField::BMessageField()
|
||||
: fItemSize(0),
|
||||
fOffsets(NULL),
|
||||
fNext(NULL)
|
||||
{
|
||||
ResetHeader("", 0);
|
||||
}
|
||||
|
||||
|
||||
BMessageField::BMessageField(const char *name, type_code type)
|
||||
: fItemSize(0),
|
||||
fOffsets(NULL),
|
||||
fNext(NULL)
|
||||
{
|
||||
ResetHeader(name, type);
|
||||
}
|
||||
|
||||
|
||||
BMessageField::BMessageField(uint8 flags, BDataIO *stream)
|
||||
: fItemSize(0),
|
||||
fOffsets(NULL),
|
||||
fNext(NULL)
|
||||
{
|
||||
Unflatten(flags, stream);
|
||||
}
|
||||
|
||||
|
||||
BMessageField::BMessageField(const BMessageField &other)
|
||||
: fItemSize(0),
|
||||
fOffsets(NULL),
|
||||
fNext(NULL)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
|
||||
BMessageField::~BMessageField()
|
||||
{
|
||||
MakeEmpty();
|
||||
}
|
||||
|
||||
|
||||
BMessageField &
|
||||
BMessageField::operator=(const BMessageField &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
MakeEmpty();
|
||||
fNext = NULL;
|
||||
|
||||
memcpy(&fHeader, &other.fHeader, sizeof(FieldHeader));
|
||||
|
||||
fFlatBuffer.Write(other.fFlatBuffer.Buffer(), other.fFlatBuffer.BufferLength());
|
||||
|
||||
if (other.fOffsets) {
|
||||
int32 count = other.fOffsets->CountItems();
|
||||
fOffsets = new BList(count);
|
||||
|
||||
for (int32 index = 0; index < count; index++)
|
||||
fOffsets->AddItem(other.fOffsets->ItemAt(index));
|
||||
} else {
|
||||
fItemSize = other.fItemSize;
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BMessageField::Flatten(BDataIO *stream)
|
||||
{
|
||||
// write flat header including name
|
||||
stream->Write(&fHeader, sizeof(fHeader) - sizeof(fHeader.name) + fHeader.nameLength);
|
||||
|
||||
// write flat data
|
||||
stream->Write(fFlatBuffer.Buffer(), fHeader.dataSize);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BMessageField::Unflatten(uint8 flags, BDataIO *stream)
|
||||
{
|
||||
TReadHelper reader(stream);
|
||||
|
||||
// read the header
|
||||
if (flags == MSG_FLAG_VALID
|
||||
|| flags == MSG_FLAG_VALID | MSG_FLAG_FIXED_SIZE) {
|
||||
// we can read the header as flat data
|
||||
fHeader.flags = flags;
|
||||
stream->Read(&fHeader.type, sizeof(fHeader) - sizeof(fHeader.flags) - sizeof(fHeader.name));
|
||||
stream->Read(&fHeader.name, fHeader.nameLength);
|
||||
fItemSize = fHeader.dataSize / fHeader.count;
|
||||
} else {
|
||||
// we have to disassemble the header
|
||||
type_code type;
|
||||
reader(type);
|
||||
ResetHeader("", type);
|
||||
|
||||
if (flags & MSG_FLAG_SINGLE_ITEM) {
|
||||
fHeader.count = 1;
|
||||
|
||||
if (flags & MSG_FLAG_MINI_DATA) {
|
||||
uint8 littleData;
|
||||
reader(littleData);
|
||||
fHeader.dataSize = littleData;
|
||||
} else
|
||||
reader(fHeader.dataSize);
|
||||
} else {
|
||||
if (flags & MSG_FLAG_MINI_DATA) {
|
||||
uint8 littleData;
|
||||
reader(littleData);
|
||||
fHeader.count = littleData;
|
||||
|
||||
reader(littleData);
|
||||
fHeader.dataSize = littleData;
|
||||
} else {
|
||||
reader(fHeader.count);
|
||||
reader(fHeader.dataSize);
|
||||
}
|
||||
}
|
||||
|
||||
reader(fHeader.nameLength);
|
||||
reader(fHeader.name, fHeader.nameLength);
|
||||
}
|
||||
|
||||
// now read the data
|
||||
fFlatBuffer.SetSize(fHeader.dataSize);
|
||||
stream->Read((void *)fFlatBuffer.Buffer(), fHeader.dataSize);
|
||||
|
||||
// ToDo: enable swapping
|
||||
// swap the data if necessary
|
||||
if (false) {
|
||||
// is the data fixed size?
|
||||
if (flags & MSG_FLAG_FIXED_SIZE) {
|
||||
// make sure to swap the data
|
||||
status_t status = swap_data(fHeader.type,
|
||||
(void *)fFlatBuffer.Buffer(), fHeader.dataSize, B_SWAP_ALWAYS);
|
||||
if (status < B_OK)
|
||||
throw status;
|
||||
} else if (fHeader.type == B_REF_TYPE) {
|
||||
// apparently, entry_refs are the only variable-length data
|
||||
// explicitely swapped -- the dev_t and ino_t specifically
|
||||
// ToDo: this looks broken
|
||||
byte_swap(*(entry_ref *)fFlatBuffer.Buffer());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BMessageField::ResetHeader(const char *name, type_code type)
|
||||
{
|
||||
memset(&fHeader, 0, sizeof(fHeader));
|
||||
fHeader.flags |= MSG_FLAG_VALID;
|
||||
fHeader.type = type;
|
||||
SetName(name);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BMessageField::MakeEmpty()
|
||||
{
|
||||
fFlatBuffer.SetSize(0);
|
||||
|
||||
if (fOffsets)
|
||||
fOffsets->MakeEmpty();
|
||||
|
||||
fHeader.dataSize = 0;
|
||||
fHeader.count = 0;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageField::SetFixedSize(int32 itemSize, int32 /*count*/)
|
||||
{
|
||||
// ToDo: use count here to preallocate the buffer
|
||||
if (fHeader.count > 0 && itemSize != fItemSize) {
|
||||
debugger("not allowed\n");
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
fItemSize = itemSize;
|
||||
fHeader.flags |= MSG_FLAG_FIXED_SIZE;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BMessageField::SetName(const char *name)
|
||||
{
|
||||
fHeader.nameLength = min_c(strlen(name), 254);
|
||||
memcpy(fHeader.name, name, fHeader.nameLength);
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
BMessageField::AddItem(size_t length)
|
||||
{
|
||||
fHeader.count++;
|
||||
|
||||
int32 offset = fFlatBuffer.BufferLength();
|
||||
if (fHeader.flags & MSG_FLAG_FIXED_SIZE) {
|
||||
fHeader.dataSize += length;
|
||||
fFlatBuffer.SetSize(offset + length);
|
||||
return (char *)fFlatBuffer.Buffer() + offset;
|
||||
}
|
||||
|
||||
if (!fOffsets)
|
||||
fOffsets = new BList();
|
||||
|
||||
fOffsets->AddItem((void *)offset);
|
||||
|
||||
size_t newLength = round_to_8(length);
|
||||
fHeader.dataSize += newLength;
|
||||
FlatResize(offset, 0, newLength);
|
||||
fFlatBuffer.WriteAt(offset, &length, sizeof(length));
|
||||
return (char *)fFlatBuffer.Buffer() + offset + sizeof(newLength);
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
BMessageField::ReplaceItem(int32 index, size_t newLength)
|
||||
{
|
||||
if (fHeader.flags & MSG_FLAG_FIXED_SIZE)
|
||||
return (char *)fFlatBuffer.Buffer() + (index * fItemSize);
|
||||
|
||||
int32 offset = (int32)fOffsets->ItemAt(index);
|
||||
|
||||
size_t oldLength;
|
||||
fFlatBuffer.ReadAt(offset, &oldLength, sizeof(oldLength));
|
||||
fFlatBuffer.WriteAt(offset, &newLength, sizeof(newLength));
|
||||
|
||||
oldLength = round_to_8(oldLength);
|
||||
newLength = round_to_8(newLength);
|
||||
|
||||
if (oldLength == newLength)
|
||||
return (char *)fFlatBuffer.Buffer() + offset + sizeof(newLength);
|
||||
|
||||
FlatResize(offset, oldLength, newLength);
|
||||
fHeader.dataSize += newLength - oldLength;
|
||||
|
||||
return (char *)fFlatBuffer.Buffer() + offset + sizeof(newLength);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BMessageField::RemoveItem(int32 index)
|
||||
{
|
||||
fHeader.count--;
|
||||
|
||||
if (fHeader.flags & MSG_FLAG_FIXED_SIZE) {
|
||||
FlatResize(index * fItemSize, fItemSize, 0);
|
||||
fHeader.dataSize -= fItemSize;
|
||||
return;
|
||||
}
|
||||
|
||||
size_t oldLength;
|
||||
int32 offset = (int32)fOffsets->ItemAt(index);
|
||||
fFlatBuffer.ReadAt(offset, &oldLength, sizeof(oldLength));
|
||||
oldLength = round_to_8(oldLength);
|
||||
|
||||
FlatResize(offset, oldLength, 0);
|
||||
fHeader.dataSize -= oldLength;
|
||||
}
|
||||
|
||||
|
||||
const void *
|
||||
BMessageField::BufferAt(int32 index, ssize_t *size) const
|
||||
{
|
||||
if (fHeader.flags & MSG_FLAG_FIXED_SIZE) {
|
||||
if (size)
|
||||
*size = fItemSize;
|
||||
|
||||
return (char *)fFlatBuffer.Buffer() + (index * fItemSize);
|
||||
}
|
||||
|
||||
int32 offset = (int32)fOffsets->ItemAt(index);
|
||||
if (size)
|
||||
fFlatBuffer.ReadAt(offset, size, sizeof(ssize_t));
|
||||
|
||||
return (char *)fFlatBuffer.Buffer() + offset + sizeof(ssize_t);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BMessageField::PrintToStream() const
|
||||
{
|
||||
// ToDo: implement
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BMessageField::FlatResize(int32 offset, size_t oldLength, size_t newLength)
|
||||
{
|
||||
ssize_t change = newLength - oldLength;
|
||||
ssize_t bufferLength = fFlatBuffer.BufferLength();
|
||||
|
||||
if (change > 0)
|
||||
fFlatBuffer.SetSize(bufferLength + change);
|
||||
|
||||
if (offset == bufferLength) {
|
||||
// the easy case for adds
|
||||
return;
|
||||
}
|
||||
|
||||
ssize_t length = bufferLength - offset - oldLength;
|
||||
if (length > 0) {
|
||||
uint8 *location = (uint8 *)fFlatBuffer.Buffer() + offset;
|
||||
memmove(location + newLength, location + oldLength, length);
|
||||
}
|
||||
|
||||
if (change < 0)
|
||||
fFlatBuffer.SetSize(bufferLength + change);
|
||||
|
||||
for (int32 index = fOffsets->CountItems() - 1; index >= 0; index--) {
|
||||
int32 oldOffset = (int32)fOffsets->ItemAt(index);
|
||||
if (oldOffset <= offset)
|
||||
break;
|
||||
|
||||
fOffsets->ReplaceItem(index, (void *)(offset + change));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace BPrivate
|
||||
@@ -1,281 +0,0 @@
|
||||
/*
|
||||
* Copyright 2005, Haiku.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Michael Lotz <[email protected]>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <DataIO.h>
|
||||
#include <MessageUtils.h>
|
||||
#include "MessageBody3.h"
|
||||
#include "MessageField3.h"
|
||||
|
||||
namespace BPrivate {
|
||||
|
||||
#define DATA_OFFSET (fOffset + fDataOffset)
|
||||
|
||||
inline int32
|
||||
round_to_8(int32 length)
|
||||
{
|
||||
// already includes the + 4 for size_t length field
|
||||
return (length + 11) & ~7;
|
||||
}
|
||||
|
||||
|
||||
BMessageField::BMessageField(BMessageBody *parent, int32 offset,
|
||||
const char *name, type_code type)
|
||||
: fParent(parent),
|
||||
fOffset(offset),
|
||||
fDataOffset(0),
|
||||
fFixedSize(false),
|
||||
fItemSize(0),
|
||||
fItemInfos(5),
|
||||
fNext(NULL)
|
||||
{
|
||||
// insert space needed for the header
|
||||
fParent->FlatInsert(fOffset, 0, sizeof(FieldHeader));
|
||||
|
||||
// fill the header
|
||||
FieldHeader *header = Header();
|
||||
header->type = type;
|
||||
header->flags = MSG_FLAG_VALID;
|
||||
header->count = 0;
|
||||
header->dataSize = 0;
|
||||
header->nameLength = 0;
|
||||
|
||||
SetName(name);
|
||||
}
|
||||
|
||||
|
||||
BMessageField::BMessageField(BMessageBody *parent)
|
||||
: fParent(parent),
|
||||
fOffset(0),
|
||||
fDataOffset(0),
|
||||
fFixedSize(false),
|
||||
fItemSize(0),
|
||||
fItemInfos(5),
|
||||
fNext(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
BMessageField::Unflatten(int32 _offset)
|
||||
{
|
||||
fOffset = _offset;
|
||||
|
||||
// field is already present, just tap into it
|
||||
FieldHeader *header = Header();
|
||||
fDataOffset = sizeof(FieldHeader) + header->nameLength;
|
||||
fFixedSize = header->flags & MSG_FLAG_FIXED_SIZE;
|
||||
|
||||
if (fFixedSize) {
|
||||
if (header->count > 0)
|
||||
fItemSize = header->dataSize / header->count;
|
||||
return fDataOffset + header->count * fItemSize;
|
||||
}
|
||||
|
||||
// create the item info list
|
||||
int32 offset = 0;
|
||||
uint8 *location = fParent->FlatBuffer() + DATA_OFFSET;
|
||||
for (int32 index = 0; index < header->count; index++) {
|
||||
ItemInfo *info = new ItemInfo(offset);
|
||||
info->length = *(size_t *)location;
|
||||
info->paddedLength = round_to_8(info->length);
|
||||
fItemInfos.AddItem(info);
|
||||
|
||||
offset += info->paddedLength;
|
||||
location += info->paddedLength;
|
||||
}
|
||||
|
||||
return fDataOffset + offset;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BMessageField::SetName(const char *newName)
|
||||
{
|
||||
int32 newLength = min_c(strlen(newName), B_FIELD_NAME_LENGTH - 1) + 1;
|
||||
char *buffer = (char *)fParent->FlatInsert(fOffset + sizeof(FieldHeader),
|
||||
Header()->nameLength, newLength);
|
||||
|
||||
strncpy(buffer, newName, newLength - 1);
|
||||
buffer[newLength - 1] = 0;
|
||||
|
||||
Header()->nameLength = newLength;
|
||||
fDataOffset = sizeof(FieldHeader) + newLength;
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
BMessageField::Name() const
|
||||
{
|
||||
return (const char *)(fParent->FlatBuffer() + fOffset + sizeof(FieldHeader));
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BMessageField::SetFixedSize(int32 itemSize)
|
||||
{
|
||||
if (fItemInfos.CountItems() > 0
|
||||
&& (fItemSize > 0 && fItemSize != itemSize))
|
||||
return B_BAD_VALUE;
|
||||
|
||||
fItemSize = itemSize;
|
||||
Header()->flags |= MSG_FLAG_FIXED_SIZE;
|
||||
fFixedSize = true;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BMessageField::AddItem(const void *item, ssize_t length)
|
||||
{
|
||||
memcpy(AddItem(length), item, length);
|
||||
}
|
||||
|
||||
|
||||
uint8 *
|
||||
BMessageField::AddItem(ssize_t length)
|
||||
{
|
||||
FieldHeader *header = Header();
|
||||
|
||||
if (fFixedSize) {
|
||||
int32 offset = DATA_OFFSET + (header->count * fItemSize);
|
||||
header->dataSize += fItemSize;
|
||||
header->count++;
|
||||
return fParent->FlatInsert(offset, 0, fItemSize);
|
||||
}
|
||||
|
||||
int32 newOffset = 0;
|
||||
if (header->count > 0) {
|
||||
ItemInfo *info = (ItemInfo *)fItemInfos.ItemAt(header->count - 1);
|
||||
newOffset = info->offset + info->paddedLength;
|
||||
}
|
||||
|
||||
ItemInfo *newInfo = new ItemInfo(newOffset, length);
|
||||
newInfo->paddedLength = round_to_8(length);
|
||||
|
||||
fItemInfos.AddItem(newInfo);
|
||||
header->dataSize += newInfo->paddedLength;
|
||||
header->count++;
|
||||
|
||||
uint8 *result = fParent->FlatInsert(DATA_OFFSET + newInfo->offset, 0, newInfo->paddedLength);
|
||||
*(int32 *)result = length;
|
||||
return result + sizeof(int32);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BMessageField::ReplaceItem(int32 index, const void *newItem, ssize_t length)
|
||||
{
|
||||
memcpy(ReplaceItem(index, length), newItem, length);
|
||||
}
|
||||
|
||||
|
||||
uint8 *
|
||||
BMessageField::ReplaceItem(int32 index, ssize_t length)
|
||||
{
|
||||
if (fFixedSize)
|
||||
return fParent->FlatBuffer() + DATA_OFFSET + (index * fItemSize);
|
||||
|
||||
ItemInfo *info = (ItemInfo *)fItemInfos.ItemAt(index);
|
||||
int32 newLength = round_to_8(length);
|
||||
|
||||
if (info->paddedLength == newLength) {
|
||||
uint8 *result = fParent->FlatBuffer() + DATA_OFFSET + info->offset;
|
||||
info->length = length;
|
||||
*(int32 *)result = length;
|
||||
return result + sizeof(int32);
|
||||
}
|
||||
|
||||
FieldHeader *header = Header();
|
||||
int32 change = newLength - info->paddedLength;
|
||||
for (int32 i = index + 1; i < header->count; i++)
|
||||
((ItemInfo *)fItemInfos.ItemAt(i))->offset += change;
|
||||
header->dataSize += change;
|
||||
|
||||
int32 oldLength = info->paddedLength;
|
||||
info->length = length;
|
||||
info->paddedLength = newLength;
|
||||
|
||||
uint8 *result = fParent->FlatInsert(DATA_OFFSET + info->offset, oldLength, newLength);
|
||||
*(int32 *)result = length;
|
||||
return result + sizeof(int32);
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
BMessageField::ItemAt(int32 index, ssize_t *size)
|
||||
{
|
||||
if (fFixedSize) {
|
||||
if (size)
|
||||
*size = fItemSize;
|
||||
|
||||
return fParent->FlatBuffer() + DATA_OFFSET + (index * fItemSize);
|
||||
}
|
||||
|
||||
ItemInfo *info = (ItemInfo *)fItemInfos.ItemAt(index);
|
||||
|
||||
if (size)
|
||||
*size = info->length;
|
||||
|
||||
return fParent->FlatBuffer() + DATA_OFFSET + info->offset + sizeof(int32);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BMessageField::RemoveItem(int32 index)
|
||||
{
|
||||
FieldHeader *header = Header();
|
||||
|
||||
if (fFixedSize) {
|
||||
header->count--;
|
||||
header->dataSize -= fItemSize;
|
||||
fParent->FlatInsert(DATA_OFFSET + (index * fItemSize), fItemSize, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
ItemInfo *info = (ItemInfo *)fItemInfos.RemoveItem(index);
|
||||
|
||||
for (int32 i = index; i < header->count; i++)
|
||||
((ItemInfo *)fItemInfos.ItemAt(i))->offset -= info->paddedLength;
|
||||
|
||||
header->count--;
|
||||
header->dataSize -= info->paddedLength;
|
||||
fParent->FlatInsert(DATA_OFFSET + info->offset, info->paddedLength, 0);
|
||||
delete info;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BMessageField::PrintToStream() const
|
||||
{
|
||||
FieldHeader *header = Header();
|
||||
printf("\tname: \"%s\"; items: %ld; dataSize: %ld; flags: %02x; offset: %ld", Name(), header->count, header->dataSize, header->flags, fOffset);
|
||||
// ToDo: implement for real
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BMessageField::MakeEmpty()
|
||||
{
|
||||
for (int32 index = 0; index < fItemInfos.CountItems(); index++)
|
||||
delete (ItemInfo *)fItemInfos.ItemAt(index);
|
||||
|
||||
fItemInfos.MakeEmpty();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BMessageField::RemoveSelf()
|
||||
{
|
||||
// remove ourself from the flat buffer
|
||||
int32 dataSize = Header()->dataSize;
|
||||
fParent->FlatInsert(fOffset, fDataOffset + dataSize, 0);
|
||||
fOffset = 0;
|
||||
}
|
||||
|
||||
} // namespace BPrivate
|
||||
Reference in New Issue
Block a user