BMessage

Derived from: none

Declared in: be/app/Message.h

Library: libbe.so

[method summary]

A BMessage bundles information so that it can be conveyed from one application to another, one thread of execution to another, or even one object to another. Servers use BMessage objects to notify applications about events. An application can use them to communicate with other applications or to initiate activity in a different thread of the same application. In the Interface Kit, BMessages package information that the user can drag from one location on-screen and drop on another. Behind the scenes in the Storage Kit, they convey queries and hand back requested information.

A BMessage is simply a container. The class defines functions that let you put information into a message, determine what kinds of information are present in a message that's been delivered to you, and get the information out. It also has a function that lets you reply to a message once it's received. But it doesn't have functions that can make the initial delivery. For that it depends on the help of other classes in the Application Kit, particularly BLooper and BMessenger. See the "Messaging" section near the beginning of this chapter for an overview of the messaging mechanism and how BMessage objects work with these other classes.

As a data container, a BMessage can be used for purposes other than sending a message. The operating system assigns them at least three other roles:

The clipboard is represented by the BClipboard class, documented in this chapter. Archiving and the BArchivable class are described in the Support Kit. Print settings are outlined for the BPrintJob class, in the Interface Kit.


BMessage Functions

The BMessage class defines five sets of functions:

When data is added to a BMessage, it's associated with a name, a number of bytes, and a type code. The name can be anything you choose, and the number of bytes must be accurate. The type code should permit the message receiver to identify the type of data in the message, so it must be defined as part of a protocol that the sender and receiver both understand. A number of codes for common types are defined in the Support Kit; see "Type Codes" in The Support Kit chapter.


Message Ownership

BMessages always belong to the sender. When a message is received by BHandler::MessageReceived() or by BLooper::DispatchMessage(), these functions should take whatever action they wish in response to the message, but they should never delete the message. Deletion of the message is always the sender's responsibility.


Data Members

uint32 what
A coded constant that captures what the message is about. For example, a message that's delivered to report a mouse-down event will have B_MOUSE_DOWN as its what data member. An application that requests information from another application might put a TRANSMIT_DATA or SEND_INFO command in the what field. A message that's posted as the result of the user clicking a Cancel button might simply have CANCEL as the what data member and include no other information.


Constructor and Destructor


BMessage()

      BMessage(uint32 command) 
      BMessage(BMessage *message) 
      BMessage(const BMessage &message) 
      BMessage(void) 

Assigns command as the new BMessage object's what data member, and ensures that the object otherwise starts out empty. Given the definition of a message constant such as,

   #define RECEIPT_ACKNOWLEDGED  0x80

a complete message can be created as simply as this:

   BMessage msg(RECEIPT_ACKNOWLEDGED);

As a public data member, what can also be set explicitly. The following two lines of code are equivalent to the one above:

   BMessage msg;
   msg.what = RECEIPT_ACKNOWLEDGED;

Other information can be added to the message by calling AddData() or a kindred function.

A BMessage can also be constructed as a copy of another message, or assigned from another message:

   BMessage *differentMsg = new BMessage(QUIT_THAT);
   msg = *differentMsg;

It's necessary to copy any messages you receive that you want to keep, since the thread that receives the message automatically deletes it before getting the next message. (More typically, you'd copy any data you want to save from the message, but not the BMessage itself.)

As an alternative to copying a received message, you can sometimes detach it from the message loop so that it won't be deleted (see DetachCurrentMessage() in the BLooper class).

BMessage objects can be either dynamically allocated with the new operator or statically allocated, as shown in the examples above.

When posting or sending a message, or when initiating a drag-and-drop operation, you retain ownership of the BMessage and are responsible for being sure it's destroyed. Stack allocation is therefore often adequate. However, when assigning a BMessage to another object (such as a BInvoker), ownership is transferred with it. Since the object must continue to live after the assigning function returns, dynamic allocation is usually required.

See also: BLooper::DetachCurrentMessage()


~BMessage()

      virtual ~BMessage()

Frees all memory allocated to hold message data. If the message sender is expecting a reply but hasn't received one, a default reply (with B_NO_REPLY as the what data member) is sent before the message is destroyed.

The system retains ownership of the messages it delivers to you. Each message loop routinely deletes delivered BMessages after the application is finished responding to them.


Member Functions


AddData(), AddBool(), AddInt8(), AddInt16(), AddInt32(), AddInt64(), AddFloat(), AddDouble(), AddString(), AddPoint(), AddRect(), AddRef(), AddMessage(), AddMessenger(), AddPointer(), AddFlat()

      status_t AddData(const char *name, type_code type, 
         const void *data, 
         ssize_t numBytes, 
         bool fixedSize = true, 
         int32 numItems = 1)
      status_t AddBool(const char *name, bool aBool)
      status_t AddInt8(const char *name, int8 anInt8)
      status_t AddInt16(const char *name, int16 anInt16)
      status_t AddInt32(const char *name, int32 anInt32)
      status_t AddInt64(const char *name, int64 anInt64)
      status_t AddFloat(const char *name, float aFloat)
      status_t AddDouble(const char *name, double aDouble)
      status_t AddString(const char *name, const char *string)
      status_t AddPoint(const char *name, BPoint point)
      status_t AddRect(const char *name, BRect rect)
      status_t AddRef(const char *name, const entry_ref *ref)
      status_t AddMessage(const char *name, const BMessage *message)
      status_t AddMessenger(const char *name, BMessenger messenger)
      status_t AddPointer(const char *name, const void *pointer)
      status_t AddFlat(const char *name, BFlattenable *object, int32 numItems = 1)

