[NeoStats-Devel] [Commits] r2810 - trunk/include
[email protected] Mon, 12 Sep 2005 23:57:42 +1000
| Newsgroups | gmane.comp.neostats.devel |
|---|---|
| Message-ID | <[email protected]> |
Author: Fish
Date: Mon Sep 12 21:57:35 2005
New Revision: 2810
Added:
trunk/include/MiniMessage.h (contents, props changed)
trunk/include/MiniMessageGateway.h (contents, props changed)
trunk/include/MuscleSupport.h (contents, props changed)
Log:
Commit the MiniMessage files
Added: trunk/include/MiniMessage.h
==============================================================================
--- (empty file)
+++ trunk/include/MiniMessage.h Mon Sep 12 21:57:35 2005
@@ -0,0 +1,602 @@
+/* NeoStats - IRC Statistical Services
+** Copyright (c) 1999-2005 Adam Rutter, Justin Hammond, Mark Hetherington
+** http://www.neostats.net/
+**
+** Portions Copyright (c) 2000 - 2001 ^Enigma^
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+** USA
+**
+** NeoStats CVS Identification
+** $Id$
+*/
+
+
+#ifndef MiniMessage_h
+#define MiniMessage_h
+
+#include "MuscleSupport.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* My own little boolean type, since C doesn't come with one built in. */
+typedef char MBool;
+enum {MFalse = 0, MTrue}; /* and boolean values to go in it */
+
+/* This file contains a C API for a "minimalist" implementation of the MUSCLE */
+/* Message dictionary object. This implementation sacrifices a certain amount */
+/* of flexibility and convenience in exchange for a very lightweight */
+/* and efficient implementation. */
+
+/** Definition of our Point class -- two floats */
+struct _MPoint {
+ float x;
+ float y;
+};
+typedef struct _MPoint MPoint;
+
+/** Definition of our Rect class -- four floats */
+struct _MRect {
+ float left;
+ float top;
+ float right;
+ float bottom;
+};
+typedef struct _MRect MRect;
+
+/** Definition of our opaque handle to a MMessage object. Your
+ * code doesn't know what a (MMessage *) points to, and it doesn't care,
+ * because all operations on it should happen via calls to the functions
+ * that are defined below.
+ */
+struct _MMessage;
+typedef struct _MMessage MMessage;
+
+/** This object is used in field name iterations */
+struct _MMessageIterator {
+ const MMessage * message;
+ void * iterState;
+ uint32 typeCode;
+};
+typedef struct _MMessageIterator MMessageIterator;
+
+/** Definition of our byte-array class, including size value */
+struct _MByteBuffer {
+ uint32 numBytes;
+ uint8 bytes; /* Note that this is only the first byte; there are usually more after this one */
+};
+typedef struct _MByteBuffer MByteBuffer;
+
+/** Allocates and initializes a new MByteBuffer with the specified number of bytes, and returns a pointer to it.
+ * @param numBytes How many bytes to allocate in this buffer.
+ * @param clearBytes If MTrue, all the data bytes in the returned MByteBuffer will be zero.
+ * If MFalse, the bytes' values will be undefined (which is a bit more efficient)
+ * @returns a newly allocated MByteBuffer with the specified number of bytes, or NULL on failure.
+ * If non-NULL, it becomes the the responsibility of the calling code to call FreeMByteBuffer()
+ * on the MByteBuffer when it is done using it.
+ */
+MByteBuffer * MBAllocByteBuffer(uint32 numBytes, MBool clearBytes);
+
+/** Allocates and initializes a new MByteBuffer to contain a copy of the specified NUL-terminated string.
+ * @param sourceString The string to copy into the newly allocated byte buffer.
+ * @returns A newly allocated MByteBuffer containing a copy of the specified string, or NULL on failure.
+ * Note that the returned MByteBuffer's string will be NUL-terminated too.
+ */
+MByteBuffer * MBStrdupByteBuffer(const char * sourceString);
+
+/** Attempts to create and return a cloned copy of (cloneMe).
+ * @param cloneMe The MByteBuffer to create a copy of.
+ * @returns The newly allocated MByteBuffer, or NULL on failure.
+ */
+MByteBuffer * MBCloneByteBuffer(const MByteBuffer * cloneMe);
+
+/** Returns MTrue iff the two byte buffers are equal (i.e. both hold the same byte sequence)
+ * @param buf1 The first byte buffer to compare.
+ * @param buf2 The first byte buffer to compare.
+ * @returns True if buf1 has the same byte sequence as buf2, otherwise MFalse.
+ */
+MBool MBAreByteBuffersEqual(const MByteBuffer * buf1, const MByteBuffer * buf2);
+
+/** Frees a previously created MByteBuffer and all the data that it holds.
+ * @param msg The MByteBuffer to free. If NULL, no action will be taken.
+ */
+void MBFreeByteBuffer(MByteBuffer * msg);
+
+/** Allocates and initializes a new MMessage with the specified what code, and returns a pointer to it.
+ * @param what Initial 'what' code to give to the MMessage.
+ * @returns a newly allocated MMessage, or NULL on failure. If non-NULL, it becomes the
+ * the responsibility of the calling code to call MMFreeMessage() on the MMessage
+ * when it is done using it.
+ */
+MMessage * MMAllocMessage(uint32 what);
+
+/** Attempts to create and return a cloned copy of (cloneMe).
+ * @param cloneMe The MMessage to create a copy of.
+ * @returns The newly allocated MMessage, or NULL on failure.
+ */
+MMessage * MMCloneMessage(const MMessage * cloneMe);
+
+/** Frees a previously created MMessage and all the data that it holds.
+ * @param msg The MMessage to free. If NULL, no action will be taken.
+ */
+void MMFreeMessage(MMessage * msg);
+
+/** Returns the 'what' code associated with the specified MMessage.
+ * @param msg The MMessage to retrieve the 'what' code of.'
+ * @returns The MMessage's what code.
+ */
+uint32 MMGetWhat(const MMessage * msg);
+
+/** Sets the 'what' code associated with the specified MMessage.
+ * @param msg The MMessage to set the 'what' code of'.
+ * @param newWhat The new 'what' code to install. (Typically a B_*_TYPE value)
+ */
+void MMSetWhat(MMessage * msg, uint32 newWhat);
+
+/** Removes and frees all of the supplied MMessage's field data. The MMessage itself
+ * is not destroyed, however (use MMFreeMessage() to do that)
+ * @param msg The MMessage object to remove all data fields from.
+ */
+void MMClearMessage(MMessage * msg);
+
+/** Attempts to remove and free the specified field from the given MMessage.
+ * @param msg the MMessage object to remove the field from
+ * @param fieldName Name of the field to remove and free.
+ * @returns B_NO_ERROR if the field was found and removed, or B_ERROR if it wasn't found.
+ */
+status_t MMRemoveField(MMessage * msg, const char * fieldName);
+
+/** Attempts to create and install a string field with the specified field name into the MMessage.
+ * On success, any previously installed field with the same name will be replaced and freed.
+ * @param msg The MMessage to install the new field into.
+ * @param retainOldData This flag is relevant only if a string field with the same name already exists.
+ * If MTrue, as many of the old field's data values as possible will be transferred
+ * to the new field. Otherwise, all the old field's data will be destroyed and the
+ * new field will be created with all NULL string values.
+ * @param fieldName Field name of the new field.
+ * @param numItems Number of items that the new field should contain room for.
+ * @returns A pointer to an array of (numItems) MByteBuffer pointers, or NULL if there was an error.
+ * The returned array belongs to the MMessage, and will be freed by it at the proper time.
+ * The MByteBuffer pointers in the array, when non-NULL, are also considered to belong to the
+ * MMessage, and will have MBFreeByteBuffer() called on them when the field is destroyed.
+ * NOTE: When setting a value in the array, be sure to allocate its memory using MBAllocByteBuffer()
+ * or MBStrdupByteBuffer(), and be sure to call MBFreeByteBuffer() on the old value before
+ * you replace it.
+ */
+MByteBuffer ** MMPutStringField(MMessage * msg, MBool retainOldData, const char * fieldName, uint32 numItems);
+
+/** Attempts to create and install a boolean field with the specified field name into the MMessage.
+ * On success, any previously installed field with the same name will be replaced and freed.
+ * @param msg The MMessage to install the new field into.
+ * @param retainOldData This flag is relevant only if a boolean field with the same name already exists.
+ * If MTrue, as many of the old field's data values as possible will be transferred
+ * to the new field. Otherwise, all the old field's data will be destroyed and the
+ * new field will be created with all data values set to MFalse.
+ * @param fieldName Field name of the new field.
+ * @param numItems Number of items that the new field should contain room for.
+ * @returns A pointer to an array of (numItems) booleans, or NULL if there was an error.
+ * The returned array belongs to the MMessage, and will be freed by it at the proper time.
+ */
+MBool * MMPutBoolField(MMessage * msg, MBool retainOldData, const char * fieldName, uint32 numItems);
+
+/** Attempts to create and install an int8 field with the specified field name into the MMessage.
+ * On success, any previously installed field with the same name will be replaced and freed.
+ * @param msg The MMessage to install the new field into.
+ * @param retainOldData This flag is relevant only if an int8 field with the same name already exists.
+ * If MTrue, as many of the old field's data values as possible will be transferred
+ * to the new field. Otherwise, all the old field's data will be destroyed and the
+ * new field will be created with all zero data values.
+ * @param fieldName Field name of the new field.
+ * @param numItems Number of items that the new field should contain room for.
+ * @returns A pointer to an array of (numItems) int8s, or NULL if there was an error.
+ * The returned array belongs to the MMessage, and will be freed by it at the proper time.
+ */
+int8 * MMPutInt8Field(MMessage * msg, MBool retainOldData, const char * fieldName, uint32 numItems);
+
+/** Attempts to create and install an int16 field with the specified field name into the MMessage.
+ * On success, any previously installed field with the same name will be replaced and freed.
+ * @param msg The MMessage to install the new field into.
+ * @param retainOldData This flag is relevant only if an int16 field with the same name already exists.
+ * If MTrue, as many of the old field's data values as possible will be transferred
+ * to the new field. Otherwise, all the old field's data will be destroyed and the
+ * new field will be created with all zero data values.
+ * @param fieldName Field name of the new field.
+ * @param numItems Number of items that the new field should contain room for.
+ * @returns A pointer to an array of (numItems) int16s, or NULL if there was an error.
+ * The returned array belongs to the MMessage, and will be freed by it at the proper time.
+ */
+int16 * MMPutInt16Field(MMessage * msg, MBool retainOldData, const char * fieldName, uint32 numItems);
+
+/** Attempts to create and install an int32 field with the specified field name into the MMessage.
+ * On success, any previously installed field with the same name will be replaced and freed.
+ * @param msg The MMessage to install the new field into.
+ * @param retainOldData This flag is relevant only if an int32 field with the same name already exists.
+ * If MTrue, as many of the old field's data values as possible will be transferred
+ * to the new field. Otherwise, all the old field's data will be destroyed and the
+ * new field will be created with all zero data values.
+ * @param fieldName Field name of the new field.
+ * @param numItems Number of items that the new field should contain room for.
+ * @returns A pointer to an array of (numItems) int32s, or NULL if there was an error.
+ * The returned array belongs to the MMessage, and will be freed by it at the proper time.
+ */
+int32 * MMPutInt32Field(MMessage * msg, MBool retainOldData, const char * fieldName, uint32 numItems);
+
+/** Attempts to create and install an int64 field with the specified field name into the MMessage.
+ * On success, any previously installed field with the same name will be replaced and freed.
+ * @param msg The MMessage to install the new field into.
+ * @param retainOldData This flag is relevant only if an int64 field with the same name already exists.
+ * If MTrue, as many of the old field's data values as possible will be transferred
+ * to the new field. Otherwise, all the old field's data will be destroyed and the
+ * new field will be created with all zero data values.
+ * @param fieldName Field name of the new field.
+ * @param numItems Number of items that the new field should contain room for.
+ * @returns A pointer to an array of (numItems) int64s, or NULL if there was an error.
+ * The returned array belongs to the MMessage, and will be freed by it at the proper time.
+ */
+int64 * MMPutInt64Field(MMessage * msg, MBool retainOldData, const char * fieldName, uint32 numItems);
+
+/** Attempts to create and install a float field with the specified field name into the MMessage.
+ * On success, any previously installed field with the same name will be replaced and freed.
+ * @param msg The MMessage to install the new field into.
+ * @param retainOldData This flag is relevant only if a float field with the same name already exists.
+ * If MTrue, as many of the old field's data values as possible will be transferred
+ * to the new field. Otherwise, all the old field's data will be destroyed and the
+ * new field will be created with all zero data values.
+ * @param fieldName Field name of the new field.
+ * @param numItems Number of items that the new field should contain room for.
+ * @returns A pointer to an array of (numItems) floats, or NULL if there was an error.
+ * The returned array belongs to the MMessage, and will be freed by it at the proper time.
+ */
+float * MMPutFloatField(MMessage * msg, MBool retainOldData, const char * fieldName, uint32 numItems);
+
+/** Attempts to create and install a double field with the specified field name into the MMessage.
+ * On success, any previously installed field with the same name will be replaced and freed.
+ * @param msg The MMessage to install the new field into.
+ * @param retainOldData This flag is relevant only if a double field with the same name already exists.
+ * If MTrue, as many of the old field's data values as possible will be transferred
+ * to the new field. Otherwise, all the old field's data will be destroyed and the
+ * new field will be created with all zero data values.
+ * @param fieldName Field name of the new field.
+ * @param numItems Number of items that the new field should contain room for.
+ * @returns A pointer to an array of (numItems) doubles, or NULL if there was an error.
+ * The returned array belongs to the MMessage, and will be freed by it at the proper time.
+ */
+double * MMPutDoubleField(MMessage * msg, MBool retainOldData, const char * fieldName, uint32 numItems);
+
+/** Attempts to create and install a Message field with the specified field name into the MMessage.
+ * On success, any previously installed field with the same name will be replaced and freed.
+ * @param msg The MMessage to install the new field into.
+ * @param retainOldData This flag is relevant only if a Message field with the same name already exists.
+ * If MTrue, as many of the old field's data values as possible will be transferred
+ * to the new field. Otherwise, all the old field's data will be destroyed and the
+ * new field will be created with all NULL data values.
+ * @param fieldName Field name of the new field.
+ * @param numItems Number of items that the new field should contain room for.
+ * @returns A pointer to an array of (numItems) Messages, or NULL if there was an error.
+ * The returned array belongs to the MMessage, and will be freed by it at the proper time.
+ * NOTE: Any MMessages that this array points to are considered to be owned by the MMessage
+ * as well, for as long as they are pointed to by the array. So when setting the array
+ * values, be sure to follow pointer semantics, such that any new values are allocated
+ * off the heap, and be sure to call MMFreeMessage() on any values you replace.
+ */
+MMessage ** MMPutMessageField(MMessage * msg, MBool retainOldData, const char * fieldName, uint32 numItems);
+
+/** Attempts to create and install a pointer field with the specified field name into the MMessage.
+ * On success, any previously installed field with the same name will be replaced and freed.
+ * @param msg The MMessage to install the new field into.
+ * @param retainOldData This flag is relevant only if a pointer field with the same name already exists.
+ * If MTrue, as many of the old field's data values as possible will be transferred
+ * to the new field. Otherwise, all the old field's data will be destroyed and the
+ * new field will be created with all NULL data values.
+ * @param fieldName Field name of the new field.
+ * @param numItems Number of items that the new field should contain room for.
+ * @returns A pointer to an array of (numItems) pointers, or NULL if there was an error.
+ * The returned array belongs to the MMessage, and will be freed by it at the proper time.
+ */
+void ** MMPutPointerField(MMessage * msg, MBool retainOldData, const char * fieldName, uint32 numItems);
+
+/** Attempts to create and install a point field with the specified field name into the MMessage.
+ * On success, any previously installed field with the same name will be replaced and freed.
+ * @param msg The MMessage to install the new field into.
+ * @param retainOldData This flag is relevant only if a point field with the same name already exists.
+ * If MTrue, as many of the old field's data values as possible will be transferred
+ * to the new field. Otherwise, all the old field's data will be destroyed and the
+ * new field will be created with all zero data values.
+ * @param fieldName Field name of the new field.
+ * @param numItems Number of items that the new field should contain room for.
+ * @returns A pointer to an array of (numItems) points, or NULL if there was an error.
+ * The returned array belongs to the MMessage, and will be freed by it at the proper time.
+ */
+MPoint * MMPutPointField(MMessage * msg, MBool retainOldData, const char * fieldName, uint32 numItems);
+
+/** Attempts to create and install a rect field with the specified field name into the MMessage.
+ * On success, any previously installed field with the same name will be replaced and freed.
+ * @param msg The MMessage to install the new field into.
+ * @param retainOldData This flag is relevant only if a rect field with the same name already exists.
+ * If MTrue, as many of the old field's data values as possible will be transferred
+ * to the new field. Otherwise, all the old field's data will be destroyed and the
+ * new field will be created with all zero data values.
+ * @param fieldName Field name of the new field.
+ * @param numItems Number of items that the new field should contain room for.
+ * @returns A pointer to an array of (numItems) rects, or NULL if there was an error.
+ * The returned array belongs to the MMessage, and will be freed by it at the proper time.
+ */
+MRect * MMPutRectField(MMessage * msg, MBool retainOldData, const char * fieldName, uint32 numItems);
+
+/** Attempts to create and install an untyped data field with the specified field name into the MMessage.
+ * On success, any previously installed field with the same name will be replaced and freed.
+ * @param msg The MMessage to install the new field into.
+ * @param retainOldData This flag is relevant only if a data field with the same name already exists.
+ * If MTrue, as many of the old field's data values as possible will be transferred
+ * to the new field. Otherwise, all the old field's data will be destroyed and the
+ * new field will be created with all NULL string values.
+ * @param fieldName Field name of the new field.
+ * @param numItems Number of items that the new field should contain room for.
+ * @returns A pointer to an array of (numItems) MByteBuffer pointers, or NULL if there was an error.
+ * The returned array belongs to the MMessage, and will be freed by it at the proper time.
+ * The MByteBuffer pointers in the array, when non-NULL, are also considered to belong to the
+ * MMessage, and will have MBFreeByteBuffer() called on them when the field is destroyed.
+ * NOTE: When setting a value in the array, be sure to allocate its memory using MBAllocByteBuffer()
+ * or MBStrdupByteBuffer(), and be sure to call MBFreeByteBuffer() on the old value before
+ * you replace it.
+ */
+MByteBuffer ** MMPutDataField(MMessage * msg, MBool retainOldData, uint32 typeCode, const char * fieldName, uint32 numItems);
+
+/** Returns the number of bytes it would take to hold a flattened representation of (msg).
+ * @param msg MMessage to scan to determine its flattened size.
+ * @returns Number of bytes the flattened representation would require.
+ */
+uint32 MMGetFlattenedSize(const MMessage * msg);
+
+/** Flattens the supplied MMessage into a platform-neutral byte buffer that can be sent out over the
+ * network or saved to disk and later reassembled back into an equivalent MMessage object by calling
+ * MMUnflattenMessage().
+ * @param msg MMessage to produce the byte buffer from.
+ * @param outBuf Pointer to the output array to write into. There must be at least
+ * MMGetFlattenedSize(msg) bytes of storage available at this location,
+ * or memory corruption will result. The output into this buffer will be in
+ * with the standard MUSCLE flattened byte buffer format.
+ */
+void MMFlattenMessage(const MMessage * msg, void * outBuf);
+
+/** Unflattens the supplied byte buffer into the supplied MMessage object.
+ * @param msg MMessage object to set the state of, based on the contents of the flattened byte buffer.
+ * @param inBuf Buffer containing the flattened MMessage bytes, as previously created by
+ * MMFlattenMessage() (or some other code that writes the flattened MUSCLE Message format).
+ * @param bufSizeBytes How many valid bytes of data are available at (inBuf).
+ * @returns B_NO_ERROR if the restoration was a success, or B_ERROR otherwise (in which case (msg) will
+ * likely be left in some valid but only partially restored state)
+ */
+status_t MMUnflattenMessage(MMessage * msg, const void * inBuf, uint32 bufSizeBytes);
+
+/** Moves the specified field from one MMessage to another.
+ * @param sourceMessage The MMessage where the field currently resides.
+ * @param fieldName Name of the field to move.
+ * @param destMsg The MMessage to move the field to. If a field with this name already exists
+ * inside (destMsg), it will be replaced and freed. If (destMsg) is NULL, the
+ * field will be removed from the source Message and freed.
+ * @returns B_NO_ERROR on success, or B_ERROR on failure.
+ */
+status_t MMMoveField(MMessage * sourceMsg, const char * fieldName, MMessage * destMsg);
+
+/** Copies the specified field from one MMessage to another.
+ * @param sourceMessage The MMessage where the field currently resides.
+ * @param fieldName Name of the field to copy.
+ * @param destMsg The MMessage to copy the field to. If a field with this name already exists
+ * inside (destMsg), it will be replaced and freed. If (destMsg) is NULL, this
+ * call will have no effect.
+ * @returns B_NO_ERROR on success, or B_ERROR on failure.
+ */
+status_t MMCopyField(const MMessage * sourceMsg, const char * fieldName, MMessage * destMsg);
+
+/** Change the name of a field within its Message.
+ * @param sourceMessage The MMessage where the field currently resides.
+ * @param oldFieldName Current name of the field.
+ * @param newFieldName Desired new name of the field. If a field with this name already exists
+ * inside (sourceMsg), it will be replaced and freed.
+ * @returns B_NO_ERROR on success, or B_ERROR on failure.
+ */
+status_t MMRenameField(MMessage * sourceMsg, const char * oldFieldName, const char * newFieldName);
+
+/** Retrieves the string field with the given name.
+ * @param msg The MMessage to look for the field in.
+ * @param fieldName Name of the field to look for.
+ * @param optRetNumItems If non-NULL, the number of items in the field will be written into the uint32 this points to.
+ * @returns A pointer to the array of MByteBuffers that represents the strings on success, or NULL on failure.
+ * Note that the returned array remains under the ownership of the MMessage object.
+ */
+MByteBuffer ** MMGetStringField(const MMessage * msg, const char * fieldName, uint32 * optRetNumItems);
+
+/** Retrieves the boolean field with the given name.
+ * @param msg The MMessage to look for the field in.
+ * @param fieldName Name of the field to look for.
+ * @param optRetNumItems If non-NULL, the number of items in the field will be written into the uint32 this points to.
+ * @returns A pointer to the array of MBool on success, or NULL on failure (field not found).
+ * Note that the returned array remains under the ownership of the MMessage object.
+ */
+MBool * MMGetBoolField(const MMessage * msg, const char * fieldName, uint32 * optRetNumItems);
+
+/** Retrieves the int8 field with the given name.
+ * @param msg The MMessage to look for the field in.
+ * @param fieldName Name of the field to look for.
+ * @param optRetNumItems If non-NULL, the number of items in the field will be written into the uint32 this points to.
+ * @returns A pointer to the array of int8s on success, or NULL on failure (field not found).
+ * Note that the returned array remains under the ownership of the MMessage object.
+ */
+int8 * MMGetInt8Field(const MMessage * msg, const char * fieldName, uint32 * optRetNumItems);
+
+/** Retrieves the int16 field with the given name.
+ * @param msg The MMessage to look for the field in.
+ * @param fieldName Name of the field to look for.
+ * @param optRetNumItems If non-NULL, the number of items in the field will be written into the uint32 this points to.
+ * @returns A pointer to the array of int16s on success, or NULL on failure (field not found).
+ * Note that the returned array remains under the ownership of the MMessage object.
+ */
+int16 * MMGetInt16Field(const MMessage * msg, const char * fieldName, uint32 * optRetNumItems);
+
+/** Retrieves the int32 field with the given name.
+ * @param msg The MMessage to look for the field in.
+ * @param fieldName Name of the field to look for.
+ * @param optRetNumItems If non-NULL, the number of items in the field will be written into the uint32 this points to.
+ * @returns A pointer to the array of int32s on success, or NULL on failure (field not found).
+ * Note that the returned array remains under the ownership of the MMessage object.
+ */
+int32 * MMGetInt32Field(const MMessage * msg, const char * fieldName, uint32 * optRetNumItems);
+
+/** Retrieves the int64 field with the given name.
+ * @param msg The MMessage to look for the field in.
+ * @param fieldName Name of the field to look for.
+ * @param optRetNumItems If non-NULL, the number of items in the field will be written into the uint32 this points to.
+ * @returns A pointer to the array of int64 on success, or NULL on failure (field not found).
+ * Note that the returned array remains under the ownership of the MMessage object.
+ */
+int64 * MMGetInt64Field(const MMessage * msg, const char * fieldName, uint32 * optRetNumItems);
+
+/** Retrieves the float field with the given name.
+ * @param msg The MMessage to look for the field in.
+ * @param fieldName Name of the field to look for.
+ * @param optRetNumItems If non-NULL, the number of items in the field will be written into the uint32 this points to.
+ * @returns A pointer to the array of floats on success, or NULL on failure (field not found).
+ * Note that the returned array remains under the ownership of the MMessage object.
+ */
+float * MMGetFloatField(const MMessage * msg, const char * fieldName, uint32 * optRetNumItems);
+
+/** Retrieves the double field with the given name.
+ * @param msg The MMessage to look for the field in.
+ * @param fieldName Name of the field to look for.
+ * @param optRetNumItems If non-NULL, the number of items in the field will be written into the uint32 this points to.
+ * @returns A pointer to the array of doubles on success, or NULL on failure (field not found).
+ * Note that the returned array remains under the ownership of the MMessage object.
+ */
+double * MMGetDoubleField(const MMessage * msg, const char * fieldName, uint32 * optRetNumItems);
+
+/** Retrieves the Message field with the given name.
+ * @param msg The MMessage to look for the field in.
+ * @param fieldName Name of the field to look for.
+ * @param optRetNumItems If non-NULL, the number of items in the field will be written into the uint32 this points to.
+ * @returns A pointer to the array of Messages on success, or NULL on failure (field not found).
+ * Note that the returned array remains under the ownership of the MMessage object.
+ */
+MMessage ** MMGetMessageField(const MMessage * msg, const char * fieldName, uint32 * optRetNumItems);
+
+/** Retrieves the pointer field with the given name.
+ * @param msg The MMessage to look for the field in.
+ * @param fieldName Name of the field to look for.
+ * @param optRetNumItems If non-NULL, the number of items in the field will be written into the uint32 this points to.
+ * @returns A pointer to the array of pointers on success, or NULL on failure (field not found).
+ * Note that the returned array remains under the ownership of the MMessage object.
+ */
+void ** MMGetPointerField(const MMessage * msg, const char * fieldName, uint32 * optRetNumItems);
+
+/** Retrieves the point field with the given name.
+ * @param msg The MMessage to look for the field in.
+ * @param fieldName Name of the field to look for.
+ * @param optRetNumItems If non-NULL, the number of items in the field will be written into the uint32 this points to.
+ * @returns A pointer to the array of points on success, or NULL on failure (field not found).
+ * Note that the returned array remains under the ownership of the MMessage object.
+ */
+MPoint * MMGetPointField(const MMessage * msg, const char * fieldName, uint32 * optRetNumItems);
+
+/** Retrieves the rect field with the given name.
+ * @param msg The MMessage to look for the field in.
+ * @param fieldName Name of the field to look for.
+ * @param optRetNumItems If non-NULL, the number of items in the field will be written into the uint32 this points to.
+ * @returns A pointer to the array of rects on success, or NULL on failure (field not found).
+ * Note that the returned array remains under the ownership of the MMessage object.
+ */
+MRect * MMGetRectField(const MMessage * msg, const char * fieldName, uint32 * optRetNumItems);
+
+/** Retrieves the data field with the given name.
+ * @param msg The MMessage to look for the field in.
+ * @param typeCode The typecode of the field to look for, or B_ANY_TYPE if you aren't particular about type.
+ * @param fieldName Name of the field to look for.
+ * @param optRetNumItems If non-NULL, the number of items in the field will be written into the uint32 this points to.
+ * @returns A pointer to the array of data items on success, or NULL on failure (field not found).
+ * Note that the returned array remains under the ownership of the MMessage object.
+ */
+MByteBuffer ** MMGetDataField(const MMessage * msg, uint32 typeCode, const char * fieldName, uint32 * optRetNumItems);
+
+/** Returns information about the type and size of the specified field.
+ * @param msg The MMessage to look for the field in.
+ * @param fieldName The name of the field to look for.
+ * @param typeCode The typecode of the field to look for, or B_ANY_TYPE if you aren't particular about type.
+ * @param optRetNumItems If non-NULL, on success the uint32 this points to will have the number of items in the field written into it.
+ * @param optRetTypeCode If non-NULL, on success the uint32 this points to will have the type code of the field written into it.
+ * @returns B_NO_ERROR if the field was found, or B_ERROR if no field with the specified name and type were present.
+ */
+status_t MMGetFieldInfo(const MMessage * msg, const char * fieldName, uint32 typeCode, uint32 * optRetNumItems, uint32 * optRetTypeCode);
+
+/** Returns MTrue iff the two MMessage objects are exactly equivalent. (Note that field ordering is not considered)
+ * @param msg1 First MMessage to compare. Must not be NULL.
+ * @param msg2 Second MMessage to compare. Must not be NULL.
+ * @returns MTrue If the two MMessage objects are equal; MFalse otherwise.
+ */
+MBool MMAreMessagesEqual(const MMessage * msg1, const MMessage * msg2);
+
+/** Prints the contents of this MMessage to stdout. Useful for debugging.
+ * @param msg The MMessage to print the contents of to stdout.
+ */
+void MMPrintToStream(const MMessage * msg);
+
+/** Returns an iterator object that you can use to iterator over the field names of this MMessage.
+ * @param msg The MMessage object over whose field names you wish to iterate.
+ * @param typeCode The type of field you are interested in, or B_ANY_TYPE if you aren't particular.
+ * @returns the iterator object, suitable, for passing in to the MMGetNextFieldName() function.
+ * @note It is an error to remove or replace fields in a MMessage object while iterating over it.
+ */
+MMessageIterator MMGetFieldNameIterator(const MMessage * msg, uint32 typeCode);
+
+/** Returns the next field name in the field name iteration, or NULL if there are no more field names.
+ * @param iteratorPtr This should point to the iterator object that was returned by a MMGetFieldNameIterator() call.
+ * @param optRetTypeCode If non-NULL, the uint32 this points to will have the next field's type code written into it.
+ * @returns The next field name, or NULL if the iteration is complete.
+ */
+const char * MMGetNextFieldName(MMessageIterator * iteratorPtr, uint32 * optRetTypeCode);
+
+#ifdef MUSCLE_ENABLE_MEMORY_TRACKING
+
+/** A wrapper for malloc() that allows us to track the number of bytes currently allocated.
+ * Good for catching memory leaks. Only enabled if MUSCLE_ENABLE_MEMORY_TRACKING is defined; otherwise #defined to malloc().
+ */
+void * MMalloc(uint32 numBytes);
+
+/** A wrapper for free() that allows us to track the number of bytes currently allocated.
+ * Good for catching memory leaks. Only enabled if MUSCLE_ENABLE_MEMORY_TRACKING is defined; otherwise #defined to free().
+ */
+void * MFree(void * ptr);
+
+/** A wrapper for realloc() that allows us to track the number of bytes currently allocated.
+ * Good for catching memory leaks. Only enabled if MUSCLE_ENABLE_MEMORY_TRACKING is defined; otherwise #defined to realloc().
+ */
+void * MRealloc(void * oldBuf, uint32 newSize);
+
+#else
+# define MMalloc malloc
+# define MRealloc realloc
+# define MFree free
+#endif
+
+/** Returns the current number of allocated bytes.
+ * Good for catching memory leaks. Only enabled if MUSCLE_ENABLE_MEMORY_TRACKING is defined; otherwise always returns zero.
+ */
+uint32 MGetNumBytesAllocated();
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
Added: trunk/include/MiniMessageGateway.h
==============================================================================
--- (empty file)
+++ trunk/include/MiniMessageGateway.h Mon Sep 12 21:57:35 2005
@@ -0,0 +1,113 @@
+/* NeoStats - IRC Statistical Services
+** Copyright (c) 1999-2005 Adam Rutter, Justin Hammond, Mark Hetherington
+** http://www.neostats.net/
+**
+** Portions Copyright (c) 2000 - 2001 ^Enigma^
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+** USA
+**
+** NeoStats CVS Identification
+** $Id$
+*/
+
+#ifndef MiniMessageGateway_h
+#define MiniMessageGateway_h
+
+#include "MiniMessage.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Definition of our opaque handle to a MMessageGateway object. Your
+ * code doesn't know what a (MMessageGateway *) points to, and it doesn't care,
+ * because all operations on it should happen via calls to the functions
+ * that are defined below.
+ */
+struct _MMessageGateway;
+typedef struct _MMessageGateway MMessageGateway;
+
+/** Typedef for a callback function that knows how to read data from a buffer and send it
+ * out to (a file, the network, a serial line, wherever).
+ * @param buf The buffer to read bytes from.
+ * @param numBytes The number of bytes available for reading at (buf)
+ * @param arg This is a user-specified value; it will be the same as the value passed in to MMDoOutput().
+ * @returns The number of bytes actually read from (buf), or a negative value if there was a critical error (e.g. disconnected socket).
+ */
+typedef int32 (*MGSendFunc)(const uint8 * buf, uint32 numBytes, void * arg);
+
+/** Typedef for a callback function that knows how to read data from
+ * (a file, the network, a serial line, wherever) and write it into a supplied buffer.
+ * @param buf The buffer to write bytes to.
+ * @param numBytes The number of bytes available for writing at (buf)
+ * @param arg This is a user-specified value; it will be the same as the value passed in to MMDoInput().
+ * @returns The number of bytes actually written into (buf), or a negative value if there was a critical error (e.g. disconnected socket).
+ */
+typedef int32 (*MGReceiveFunc)(uint8 * buf, uint32 numBytes, void * arg);
+
+/** Allocates and initializes a new MMessageGateway.
+ * @returns a newly allocated MMessageGateway, or NULL on failure. If non-NULL, it becomes the
+ * the responsibility of the calling code to call MMFreeMessageGateway() on the
+ * MMessageGateway when it is done using it.
+ */
+MMessageGateway * MGAllocMessageGateway();
+
+/** Frees a previously created MMessageGateway and all the data that it holds.
+ * @param msg The MMessageGateway to free. If NULL, no action will be taken.
+ */
+void MGFreeMessageGateway(MMessageGateway * gw);
+
+/** Flattens the given MMessage into bytes and adds the result to our queue of outgoing data.
+ * @param gw The Gateway to add the message data to.
+ * @param msg The MMessage object to flatten. Note that the gateway DOES NOT assume ownership of this MMessage!
+ * You are still responsible for freeing it, and may do so immediately on return of this function, if you wish.
+ * @returns B_NO_ERROR on success, or B_ERROR on error (out of memory?)
+ */
+status_t MGAddOutgoingMessage(MMessageGateway * gw, const MMessage * msg);
+
+/** Returns MTrue iff the given gateway has any output bytes queued up, that it wants to send.
+ * @param gw The Gateway to query.
+ * @returns MTrue if there are bytes queued up to send, or MFalse otherwise.
+ */
+MBool MGHasBytesToOutput(const MMessageGateway * gw);
+
+/** Writes out as many queued bytes as possible (up to maxBytes).
+ * @param gw The Gateway that should do the outputting.
+ * @param maxBytes The maximum number of bytes that should be sent by this function call. Pass in ~0 to write without limit.
+ * @param sendFunc The function that the gateway way will call to actually do the write operation.
+ * @param arg The argument to pass to the write function.
+ * @returns The number of bytes written, or a negative number if there was an error.
+ */
+int32 MGDoOutput(MMessageGateway * gw, uint32 maxBytes, MGSendFunc sendFunc, void * arg);
+
+/** Reads in as many queued bytes as possible (up to maxBytes, or until a full MMessage is read).
+ * @param gw The Gateway that should do the inputting.
+ * @param maxBytes The maximum number of bytes that should be read by this function call. Pass in ~0 to read without limit.
+ * @param recvFunc The function that the gateway way will call to actually do the read operation.
+ * @param arg The argument to pass to the read function.
+ * @param optRetMsg If non-NULL, the pointer this argument points to will be set to a returned MMessage object
+ * if there is one ready, or NULL otherwise. NOTE: If the pointer is set non-NULL, it becomes
+ * the calling code's responsibility to call MMFreeMessage() on the pointer when you are done with it!
+ * Failure to do so will result in a memory leak.
+ * @returns The number of bytes read, or a negative number if there was an error.
+ */
+int32 MGDoInput(MMessageGateway * gw, uint32 maxBytes, MGReceiveFunc recvFunc, void * arg, MMessage ** optRetMsg);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
Added: trunk/include/MuscleSupport.h
==============================================================================
--- (empty file)
+++ trunk/include/MuscleSupport.h Mon Sep 12 21:57:35 2005
@@ -0,0 +1,757 @@
+/* NeoStats - IRC Statistical Services
+** Copyright (c) 1999-2005 Adam Rutter, Justin Hammond, Mark Hetherington
+** http://www.neostats.net/
+**
+** Portions Copyright (c) 2000 - 2001 ^Enigma^
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+** USA
+**
+** NeoStats CVS Identification
+** $Id$
+*/
+
+/* This file is Copyright 2005 Level Control Systems. See the included LICENSE.txt file for details. */
+
+/******************************************************************************
+/
+/ File: MuscleSupport.h
+/
+/ Description: Standard types, macros, etc, for MUSCLE.
+/ Many of them are suspiciously BeOS-like. ;^)
+/
+*******************************************************************************/
+
+#ifndef MuscleSupport_h
+#define MuscleSupport_h
+
+#define MUSCLE_VERSION_STRING "3.01"
+
+/* Define this if the default FD_SETSIZE is too small for you (i.e. under Windows it's only 64) */
+#if defined(MUSCLE_FD_SETSIZE)
+# if defined(FD_SETSIZE)
+# error "MuscleSupport.h: Can't redefine FD_SETSIZE, someone else has already defined it! You need to include MuscleSupport.h before including any other header files that define FD_SETSIZE."
+# else
+# define FD_SETSIZE MUSCLE_FD_SETSIZE
+# endif
+#endif
+
+/* If we are in an environment where known assembly is available, make a note of that fact */
+#if defined(__GNUC__)
+# if (defined(__PPC__) || defined(__APPLE__))
+# define MUSCLE_USE_POWERPC_INLINE_ASSEMBLY 1
+# elif defined(__i386__)
+# define MUSCLE_USE_X86_INLINE_ASSEMBLY 1
+# endif
+#endif
+
+#if defined(_MSC_VER) && defined(_X86_)
+# define MUSCLE_USE_X86_INLINE_ASSEMBLY 1
+#endif
+
+#ifndef __cplusplus
+# define MUSCLE_AVOID_NAMESPACES
+# define NEW_H_NOT_AVAILABLE
+#endif
+
+/* Since certain antique compilers don't support namespaces, we
+ * do all namespace-related declarations via macros which can
+ * be no-op'd out by declaring -DMUSCLE_AVOID_NAMESPACES in the Makefile.
+ */
+#ifdef MUSCLE_AVOID_NAMESPACES
+# define DECLARE_NAMESPACE(x)
+# define BEGIN_NAMESPACE(x)
+# define END_NAMESPACE(x)
+# define USING_NAMESPACE(x)
+#else
+# define DECLARE_NAMESPACE(x) namespace x {};
+# define BEGIN_NAMESPACE(x) namespace x {
+# define END_NAMESPACE(x) };
+# define USING_NAMESPACE(x) using namespace x;
+#endif
+
+/* Just declare the muscle namespace as existing.
+ * If we ever decide to make the muscle namespace a superset
+ * of another namespace, we would add a 'using namespace' line here.
+ */
+DECLARE_NAMESPACE(muscle);
+
+/* these CPUs can't handle non-aligned word reads, so we'll accomodate them by using memcpy() instead. */
+#if defined(MIPS) || defined(mc68000) || defined(sparc) || defined(__sparc) || defined(m68k) || defined(__68k__) || defined(__sparc__)
+# define MUSCLE_CPU_REQUIRES_DATA_ALIGNMENT
+#endif
+
+/* Borland C++ builder also runs under Win32, but it doesn't set this flag So we'd better set it ourselves. */
+#ifdef __BORLANDC__
+# ifndef WIN32
+# define WIN32 1
+# endif
+#endif
+
+/* VC++ can't handle this stuff, it's too lame */
+#ifdef WIN32
+# define UNISTD_H_NOT_AVAILABLE
+# define NEW_H_NOT_AVAILABLE
+#endif
+
+#ifndef UNISTD_H_NOT_AVAILABLE
+# include <unistd.h>
+#endif
+
+#ifndef NEW_H_NOT_AVAILABLE
+# include <new>
+# ifndef MUSCLE_AVOID_NAMESPACES
+# ifndef __MWERKS__
+using std::bad_alloc;
+using std::nothrow_t;
+using std::nothrow;
+using std::new_handler;
+using std::set_new_handler;
+# endif
+# endif
+#else
+# define MUSCLE_AVOID_NEWNOTHROW
+#endif
+
+#ifndef newnothrow
+# ifdef MUSCLE_AVOID_NEWNOTHROW
+# define newnothrow new
+# else
+# define newnothrow new (nothrow)
+# endif
+#endif
+
+/* Unfortunately, the 64-bit printf() format specifier is different for different compilers :^P */
+#if defined(__MWERKS__) || defined(WIN32) || defined(__BORLANDC__) || defined(__BEOS__)
+# if (_MSC_VER == 1200)
+# define INT64_FORMAT_SPEC "%I64i"
+# define UINT64_FORMAT_SPEC "%I64u"
+# else
+# define INT64_FORMAT_SPEC "%Li"
+# define UINT64_FORMAT_SPEC "%Lu"
+# endif
+#else
+# define INT64_FORMAT_SPEC "%lli"
+# define UINT64_FORMAT_SPEC "%llu"
+#endif
+
+#ifdef __BEOS__
+# include <kernel/debugger.h>
+# define MCRASH_IMPL debugger("muscle assertion failure")
+#elif defined(WIN32)
+# if defined(UNICODE)
+# define MCRASH_IMPL FatalAppExit(0, L"muscle assertion failure")
+# else
+# define MCRASH_IMPL FatalAppExit(0, "muscle assertion failure")
+# endif
+#else
+# define MCRASH_IMPL *((uint32*)NULL) = 0x666
+#endif
+
+#ifdef MUSCLE_AVOID_ASSERTIONS
+# define MASSERT(x,msg)
+#else
+# define MASSERT(x,msg) {if(!(x)) MCRASH(msg)}
+#endif
+
+#ifdef MUSCLE_AVOID_NAMESPACES
+# define MCRASH(msg) {LogTime(MUSCLE_LOG_CRITICALERROR, "ASSERTION FAILED: (%s:%i) %s\n", __FILE__,__LINE__,msg); LogStackTrace(MUSCLE_LOG_CRITICALERROR); MCRASH_IMPL;}
+# define WARN_OUT_OF_MEMORY LogTime(MUSCLE_LOG_CRITICALERROR, "ERROR--OUT OF MEMORY! (%s:%i)\n",__FILE__,__LINE__)
+# define MCHECKPOINT LogTime(MUSCLE_LOG_WARNING, "Reached checkpoint at %s:%i\n", __FILE__, __LINE__)
+#else
+# define MCRASH(msg) {muscle::LogTime(muscle::MUSCLE_LOG_CRITICALERROR, "ASSERTION FAILED: (%s:%i) %s\n", __FILE__,__LINE__,msg); muscle::LogStackTrace(MUSCLE_LOG_CRITICALERROR); MCRASH_IMPL;}
+# define WARN_OUT_OF_MEMORY muscle::LogTime(muscle::MUSCLE_LOG_CRITICALERROR, "ERROR--OUT OF MEMORY! (%s:%i)\n",__FILE__,__LINE__)
+# define MCHECKPOINT muscle::LogTime(muscle::MUSCLE_LOG_WARNING, "Reached checkpoint at %s:%i\n", __FILE__, __LINE__)
+#endif
+
+#define UNLESS(x) if(!(x))
+#define ARRAYITEMS(x) (sizeof(x)/sizeof(x[0])) /* returns # of items in array */
+
+typedef void * muscleVoidPointer; /* it's a bit easier, syntax-wise, to use this type than (void *) directly in some cases. */
+
+#ifdef __BEOS__
+# include <support/Errors.h>
+# include <support/ByteOrder.h> /* might as well use the real thing (and avoid complaints about duplication) */
+# include <support/SupportDefs.h>
+# include <support/TypeConstants.h>
+# ifdef BONE
+# define closesocket close
+# else
+# define BEOS_OLD_NETSERVER
+# endif
+#else
+# define B_ERROR -1
+# define B_NO_ERROR 0
+# define B_OK B_NO_ERROR
+# ifndef WIN32
+# define closesocket close
+# endif
+# ifdef __ATHEOS__
+# include </ainc/atheos/types.h>
+# else
+# ifndef MUSCLE_TYPES_PREDEFINED /* certain (ahem) projects already set these themselves... */
+# define true 1
+# define false 0
+ typedef signed char int8;
+ typedef unsigned char uint8;
+ typedef short int16;
+ typedef unsigned short uint16;
+# if defined(__osf__) /* some 64bit systems will have long=64-bit, int=32-bit */
+ typedef int int32;
+ typedef unsigned int uint32;
+# elif defined(__amd64__) /* some 64bit systems will have long=64-bit, int=32-bit */
+ typedef int int32;
+ typedef unsigned int uint32;
+# else
+ typedef long int32;
+ typedef unsigned long uint32;
+# endif
+# if defined(WIN32) && !defined(__GNUWIN32__)
+ typedef __int64 int64;
+ typedef unsigned __int64 uint64;
+# else
+ typedef long long int64;
+ typedef unsigned long long uint64;
+# endif
+ typedef unsigned char uchar;
+ typedef unsigned short unichar;
+ typedef int32 status_t;
+# endif /* !MUSCLE_TYPES_PREDEFINED */
+# endif /* !__ATHEOS__*/
+#endif /* __BEOS__*/
+
+#define MAKETYPE(x) ((((unsigned long)(x[0])) << 24) | \
+ (((unsigned long)(x[1])) << 16) | \
+ (((unsigned long)(x[2])) << 8) | \
+ (((unsigned long)(x[3])) << 0))
+
+#ifndef __BEOS__
+/* Be-style message-field type codes.
+ * I've calculated the integer equivalents for these codes
+ * because gcc whines like a little girl about the four-byte
+ * constants when compiling under Linux --jaf
+ */
+enum {
+ B_ANY_TYPE = 1095653716, /* 'ANYT' = wild card */
+ B_BOOL_TYPE = 1112493900, /* 'BOOL' = boolean (1 byte per bool) */
+ B_DOUBLE_TYPE = 1145195589, /* 'DBLE' = double-precision float (8 bytes per double) */
+ B_FLOAT_TYPE = 1179406164, /* 'FLOT' = single-precision float (4 bytes per float) */
+ B_INT64_TYPE = 1280069191, /* 'LLNG' = long long integer (8 bytes per int) */
+ B_INT32_TYPE = 1280265799, /* 'LONG' = long integer (4 bytes per int) */
+ B_INT16_TYPE = 1397248596, /* 'SHRT' = short integer (2 bytes per int) */
+ B_INT8_TYPE = 1113150533, /* 'BYTE' = byte integer (1 byte per int) */
+ B_MESSAGE_TYPE = 1297303367, /* 'MSGG' = sub Message objects (reference counted) */
+ B_POINTER_TYPE = 1347310674, /* 'PNTR' = pointers (will not be flattened) */
+ B_POINT_TYPE = 1112559188, /* 'BPNT' = Point objects (each Point has two floats) */
+ B_RECT_TYPE = 1380270932, /* 'RECT' = Rect objects (each Rect has four floats) */
+ B_STRING_TYPE = 1129534546, /* 'CSTR' = String objects (variable length) */
+ B_OBJECT_TYPE = 1330664530, /* 'OPTR' = Flattened user objects (obsolete) */
+ B_RAW_TYPE = 1380013908, /* 'RAWT' = Raw data (variable number of bytes) */
+ B_MIME_TYPE = 1296649541 /* 'MIME' = MIME strings (obsolete) */
+};
+#endif
+
+/* This one isn't defined by BeOS, so we have to enumerate it separately. */
+enum {
+ B_TAG_TYPE = 1297367367 /* 'MTAG' = new for v2.00; for in-mem-only tags */
+};
+
+/* This constant is used in various places to mean 'as much as you want' */
+#define MUSCLE_NO_LIMIT ((uint32)-1)
+
+#ifdef __cplusplus
+
+/** A handy little method to swap the bytes of any int-style datatype around */
+template<typename T> inline T muscleSwapBytes(T swapMe)
+{
+ T retVal;
+ const uint8 * readFrom = (const uint8 *) &swapMe;
+ uint8 * writeTo = ((uint8 *) &retVal)+sizeof(retVal);
+ for (uint32 i=0; i<sizeof(swapMe); i++) {*(--writeTo) = *(readFrom++);}
+ return retVal;
+}
+
+/* This template safely copies a value in from an untyped byte buffer to a typed value.
+ * (Make sure MUSCLE_CPU_REQUIRES_DATA_ALIGNMENT is defined if you are on a CPU
+ * that doesn't like non-word-aligned data reads and writes)
+ */
+template<typename T> inline void muscleCopyIn(T & dest, const void * source)
+{
+#ifdef MUSCLE_CPU_REQUIRES_DATA_ALIGNMENT
+ memcpy(&dest, source, sizeof(dest));
+#else
+ dest = *((const T*)source);
+#endif
+}
+
+/** This template safely copies a value in from a typed value to an untyped byte buffer.
+ * (Make sure MUSCLE_CPU_REQUIRES_DATA_ALIGNMENT is defined if you are on a CPU
+ * that doesn't like non-word-aligned data reads and writes)
+ */
+template<typename T> inline void muscleCopyOut(void * dest, const T & source)
+{
+#ifdef MUSCLE_CPU_REQUIRES_DATA_ALIGNMENT
+ memcpy(dest, &source, sizeof(source));
+#else
+ *((T*)dest) = source;
+#endif
+}
+
+/** This macro should be used instead of "newnothrow T[count]". It works the
+ * same, except that it hacks around an ugly bug in gcc 3.x where newnothrow
+ * would return ((T*)0x4) on memory failure instead of NULL.
+ * See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=10300
+ */
+#if __GNUC__ == 3
+template <typename T> inline T * broken_gcc_newnothrow_array(size_t count)
+{
+ T * ret = newnothrow T[count];
+ return (ret <= (T *)(sizeof(void *))) ? NULL : ret;
+}
+# define newnothrow_array(T, count) broken_gcc_newnothrow_array<T>(count)
+#else
+# define newnothrow_array(T, count) newnothrow T[count]
+#endif
+
+/** Returns the smallest of the two arguments */
+template<typename T> inline const T & muscleMin(const T & p1, const T & p2) {return (p1 < p2) ? p1 : p2;}
+
+/** Returns the smallest of the three arguments */
+template<typename T> inline const T & muscleMin(const T & p1, const T & p2, const T & p3) {return muscleMin(p3, muscleMin(p1, p2));}
+
+/** Returns the smallest of the four arguments */
+template<typename T> inline const T & muscleMin(const T & p1, const T & p2, const T & p3, const T & p4) {return muscleMin(p3, p4, muscleMin(p1, p2));}
+
+/** Returns the smallest of the five arguments */
+template<typename T> inline const T & muscleMin(const T & p1, const T & p2, const T & p3, const T & p4, const T & p5) {return muscleMin(p3, p4, p5, muscleMin(p1, p2));}
+
+/** Returns the largest of the two arguments */
+template<typename T> inline const T & muscleMax(const T & p1, const T & p2) {return (p1 < p2) ? p2 : p1;}
+
+/** Returns the largest of the three arguments */
+template<typename T> inline const T & muscleMax(const T & p1, const T & p2, const T & p3) {return muscleMax(p3, muscleMax(p1, p2));}
+
+/** Returns the largest of the four arguments */
+template<typename T> inline const T & muscleMax(const T & p1, const T & p2, const T & p3, const T & p4) {return muscleMax(p3, p4, muscleMax(p1, p2));}
+
+/** Returns the largest of the five arguments */
+template<typename T> inline const T & muscleMax(const T & p1, const T & p2, const T & p3, const T & p4, const T & p5) {return muscleMax(p3, p4, p5, muscleMax(p1, p2));}
+
+/** Swaps the two arguments */
+template<typename T> inline void muscleSwap(T & p1, T & p2) {T t = p1; p1 = p2; p2 = t;}
+
+/** Returns the value nearest to (v) that is still in the range [lo, hi]. */
+template<typename T> inline const T & muscleClamp(const T & v, const T & lo, const T & hi) {return (v < lo) ? lo : ((v > hi) ? hi : v);}
+
+/** Returns true iff (v) is in the range [lo,hi]. */
+template<typename T> inline bool muscleInRange(const T & v, const T & lo, const T & hi) {return ((v >= lo)&&(v <= hi));}
+
+/** Returns -1 if arg1 is larger, or 1 if arg2 is larger, or 0 if they are equal. */
+template<typename T> inline int muscleCompare(const T & arg1, const T & arg2) {return (arg1>arg2) ? 1 : ((arg1<arg2) ? -1 : 0);}
+
+/** Returns the absolute value of (arg) */
+template<typename T> inline T muscleAbs(const T & arg) {return (arg<0)?(-arg):arg;}
+
+/** Rounds the given float to the nearest integer value. */
+inline int muscleRintf(float f) {return (f>=0.0f) ? ((int)(f+0.5f)) : -((int)((-f)+0.5f));}
+
+/** Returns -1 if the value is less than zero, +1 if it is greater than zero, or 0 otherwise. */
+template<typename T> inline int muscleSgn(const T & arg) {return (arg<0)?-1:((arg>0)?1:0);}
+
+#endif /* __cplusplus */
+
+#ifndef __BEOS__
+
+/*
+ * Copyright(c) 1983, 1989
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * from nameser.h 8.1 (Berkeley) 6/2/93
+ * $Id$
+ */
+
+#ifndef BYTE_ORDER
+ #if (BSD >= 199103)
+ #include <machine/endian.h>
+ #else
+ #ifdef linux
+ #include <endian.h>
+ #else
+ #define LITTLE_ENDIAN 1234 /* least-significant byte first (vax, pc) */
+ #define BIG_ENDIAN 4321 /* most-significant byte first (IBM, net) */
+
+ #if defined(vax) || defined(ns32000) || defined(sun386) || defined(i386) || \
+ defined(__i386) || defined(__ia64) || \
+ defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \
+ defined(__alpha__) || defined(__alpha) || defined(__CYGWIN__) || \
+ defined(_M_IX86) || defined(__GNUWIN32__) || defined(__LITTLEENDIAN__) || \
+ (defined(__Lynx__) && defined(__x86__))
+ #define BYTE_ORDER LITTLE_ENDIAN
+ #endif
+
+ #if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \
+ defined(__sparc) || \
+ defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \
+ defined(MIPSEB) || defined(_MIPSEB) || defined(_IBMR2) || defined(DGUX) ||\
+ defined(apollo) || defined(__convex__) || defined(_CRAY) || \
+ defined(__hppa) || defined(__hp9000) || \
+ defined(__hp9000s300) || defined(__hp9000s700) || \
+ defined(__hp3000s900) || defined(MPE) || \
+ defined(BIT_ZERO_ON_LEFT) || defined(m68k) || \
+ (defined(__Lynx__) && \
+ (defined(__68k__) || defined(__sparc__) || defined(__powerpc__)))
+ #define BYTE_ORDER BIG_ENDIAN
+ #endif
+ #endif /* linux */
+ #endif /* BSD */
+#endif /* BYTE_ORDER */
+
+#if !defined(BYTE_ORDER) || (BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN)
+ /*
+ * you must determine what the correct bit order is for
+ * your compiler - the next line is an intentional error
+ * which will force your compiles to bomb until you fix
+ * the above macros.
+ */
+ error "Undefined or invalid BYTE_ORDER";
+#endif
+
+/* End replacement code from Sun/University of California */
+# if defined(MUSCLE_USE_POWERPC_INLINE_ASSEMBLY)
+static inline uint16 MusclePowerPCSwapInt16(uint16 val)
+{
+ uint16 a;
+ uint16 * addr = &a;
+ __asm__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
+ return a;
+}
+static inline uint32 MusclePowerPCSwapInt32(uint32 val)
+{
+ uint32 a;
+ uint32 * addr = &a;
+ __asm__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
+ return a;
+}
+static inline float MusclePowerPCSwapFloat(float val)
+{
+ float a;
+ float * addr = &a;
+ __asm__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
+ return a;
+}
+static inline uint64 MusclePowerPCSwapInt64(uint64 val)
+{
+ return ((uint64)(MusclePowerPCSwapInt32((uint32)((val>>32)&0xFFFFFFFF))))|(((uint64)(MusclePowerPCSwapInt32((uint32)(val&0xFFFFFFFF))))<<32);
+}
+static inline double MusclePowerPCSwapDouble(double val)
+{
+ uint64 v64 = MusclePowerPCSwapInt64(*((uint64 *)&val));
+ return *((double *)&v64);
+}
+# define B_SWAP_DOUBLE(arg) MusclePowerPCSwapDouble((double)(arg))
+# define B_SWAP_FLOAT(arg) MusclePowerPCSwapFloat((float)(arg))
+# define B_SWAP_INT64(arg) MusclePowerPCSwapInt64((uint64)(arg))
+# define B_SWAP_INT32(arg) MusclePowerPCSwapInt32((uint32)(arg))
+# define B_SWAP_INT16(arg) MusclePowerPCSwapInt16((uint16)(arg))
+# elif defined(MUSCLE_USE_X86_INLINE_ASSEMBLY)
+static inline uint16 MuscleX86SwapInt16(uint16 val)
+{
+#ifdef _MSC_VER
+ __asm {
+ mov ax, val;
+ xchg al, ah;
+ mov val, ax;
+ };
+#else
+ __asm__ ("xchgb %b0,%h0" : "=q" (val) : "0" (val));
+#endif
+ return val;
+}
+static inline uint32 MuscleX86SwapInt32(uint32 val)
+{
+#ifdef _MSC_VER
+ __asm {
+ mov eax, val;
+ bswap eax;
+ mov val, eax;
+ };
+#else
+ __asm__ ("bswap %0" : "+r" (val));
+#endif
+ return val;
+}
+static inline float MuscleX86SwapFloat(float val)
+{
+#ifdef _MSC_VER
+ __asm {
+ mov eax, val;
+ bswap eax;
+ mov val, eax;
+ };
+#else
+ __asm__ ("bswap %0" : "+r" (val));
+#endif
+ return val;
+}
+static inline uint64 MuscleX86SwapInt64(uint64 val)
+{
+#ifdef _MSC_VER
+ __asm {
+ mov eax, DWORD PTR val;
+ mov edx, DWORD PTR val + 4;
+ bswap eax;
+ bswap edx;
+ mov DWORD PTR val, edx;
+ mov DWORD PTR val + 4, eax;
+ };
+ return val;
+#else
+ return ((uint64)(MuscleX86SwapInt32((uint32)((val>>32)&0xFFFFFFFF))))|(((uint64)(MuscleX86SwapInt32((uint32)(val&0xFFFFFFFF))))<<32);
+#endif
+}
+static inline double MuscleX86SwapDouble(double val)
+{
+#ifdef _MSC_VER
+ __asm {
+ mov eax, DWORD PTR val;
+ mov edx, DWORD PTR val + 4;
+ bswap eax;
+ bswap edx;
+ mov DWORD PTR val, edx;
+ mov DWORD PTR val + 4, eax;
+ };
+ return val;
+#else
+ uint64 v64 = MuscleX86SwapInt64(*((uint64 *)&val));
+ return *((double *)&v64);
+#endif
+}
+# define B_SWAP_DOUBLE(arg) MuscleX86SwapDouble((double)(arg))
+# define B_SWAP_FLOAT(arg) MuscleX86SwapFloat((float)(arg))
+# define B_SWAP_INT64(arg) MuscleX86SwapInt64((uint64)(arg))
+# define B_SWAP_INT32(arg) MuscleX86SwapInt32((uint32)(arg))
+# define B_SWAP_INT16(arg) MuscleX86SwapInt16((uint16)(arg))
+# else
+# define B_SWAP_DOUBLE(arg) muscleSwapBytes((double)(arg))
+# define B_SWAP_FLOAT(arg) muscleSwapBytes((float)(arg))
+# define B_SWAP_INT64(arg) muscleSwapBytes((uint64)(arg))
+# define B_SWAP_INT32(arg) muscleSwapBytes((uint32)(arg))
+# define B_SWAP_INT16(arg) muscleSwapBytes((uint16)(arg))
+# endif
+# if BYTE_ORDER == LITTLE_ENDIAN
+# define B_HOST_IS_LENDIAN 1
+# define B_HOST_IS_BENDIAN 0
+# define B_HOST_TO_LENDIAN_DOUBLE(arg) ((double)(arg))
+# define B_HOST_TO_LENDIAN_FLOAT(arg) ((float)(arg))
+# define B_HOST_TO_LENDIAN_INT64(arg) ((uint64)(arg))
+# define B_HOST_TO_LENDIAN_INT32(arg) ((uint32)(arg))
+# define B_HOST_TO_LENDIAN_INT16(arg) ((uint16)(arg))
+# define B_HOST_TO_BENDIAN_DOUBLE(arg) B_SWAP_DOUBLE(arg)
+# define B_HOST_TO_BENDIAN_FLOAT(arg) B_SWAP_FLOAT(arg)
+# define B_HOST_TO_BENDIAN_INT64(arg) B_SWAP_INT64(arg)
+# define B_HOST_TO_BENDIAN_INT32(arg) B_SWAP_INT32(arg)
+# define B_HOST_TO_BENDIAN_INT16(arg) B_SWAP_INT16(arg)
+# define B_LENDIAN_TO_HOST_DOUBLE(arg) ((double)(arg))
+# define B_LENDIAN_TO_HOST_FLOAT(arg) ((float)(arg))
+# define B_LENDIAN_TO_HOST_INT64(arg) ((uint64)(arg))
+# define B_LENDIAN_TO_HOST_INT32(arg) ((uint32)(arg))
+# define B_LENDIAN_TO_HOST_INT16(arg) ((uint16)(arg))
+# define B_BENDIAN_TO_HOST_DOUBLE(arg) B_SWAP_DOUBLE(arg)
+# define B_BENDIAN_TO_HOST_FLOAT(arg) B_SWAP_FLOAT(arg)
+# define B_BENDIAN_TO_HOST_INT64(arg) B_SWAP_INT64(arg)
+# define B_BENDIAN_TO_HOST_INT32(arg) B_SWAP_INT32(arg)
+# define B_BENDIAN_TO_HOST_INT16(arg) B_SWAP_INT16(arg)
+# else /* LITTLE_ENDIAN */
+# define B_HOST_IS_LENDIAN 0
+# define B_HOST_IS_BENDIAN 1
+# define B_HOST_TO_LENDIAN_DOUBLE(arg) B_SWAP_DOUBLE(arg)
+# define B_HOST_TO_LENDIAN_FLOAT(arg) B_SWAP_FLOAT(arg)
+# define B_HOST_TO_LENDIAN_INT64(arg) B_SWAP_INT64(arg)
+# define B_HOST_TO_LENDIAN_INT32(arg) B_SWAP_INT32(arg)
+# define B_HOST_TO_LENDIAN_INT16(arg) B_SWAP_INT16(arg)
+# define B_HOST_TO_BENDIAN_DOUBLE(arg) ((double)(arg))
+# define B_HOST_TO_BENDIAN_FLOAT(arg) ((float)(arg))
+# define B_HOST_TO_BENDIAN_INT64(arg) ((uint64)(arg))
+# define B_HOST_TO_BENDIAN_INT32(arg) ((uint32)(arg))
+# define B_HOST_TO_BENDIAN_INT16(arg) ((uint16)(arg))
+# define B_LENDIAN_TO_HOST_DOUBLE(arg) B_SWAP_DOUBLE(arg)
+# define B_LENDIAN_TO_HOST_FLOAT(arg) B_SWAP_FLOAT(arg)
+# define B_LENDIAN_TO_HOST_INT64(arg) B_SWAP_INT64(arg)
+# define B_LENDIAN_TO_HOST_INT32(arg) B_SWAP_INT32(arg)
+# define B_LENDIAN_TO_HOST_INT16(arg) B_SWAP_INT16(arg)
+# define B_BENDIAN_TO_HOST_DOUBLE(arg) ((double)(arg))
+# define B_BENDIAN_TO_HOST_FLOAT(arg) ((float)(arg))
+# define B_BENDIAN_TO_HOST_INT64(arg) ((uint64)(arg))
+# define B_BENDIAN_TO_HOST_INT32(arg) ((uint32)(arg))
+# define B_BENDIAN_TO_HOST_INT16(arg) ((uint16)(arg))
+# endif /* !LITTLE_ENDIAN */
+#endif /* !__BEOS__ */
+
+/* Macro to turn a type code into a string representation.
+ * (typecode) is the type code to get the string for
+ * (buf) is a (char *) to hold the output string; it must be >= 5 bytes long.
+ */
+#define MakePrettyTypeCodeString(typecode, buf) \
+ { \
+ uint32 __bigEndian = B_HOST_TO_BENDIAN_INT32(typecode); \
+ memcpy(buf, (const char *)&__bigEndian, sizeof(__bigEndian)); \
+ buf[sizeof(__bigEndian)] = '\0'; \
+ }
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h> /* for errno */
+
+#ifdef WIN32
+# include <windows.h>
+# include <winsock.h> /* for WSAGetLastError() */
+#endif
+
+#ifdef __cplusplus
+# include "syslog/SysLog.h" /* for LogTime() */
+#endif /* __cplusplus */
+
+/** Checks errno and returns true iff the last I/O operation
+ * failed because it would have had to block otherwise.
+ * NOTE: Returns int so that it will compile even in C environments where no bool type is defined.
+ */
+static inline int PreviousOperationWouldBlock()
+{
+#ifdef WIN32
+ return (WSAGetLastError() == WSAEWOULDBLOCK);
+#else
+ return (errno == EWOULDBLOCK);
+#endif
+}
+
+/** Checks errno and returns true iff the last I/O operation
+ * failed because it was interrupted by a signal or etc.
+ * NOTE: Returns int so that it will compile even in C environments where no bool type is defined.
+ */
+static inline int PreviousOperationWasInterrupted()
+{
+#ifdef WIN32
+ return (WSAGetLastError() == WSAEINTR);
+#else
+ return (errno == EINTR);
+#endif
+}
+
+/** This function applies semi-standard logic to convert the return value
+ * of a system I/O call and (errno) into a proper MUSCLE-standard return value.
+ * (A MUSCLE-standard return value's semantics are: Negative on error,
+ * otherwise the return value is the number of bytes that were transferred)
+ * @param origRet The return value of the original system call (e.g. to read()/write()/send()/recv())
+ * @param maxSize The maximum number of bytes that the system call was permitted to send during that call.
+ * @param blocking True iff the socket/file descriptor is in blocking I/O mode. (Type is int for C compatibility -- it's really a boolean parameter)
+ * @returns The system call's return value equivalent in MUSCLE return value semantics.
+ */
+static inline int32 ConvertReturnValueToMuscleSemantics(int origRet, uint32 maxSize, int blocking)
+{
+ int32 retForBlocking = ((origRet > 0)||(maxSize == 0)) ? origRet : -1;
+ return blocking ? retForBlocking : ((origRet<0)&&((PreviousOperationWouldBlock())||(PreviousOperationWasInterrupted()))) ? 0 : retForBlocking;
+}
+
+BEGIN_NAMESPACE(muscle);
+
+#if MUSCLE_TRACE_CHECKPOINTS > 0
+
+/** Exposed as an implementation detail. Please ignore! */
+extern volatile uint32 * _muscleTraceValues;
+
+/** Exposed as an implementation detail. Please ignore! */
+extern uint32 _muscleNextTraceValueIndex;
+
+/** Sets the location of the trace-checkpoints array to store trace checkpoints into.
+ * @param location A pointer to an array of at least (MUSCLE_TRACE_CHECKPOINTS) uint32s, or NULL.
+ * If NULL (or if this function is never called), the default array will be used.
+ */
+void SetTraceValuesLocation(volatile uint32 * location);
+
+/** Set this process's current trace value to (v). This can be used as a primitive debugging tool, to determine
+ * where this process was last seen executing -- useful for determining where the process is spinning at.
+ * @note this function is a no-op if MUSCLE_TRACE_CHECKPOINTS is not defined to a value greater than zero.
+ */
+static inline void StoreTraceValue(uint32 v)
+{
+ _muscleTraceValues[_muscleNextTraceValueIndex] = v; /* store the current value */
+ _muscleNextTraceValueIndex = (_muscleNextTraceValueIndex+1)%MUSCLE_TRACE_CHECKPOINTS; /* move the pointer */
+ _muscleTraceValues[_muscleNextTraceValueIndex] = ((uint32)-1); /* mark the next position with a special tag to show that it's next */
+}
+
+/** Returns a pointer to the first value in the trace-values array. */
+static inline const volatile uint32 * GetTraceValues() {return _muscleTraceValues;}
+
+/** A macro for automatically setting a trace checkpoint value based on current code location.
+ * The value will be the two characters of the function or file name, left-shifted by 16 bits,
+ * and then OR'd together with the current line number. This should give the debugging person a
+ * fairly good clue as to where the checkpoint was located, while still being very cheap to implement.
+ *
+ * @note This function will be a no-op unless MUSCLE_TRACE_CHECKPOINTS is defined to be greater than zero.
+ */
+#if defined(__GNUC__)
+#define TCHECKPOINT \
+{ \
+ const char * d = __FUNCTION__; \
+ StoreTraceValue((d[0]<<24)|(d[1]<<16)|(__LINE__)); \
+}
+#else
+#define TCHECKPOINT \
+{ \
+ const char * d = __FILE__; \
+ StoreTraceValue((d[0]<<24)|(d[1]<<16)|(__LINE__)); \
+}
+#endif
+
+#else
+/* no-op implementations for when we aren't using the trace facility */
+static inline void SetTraceValuesLocation(volatile uint32 * location) {(void) location;} /* named param is necessary for C compatibility */
+static inline void StoreTraceValue(uint32 v) {(void) v;} /* named param is necessary for C compatibility */
+#define TCHECKPOINT {/* empty */}
+#endif
+
+END_NAMESPACE(muscle);
+
+#endif /* _MUSCLE_SUPPORT_H */