These functions put data in the BMessage. AddData() copies numBytes of data into the object, and assigns the data a name and a type code. It copies whatever the data pointer points to. For example, if you want to add a string of characters to the message, data should be the string pointer (char *). If you want to add only the string pointer, not the characters themselves, data should be a pointer to the pointer (char **). The assigned type must be a specific data type; it should not be B_ANY_TYPE.

Most of the other functions--AddBool(), AddFloat(), AddRect(), and so on--are specialized and simplified variants of AddData(). They each add a particular type of data to the message, ensure its integrity, and register it under the appropriate type code, as tabulated below:

Function Adds type Assigns type code
AddBool() a bool B_BOOL_TYPE
AddInt8() an int8 or uint8 B_INT8_TYPE
AddInt16() an int16 or uint16 B_INT16_TYPE
AddInt32() an int32 or uint32 B_INT32_TYPE
AddInt64() an int64 or uint64 B_INT64_TYPE
AddFloat() a float B_FLOAT_TYPE
AddDouble() a double B_DOUBLE_TYPE
AddString() a character string B_STRING_TYPE
AddPoint() a BPoint object B_POINT_TYPE
AddRect() a BRect object B_RECT_TYPE
AddRef() an entry_ref B_REF_TYPE
AddMessage() a BMessage object B_MESSAGE_TYPE
AddMessenger() a BMessenger object B_MESSENGER_TYPE
AddPointer() a pointer to anything B_POINTER_TYPE

Each of these type-specific functions calculates the number of bytes in the data they add. AddString(), like AddData(), takes a pointer to the data it adds. The string must be null-terminated; the null character is counted and copied into the message. Similarly, AddRef() adds the pointed to entry_ref structure to the message (and the variable-length name that's one of the elements of the structure); AddMessage() adds one BMessage to another.

The other functions are simply passed the data directly. For example, AddInt32() takes an int32 or uint32 and AddMessenger() takes a BMessenger object, whereas AddData() would be passed a pointer to an int32 and a pointer to a BMessenger. AddPointer() adds only the pointer it's passed, not the data it points to. To accomplish the same thing, AddData() would take a pointer to the pointer. (The pointer will be valid only locally; it won't be useful to a remote destination.)

AddFlat() flattens an object (by calling its Flatten() function) and adds the flat data to the message. It calls the object's TypeCode() function to learn the type code it should associate with the data. FindFlat() will reverse this process and restore the object to its unflat form. The BFlattenable protocol is documented in the Support Kit.

Names of data can be arbitrarily assigned, but a name can't be more than 255 characters long.

If more than one item of data is added under the same name, the BMessage creates an array of data for that name. Each successive call appends another data element to the end of the array. For example, the following code creates an array named "primes" with 37 stored at index 0, 223 stored at index 1, and 1,049 stored at index 2.

   BMessage *msg = new BMessage(NUMBERS);
   int32 x = 37;
   int32 y = 223;
   int32 z = 1049;
   
   msg->AddInt32("primes", x);
   msg->AddFloat("pi", 3.1416);
   msg->AddInt32("primes", y);
   msg->AddData("primes", B_INT32_TYPE, &z, sizeof(int32));

Note that entering other data between some of the elements of an array--in this case, "pi"--doesn't increment the array index.

All elements in a named array must be of the same type; it's an error to try to mix types under the same name.

When you call AddData() to place the first item in an array under a new name, you can provide it with two arguments, fixedSize and numItems, that will improve the object's efficiency when it adds subsequent items to the array. If the fixedSize flag is true, each item in the array must have the same number of bytes; if the flag is false, items can vary in size. For example, all items in an array of integers will be the same size, but the items in an array of strings are likely to have differing lengths. AddData() takes the numItems argument as a hint, an indication of how many items will be added to the array. It can more economically allocate memory for the items if it can anticipate how many there will be.

When adding subsequent items to the array, AddData() ignores the fixedSize and numItems arguments; they're relevant only when the array is first established. You can call AddData() with these arguments to provide the necessary hints when setting up the array, then call other functions to add more items.

You can also provide a numItems hint to AddFlat() when you call it to set up a new array. AddFlat() calls the object's IsFixedSize() function to discover whether all items in the array will be the same size.

These functions return B_ERROR if the data is too massive to be added to the message, B_BAD_TYPE if the data can't be added to an existing array because it's the wrong type, B_NO_MEMORY if the BMessage can't get enough memory to hold the data, and B_BAD_VALUE if the proposed name for the data is longer than 255 bytes. If all goes well, they return B_OK.

There's no limit on the number of named fields a message can contain or on the size of a field's data. However, since the search is linear, combing through a very long list of names to find a particular piece of data may be inefficient. Also, because of the amount of data that must be moved, an extremely large message (over 100,000 bytes, say) can slow the delivery mechanism. It's sometimes better to put some of the information in a common location (a file, a private clipboard, a shared area of memory) and just refer to it in the message. Sometimes later messages can be used to arrange for the transfer of data if the message receiver requires it.

See also: FindData(), GetInfo()


AddSpecifier()

      status_t AddSpecifier(const BMessage *message)
      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)

Adds a specifier to the specifier stack. There are several variations of this method. The first adds the specifier message to the specifier stack. The other methods add a specifier targeting the property property, with specifier constants B_DIRECT_SPECIFIER, B_INDEX_SPECIFIER, B_RANGE_SPECIFIER, and B_NAME_SPECIFIER, respectively. For all other specifiers, you must construct the specifier separately and then call AddSpecifier() on the message. For more information about specifiers, see the "Scripting" section near the beginning of this chapter.

Specifiers are stored in a data array named "specifiers." However, since AddSpecifier() also sets the notion of the current specifier, specifiers should always be added to a scripting message with this method rather than with AddMessage().

AddSpecifier() returns B_OK if it's able to add the specifier to the BMessage and an error code, generally only B_NO_MEMORY to indicate that it has run out of memory, if not.

See also: GetCurrentSpecifier(), HasSpecifiers(), PopSpecifier()


CountNames()

      int32 CountNames(type_code type) const

Returns the number of named data fields in the BMessage that store data of the specified type. An array of information held under a single name counts as one field; each name is counted only once, no matter how many data items are stored under that name.

If type is B_ANY_TYPE, this function counts all named fields. If type is a specific type, it counts only fields that store data registered as that type.

See also: GetInfo()


DropPoint() see WasDropped()


FindData(), FindBool(), FintInt8(), FindInt16(), FindInt32(), FindInt64(), FindFloat(), FindDouble(), FindString(), FindPoint(), FindRect(), FindRef(), FindMessage(), FindMessenger(), FindPointer(), FindFlat()

      status_t FindData(const char *name, 
         type_code type, 
         int32 index, 
         const void **data, 
         ssize_t *numBytes) const
      status_t FindData(const char *name, 
         type_code type, 
         const void **data, 
         ssize_t *numBytes) const
      status_t FindBool(const char *name, 
         int32 index, 
         bool *aBool) const
      status_t FindBool(const char *name, bool *aBool) const
      bool FindBool(const char *name, int32 index = 0) const
      status_t FindInt8(const char *name, 
         int32 index, 
         int8 *anInt8) const
      status_t FindInt8(const char *name, 
         int8 *anInt8) const
      status_t FindInt16(const char *name, 
         int32 index, 
         int16 *anInt16) const
      status_t FindInt16(const char *name, int16 *anInt16) const
      int16 FindInt16(const char *name, int32 index = 0) const
      status_t FindInt32(const char *name, 
         int32 index, 
         int32 *anInt32) const
      status_t FindInt32(const char *name, int32 *anInt32) const
      int32 FindInt32(const char *name, int32 index = 0) const
      status_t FindInt64(const char *name, 
         int32 index, 
         int64 *anInt64) const
      status_t FindInt64(const char *name, int64 *anInt64) const
      status_t FindFloat(const char *name, 
         int32 index, 
         float *aFloat) const
      status_t FindFloat(const char *name, float *aFloat) const
      float FindFloat(const char *name, int32 index = 0) const
      status_t FindDouble(const char *name, 
         int32 index, 
         double *aDouble) const
      status_t FindDouble(const char *name, double *aDouble) const
      double FindDouble(const char *name, int32 index = 0) const
      status_t FindString(const char *name, 
         int32 index, 
         const char **string) const
      status_t FindString(const char *name, const char **string) const
      const char *FindString(const char *name, int32 index = 0) const
      status_t FindPoint(const char *name, 
         int32 index, 
         BPoint *point) const
      status_t FindPoint(const char *name, BPoint *point) const
      BPoint FindPoint(const char *name, int32 index = 0) const
      int32 FindRect(const char *name, 
         int32 index, 
         BRect *rect) const
      int32 FindRect(const char *name, BRect *rect) const
      BRect FindRect(const char *name, int32 index = 0) const
      status_t FindRef(const char *name, 
         int32 index, 
         entry_ref *ref) const
      status_t FindRef(const char *name, entry_ref *ref) const
      status_t FindMessage(const char *name, 
         int32 index, 
         BMessage *message) const
      status_t FindMessage(const char *name, BMessage *message) const
      status_t FindMessenger(const char *name, 
         int32 index, 
         BMessenger *messenger) const
      status_t FindMessenger(const char *name, BMessenger *messenger) const
      status_t FindPointer(const char *name, 
         int32 index, 
         void **pointer) const
      status_t FindPointer(const char *name, void **pointer) const
      status_t FindFlat(const char *name, 
         int32 index, 
         BFlattenable *object) const
      status_t FindFlat(const char *name, BFlattenable *object) const

These functions retrieve data from the BMessage. Each looks for data stored under the specified name. If more than one data item has the same name, an index can be provided to tell the function which item in the name array it should find. Indices begin at 0. If an index isn't provided, the function will find the first, or only, item in the array.

FindData() places a pointer to the requested data item in the variable referred to by data and records the size of the item (the number of bytes it takes up) in the variable referred to by numBytes. It asks for data of a specified type. If the type is B_ANY_TYPE, it provides a pointer to the data no matter what type it actually is. But if type is a specific data type, it provides the pointer only if the name field holds data of that particular type.

It's important to keep in mind that FindData() only gives you a pointer to the data, never the data itself. If the data is a pointer--for example, a pointer to an object--it provides a pointer to the pointer. The variable that's assigned the returned pointer must be doubly indirect. For example:

   MyClass **object;
   ssize_t numBytes;
   if ( !msg->FindData("name", B_POINTER_TYPE, &object, &numBytes) )
       (*object)->GetSomeInformation();
       . . .
   }

The other functions are specialized versions of FindData(). They match the corresponding Add...() functions and search for named data of a particular type, as described below:

Function Finds data Registered as type
FindBool() a bool B_BOOL_TYPE
FindInt8() an int8 or uint8 B_INT8_TYPE
FindInt16() an int16 or uint16 B_INT16_TYPE
FindInt32() an int32 or uint32 B_INT32_TYPE
FindInt64() an int64 or uint64 B_INT64_TYPE
FindFloat() a float B_FLOAT_TYPE
FindDouble) a double B_DOUBLE_TYPE
FindString() a character string B_STRING_TYPE
FindPoint() a BPoint object B_POINT_TYPE
FindRect() a BRect object B_RECT_TYPE
FindRef() an entry_ref B_REF_TYPE
FindMessage() a BMessage object B_MESSAGE_TYPE
FindMessenger() a BMessenger object B_MESSENGER_TYPE
FindPointer() a pointer to anything B_POINTER_TYPE

FindString() works like FindData(); it places a pointer to the string in the variable that its string argument refers to. You have to copy the characters yourself.

The other type-specific functions retrieve the requested data item from the message by copying it to the variable referred to by the last argument; you get the data, not just a pointer to it. For example, FindMessenger() assigns the BMessenger it finds in the message to the messenger object, whereas FindData() would provide only a pointer to a BMessenger. FindPointer() puts the found pointer in the void* variable that pointer refers to; FindData(), as illustrated above, would provide a pointer to the pointer. (If the message was delivered from a remote source, pointers retrieved from the message won't be valid.)

FindRef() retrieves an entry_ref structure; the data that's used to reconstitute the structure may have been added as an entry_ref (through AddRef()), or as a flattened BPath object (AddFlat()).

FindFlat() assigns the object stored in the BMessage to the object passed as an argument--it calls the object's Unflatten() function and passes it the flat data from the message--provided that the two objects have compatible types. The argument object's AllowsTypeCode() function must return true when tested with the type code stored in the message; if not, FindFlat() fails and returns B_BAD_VALUE.

If these functions can't find any data associated with name, they return a B_NAME_NOT_FOUND error. If they can't find name data of the requested type (or the type the function returns), they return B_BAD_TYPE. If the index is out of range, they return B_BAD_INDEX. You can rely on the values they retrieve only if they return B_OK and the data was correctly recorded when it was added to the message.

When they fail, FindData() and FindString() provide NULL pointers. FindRect() hands you an invalid rectangle and FindMessenger() an invalid BMessenger. Most of the other functions set the data values to 0, which may be indistinguishable from valid values.

Finding a data item doesn't remove it from the BMessage.

(Several functions, such as FindRect() and FindInt32(), have versions that return the found value directly. These versions don't report errors and may not be supported in the future.)

See also: GetInfo(), AddData()


Flatten(), Unflatten(), FlattenedSize()

      status_t Flatten(BDataIO *object, ssize_t *outNumBytes = NULL) const
      status_t Flatten(char *address, ssize_t bufferSize = 0) const
      status_t Unflatten(BDataIO *object)
      status_t Unflatten(const char *address)
      ssize_t FlattenedSize(void) const

These functions write the BMessage and the data it contains to a "flat" (untyped) buffer of bytes, and reconstruct a BMessage object from such a buffer.

If passed a BDataIO object (such as a BFile), Flatten() calls the object's Write() function to write the flattened message data, and returns in outNumBytes the number of bytes written to the object.

If the address of a buffer is passed, it begins writing the flattened data at the first byte of the buffer. You must specify, in bufferSize, the size of the buffer in bytes.

FlattenedSize() returns the number of bytes you must provide in the buffer to hold the flattened object.

Unflatten() empties the BMessage of any information it may happen to contain, then initializes the object from data read from the buffer. If passed a BDataIO object, it calls the object's Read() function to read the message data. If passed a buffer address, it begins reading at the start of the buffer. It's up to the caller to make sure that Unflatten() reads data that Flatten() wrote and that pointers are positioned correctly.

Flatten() returns any errors encountered when writing the data, or B_OK if there is no error.

If it doesn't recognize the data in the buffer as being a flattened object or there's a failure in reading the data, Unflatten() returns B_BAD_VALUE. If it doesn't have adequate memory to recreate the whole message, it returns B_NO_MEMORY. Otherwise, it returns B_OK.

See also: the BDataIO class in the Support Kit


GetCurrentSpecifier(), PopSpecifier()

      status_t GetCurrentSpecifier(int32 *index, 
         BMessage *specifier = NULL, 
         int32 *what = NULL, 
         const char **property = NULL) const
      status_t PopSpecifier(void) 

GetCurrentSpecifier() unpacks the current specifier in the BMessage, the one at the top of the specifier stack; PopSpecifier() changes the notion of which specifier is current, by popping the current one from the stack.

These functions aid in implementing a class-specific version of BHandler's ResolveSpecifier() function--the first gets the specifier that needs to be resolved, and the second pops it from the stack after it is resolved. You can also call them to examine relevant specifiers when handling a message that targets an object property (such as B_GET_PROPERTY).

A scripting BMessage keeps specifiers in a data array named "specifiers"; each specifier is itself a BMessage, but one with a special structure and purpose in the scripting system. See the "Scripting" section near the beginning of this chapter for an overview of the system and the place of specifiers in it.

The specifiers in a message are ordered and, until PopSpecifier() is called, the one that was added last--the one with the greatest index--is the current specifier. PopSpecifier() merely decrements the index that picks the current specifier; it doesn't delete anything from the BMessage.

GetCurrentSpecifier() puts the index of the current specifier in the variable that its first argument, index, refers to. If other arguments are provided, it makes the specifier BMessage a copy of the current specifier. It also extracts two pieces of information from the specifier: It places the what data member of the specifier in the what variable and a pointer to the property name in the property variable. These last two output arguments won't be valid if the specifier argument is NULL.

Both functions fail if the BMessage doesn't contain specifiers. In addition, GetCurrentSpecifier() fails if it can't find data in the BMessage for its specifier and property arguments, and PopSpecifier() fails if the BMessage isn't one that has been delivered to you after being processed through a message loop. When it fails, GetCurrentSpecifier() returns B_BAD_SCRIPT_SYNTAX, but PopSpecifier() returns B_BAD_VALUE. On success, both functions return B_OK.

See also: AddSpecifier(), HasSpecifiers(), BHandler::ResolveSpecifier()


GetInfo()

      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
      status_t GetInfo(type_code type, int32 index,
         char **nameFound,
         type_code *typeFound,
         int32 *countFound = NULL) const

Provides information about the data fields stored in the BMessage.

When passed a name that matches a name within the BMessage, GetInfo() places the type code for data stored under that name in the variable referred to by typeFound and writes the number of data items with that name into the variable referred to by countFound. It then returns B_OK. If it can't find a name field within the BMessage, it sets the countFound variable to 0, and returns B_NAME_NOT_FOUND (without modifying the typeFound variable).

When the fixedSize argument is specified, the bool referenced by fixedSize is set to true if all items in the array specified by name must be the same size, and false if the items can be of different sizes (see AddData()).

When passed a type and an index, GetInfo() looks only at fields that store data of the requested type and provides information about the field at the requested index. Indices begin at 0 and are type specific. For example, if the requested type is B_DOUBLE_TYPE and the BMessage contains a total of three named fields that store double data, the first field would be at index 0, the second at 1, and the third at 2--no matter what other types of data actually separate them in the BMessage, and no matter how many data items each field contains. (Note that the index in this case ranges over fields, each with a different name, not over the data items within a particular named field.) If the requested type is B_ANY_TYPE, this function looks at all fields and gets information about the one at index whatever its type.

If successful in finding data of the type requested at index, GetInfo() returns B_OK and provides information about the data through the last three arguments:

If GetInfo() can't find data of the requested type at index, it sets the countFound variable to 0, and returns B_BAD_TYPE. If the index is out of range, it returns B_BAD_INDEX.

This version of GetInfo() can be used to iterate through all the BMessage's data. For example:

   char  *name;
   uint32  type;
   int32   count;
   
   for ( int32 i = 0; 
         msg->GetInfo(B_ANY_TYPE, i, &name, &type, &count) == B_OK;
         i++ ) {
       . . .
   }

If the index is incremented from 0 in this way, all data of the requested type will have been read when GetInfo() returns B_NAME_NOT_FOUND. If the requested type is B_ANY_TYPE, as shown above, it will reveal the name and type of every field in the BMessage.

See also: HasData(), AddData(), FindData()


HasData(), HasBool(), HasInt8(), HasInt16(), HasInt32(), HasInt64(), HasFloat(), HasDouble(), HasString(), HasPoint(), HasRect(), HasRef(), HasMessage(), HasMessenger(), HasPointer()

      bool HasData(const char *name, type_code type, int32 index = 0) const
      bool HasBool(const char *name, int32 index = 0) const
      bool HasInt8(const char *name, int32 index = 0) const
      bool HasInt16(const char *name, int32 index = 0) const
      bool HasInt32(const char *name, int32 index = 0) const
      bool HasInt64(const char *name, int32 index = 0) const
      bool HasFloat(const char *name, int32 index = 0) const
      bool HasDouble(const char *name, int32 index = 0) const
      bool HasString(const char *name, int32 index = 0) const
      bool HasPoint(const char *name, int32 index = 0) const
      bool HasRect(const char *name, int32 index = 0) const
      bool HasRef(const char *name, int32 index = 0) const
      bool HasMessage(const char *name, int32 index = 0) const
      bool HasMessenger(const char *name, int32 index = 0) const
      bool HasPointer(const char *name, int32 index = 0) const

These functions test whether the BMessage contains data of a given name and type. They're generally less useful than the corresponding Find...() functions. If the message contains the data you're looking for, you probably will want to call Find...() to get it. Since the Find...() functions return errors if the message doesn't have data of the requested name and type, it's more efficient to just call Find...() and not bother with Has...(). At any rate, here's how these functions work:

If type is B_ANY_TYPE and no index is provided, HasData() returns true if the BMessage stores any data at all under the specified name, regardless of its type, and false if the name passed doesn't match any within the object.

If type is a particular type code, HasData() returns true only if the BMessage has a name field that stores data of that type. If the type and name don't match, it returns false.

If an index is supplied, HasData() returns true only if the BMessage has a name field that stores a data item of the specified type at that particular index. If the index is out of range, it returns false.

The other functions--HasBool(), HasFloat(), HasPoint(), and so on--are specialized versions of HasData(). They test for a particular type of data stored under the specified name.

See also: GetInfo()


HasSpecifiers()

      bool HasSpecifiers(void) const

Returns true if the BMessage has specifiers added by an AddSpecifier() function, and false if not.

See also: AddSpecifier(), GetCurrentSpecifier()


IsEmpty() see MakeEmpty()


IsReply() see WasDelivered()


IsSourceRemote() see WasDelivered()


IsSourceWaiting() see WasDelivered()


IsSystem()

      bool IsSystem(void) const

Returns true if the what data member of the BMessage object identifies it as a system-defined message, and false if not.


MakeEmpty(), IsEmpty()

      status_t MakeEmpty(void) 
      bool IsEmpty(void) const

MakeEmpty() removes and frees all data that has been added to the BMessage, without altering the what constant. It returns B_OK, unless the message can't be altered (as it can't if it's being dragged), in which case it returns B_ERROR.

IsEmpty() returns true if the BMessage has no data (whether or not it was emptied by MakeEmpty()), and false if it has some.

See also: RemoveName()


Previous() see WasDelivered()


PrintToStream()

      void PrintToStream(void) const

Prints information about the BMessage to the standard output stream (stdout). Each field of named data is reported in the following format,

   #entry name, type = type, count = count

where name is the name that the data is registered under, type is the constant that indicates what type of data it is, and count is the number of data items in the named array.


RemoveName(), RemoveData()

      status_t RemoveName(const char *name)
      status_t RemoveData(const char *name, int32 index = 0)

RemoveName() removes all data entered in the BMessage under name and the name itself. RemoveData() removes the single item of data at index in the name array. If the array has just one data item, it removes the array and name just as RemoveName() would.

Both functions free the memory that was allocated to hold the data, and return B_OK when successful. However, if there's no data in the BMessage under name, they return a B_NAME_NOT_FOUND error. If message data can be read but can't be changed (as it can't for a message that's being dragged), they both return B_ERROR. If the index is out of range, RemoveData() returns B_BAD_INDEX (the index is too high) or B_BAD_VALUE (the value passed is a negative number).

See also: MakeEmpty()


ReplaceData(), ReplaceBool(), ReplaceInt8(), ReplaceInt16(), ReplaceInt32(), ReplaceInt64(), ReplaceFloat(), ReplaceDouble(), ReplaceString(), ReplacePoint(), ReplaceRect(), ReplaceRef(), ReplaceMessage(), ReplaceMessenger(), ReplacePointer(), ReplaceFlat()

      status_t ReplaceData(const char *name, 
         type_code type,
         const void *data, 
         ssize_t numBytes)
      status_t ReplaceData(const char *name, 
         type_code type,
          int32 index,
         const void *data, 
         ssize_t numBytes)
      status_t ReplaceBool(const char *name, bool aBool)
      status_t ReplaceBool(const char *name, 
         int32 index, 
         bool aBool)
      status_t ReplaceInt8(const char *name, int8 anInt8)
      status_t ReplaceInt8(const char *name, 
         int32 index, 
         int8 anInt8)
      status_t ReplaceInt16(const char *name, int16 anInt16)
      status_t ReplaceInt16(const char *name, 
         int32 index, 
         int16 anInt16)
      status_t ReplaceInt32(const char *name, long anInt32)
      status_t ReplaceInt32(const char *name, 
         int32 index, 
         int32 anInt32)
      status_t ReplaceInt64(const char *name, int64 anInt64)
      status_t ReplaceInt64(const char *name, 
         int32 index, 
         int64 anInt64)
      status_t ReplaceFloat(const char *name, float aFloat)
      status_t ReplaceFloat(const char *name, 
         int32 index, 
         float aFloat)
      status_t ReplaceDouble(const char *name, double aDouble)
      status_t ReplaceDouble(const char *name, 
         int32 index, 
         double aDouble)
      status_t ReplaceString(const char *name, const char *string)
      status_t ReplaceString(const char *name, 
         int32 index, 
         const char *string)
      status_t ReplacePoint(const char *name, BPoint point)
      status_t ReplacePoint(const char *name, 
         int32 index, 
         BPoint point)
      status_t ReplaceRect(const char *name, BRect rect)
      status_t ReplaceRect(const char *name, 
         int32 index, 
         BRect rect)
      status_t ReplaceRef(const char *name, entry_ref *ref)
      status_t ReplaceRef(const char *name, 
         int32 index, 
         entry_ref *ref)
      status_t ReplaceMessage(const char *name, BMessage *message)
      status_t ReplaceMessage(const char *name, 
         int32 index, 
         BMessage *message)
      status_t ReplaceMessenger(const char *name, BMessenger messenger)
      status_t ReplaceMessenger(const char *name, 
         int32 index, 
         BMessenger messenger)
      status_t ReplacePointer(const char *name, const void *pointer)
      status_t ReplacePointer(const char *name, 
         int32 index, 
         const void *pointer)
      status_t ReplaceFlat(const char *name, BFlattenable *object)
      status_t ReplaceFlat(const char *name, 
         int32 index, 
         BFlattenable *object)

These functions replace a data item in the name field with another item passed as an argument. If an index is provided, they replace the item in the name array at that index; if an index isn't mentioned, they replace the first (or only) item stored under name. If an index is provided but it's out of range, the replacement fails.

ReplaceData() replaces an item in the name field with numBytes of data, but only if the type code that's specified for the data matches the type of data that's already stored in the field. The type must be specific; it can't be B_ANY_TYPE.

FindFlat() replaces a flattened object with another object, provided that the type reported by the argument object (by its TypeCode() function) matches the type recorded for the item in the message. If not, it returns B_BAD_VALUE.

The other functions are simplified versions of ReplaceData(). They each handle the specific type of data declared for their last arguments. They succeed if this type matches the type of data already in the name field, and fail if it does not. The new data is added precisely as the counterpart Add...() function would add it.

If successful, all these functions return B_OK. If unsuccessful, they return an error code--B_ERROR if the message is read-only (as it is while the message is being dragged), B_BAD_INDEX if the index is out of range, B_NAME_NOT_FOUND if the name field doesn't exist, or B_BAD_TYPE if the field doesn't contain data of the specified type.

See also: AddData()


ReturnAddress()

      BMessenger ReturnAddress(void)

Returns a BMessenger object that can be used to reply to the BMessage. Calling the BMessenger's SendMessage() function is equivalent to calling SendReply(), except that the return message won't be marked as a reply. If a reply isn't allowed (if the BMessage wasn't delivered), the returned BMessenger will be invalid.

If you want to use the ReturnAddress() BMessenger to send a synchronous reply, you must do so before the BMessage is deleted and a default reply is sent.

See also: SendReply(), WasDelivered()


SendReply()

      status_t SendReply(BMessage *message, 
         BMessage *reply, 
         bigtime_t sendTimeout = B_INFINITE_TIMEOUT, 
         bigtime_t replyTimeout = B_INFINITE_TIMEOUT)
      status_t SendReply(BMessage *message, 
         BHandler *replyHandler = NULL, 
         bigtime_t sendTimeout = B_INFINITE_TIMEOUT)
      status_t SendReply(uint32 command, BMessage *reply)
      status_t SendReply(uint32 command, BHandler *replyHandler = NULL)

Sends a reply message back to the sender of the BMessage (in the case of a synchronous reply) or to a target BHandler (in the case of an asynchronous reply). Whether the reply is synchronous or asynchronous depends on how the BMessage that's sending the reply was itself sent:

SendReply() works only for BMessage objects that have been processed through a message loop and delivered to you. The caller retains ownership of the reply message passed to SendReply(); it can be deleted (or left to die on the stack) after the function returns.

SendReply() sends a message--a reply message, to be sure, but a message nonetheless. It behaves exactly like the other message-sending function, BMessenger's SendMessage():

By default, SendReply() doesn't return until the reply message is delivered (placed in the BLooper's port queue). It's possible, in some circumstances, for the receiving port queue to be full, in which case SendReply() will block until a slot becomes free. However, you can limit how long SendReply() will wait to deliver the message before it gives up and returns. The sendTimeout argument is the number of microseconds you give the function to do its work. If the time limit is exceeded, the function fails and returns an error (B_TIMED_OUT).

When asking for a synchronous reply, separate sendTimeout and replyTimeout limits can be set for sending the message and receiving the reply. There is no time limit if a timeout value is set to B_INFINITE_TIMEOUT--as it is by default. The function won't block at all if the timeout is set to 0.

If a command is passed rather than a message, SendReply() constructs the reply BMessage, initializes its what data member with the command constant, and sends it just like any other reply. The command versions of this function have infinite timeouts; they block until the message is delivered and, if requested, a synchronous reply is received.

This function returns B_OK if the reply is successfully sent. If there's a problem in sending the message, it returns the same sort of error code as BMessenger's SendMessage(). It may also report a reply-specific problem. The more informative return values are as follows:

Error code Is returned when
B_BAD_REPLY Attempting to reply to a message that hasn't been delivered yet.
B_DUPLICATE_REPLY Sending a reply after one has already been sent and delivered.
B_BAD_THREAD_ID Sending a reply to a destination thread that no longer exists.
B_BAD_PORT_ID Sending a reply to a BLooper and port that no longer exist.
B_TIMED_OUT Taking longer than the specified time limit to deliver a reply message or to receive a synchronous reply to the reply.

If you want to delay sending a reply and keep the BMessage object beyond the time it's scheduled to be deleted, you may be able to detach it from the message loop. See DetachCurrentMessage() in the BLooper class.

See also: BMessenger::SendMessage(), BLooper::DetachCurrentMessage(), Error, ReturnAddress()


Unflatten() see Flatten()


WasDelivered(), IsSourceRemote(), IsSourceWaiting(), IsReply(), Previous()

      bool WasDelivered(void) const
      bool IsSourceRemote(void) const
      bool IsSourceWaiting(void) const
      bool IsReply(void) const
      const BMessage *Previous(void) const 

These functions can help if you're engaged in an exchange of messages or managing an ongoing communication.

WasDelivered() indicates whether it's possible to send a reply to a message. It returns true for a BMessage that was posted, sent, or dropped--that is, one that has been processed through a message loop--and false for a message that has not yet been delivered by any means.

IsSourceRemote() returns true if the message had its source in another application, and false if the source is local or the message hasn't been delivered yet.

IsSourceWaiting() returns true if the message source is waiting for a synchronous reply, and false if not. The source thread can request and wait for a reply when calling either BMessenger's SendMessage() or BMessage's SendReply() function.

IsReply() returns true if the BMessage is a reply to a previous message (if it was sent by the SendReply() function), and false if not.

Previous() returns the previous message--the message to which the current BMessage is a reply. It works only for a BMessage that's received as an asynchronous reply to a previous message. A synchronous reply is received in the context of the previous message, so it's not necessary to call a function to get it. But when an asynchronous reply is received, the context of the original message is lost; this function can provide it. Previous() returns NULL if the BMessage isn't an asynchronous reply to another message.

See also: BMessenger::SendMessage(), SendReply(), ReturnAddress()


WasDropped(), DropPoint()

      bool WasDropped(void) const
      BPoint DropPoint(BPoint *offset = NULL) const

WasDropped() returns true if the user delivered the BMessage by dragging and dropping it, and false if the message was posted or sent in application code or if it hasn't yet been delivered at all.

DropPoint() reports the point where the cursor was located when the message was dropped (when the user released the mouse button). It directly returns the point in the screen coordinate system and, if an offset argument is provided, returns it by reference in coordinates based on the image or rectangle the user dragged. The offset assumes a coordinate system with (0.0, 0.0) at the left top corner of the dragged rectangle or image.

Since any value can be a valid coordinate, DropPoint() produces reliable results only if WasDropped() returns true.

See also: BView::DragMessage()


Operators


= (assignment)

      BMessage &operator =(const BMessage&)

Assigns one BMessage object to another. After the assignment, the two objects are duplicates of each other without shared data.


new

      void *operator new(size_t numBytes)

Allocates memory for a BMessage object, or takes the memory from a previously allocated cache. The caching mechanism is an efficient way of managing memory for objects that are created frequently and used for short periods of time, as BMessages typically are.


delete

      void operator delete(void *memory, size_t numBytes)

Frees memory allocated by the BMessage version of new, which may mean restoring the memory to the cache.






The Be Book, in lovely HTML, for BeOS Release 4.

Copyright © 1998 Be, Inc. All rights reserved.

Last modified December 11, 1998.