uint32 MMGetFlattenedSize(const MMessage * msg) { /* For the message header: 4 bytes for the protocol revision #, 4 bytes for the number-of-entries field, 4 bytes for what code */ uint32 sum = 3 * sizeof(uint32); const MMessageField * f = msg->firstField; while(f) { if (f->isFlattenable) sum += GetMMessageFieldFlattenedSize(f, MTrue); f = f->nextField; } return sum; }
static void PrintMMessageFieldToStream(const MMessageField * field, FILE * file, int indent) { char pbuf[5]; const void * data = field->data; int i = 0; int ni = field->numItems; if (ni > 10) ni = 10; /* truncate to avoid too much spam */ MakePrettyTypeCodeString(field->typeCode, pbuf); DoIndent(indent); fprintf(file, "Entry: Name=[%s] GetNumItems()="UINT32_FORMAT_SPEC", TypeCode=%s ("INT32_FORMAT_SPEC") flatSize="UINT32_FORMAT_SPEC"\n", field->name, field->numItems, pbuf, field->typeCode, GetMMessageFieldFlattenedSize(field, MFalse)); for (i=0; i<ni; i++) { DoIndent(indent); fprintf(file, " %i. ", i); switch(field->typeCode) { case B_BOOL_TYPE: fprintf(file, "%i\n", (((const MBool *)data)[i])); break; case B_DOUBLE_TYPE: fprintf(file, "%f\n", ((const double *)data)[i]); break; case B_FLOAT_TYPE: fprintf(file, "%f\n", ((const float *)data)[i]); break; case B_INT64_TYPE: fprintf(file, INT64_FORMAT_SPEC"\n", ((const int64 *)data)[i]); break; case B_INT32_TYPE: fprintf(file, INT32_FORMAT_SPEC"\n", ((const int32 *)data)[i]); break; case B_POINTER_TYPE: fprintf(file, "%p\n", ((const void **)data)[i]); break; case B_INT16_TYPE: fprintf(file, "%i\n", ((const int16 *)data)[i]); break; case B_INT8_TYPE: fprintf(file, "%i\n", ((const int8 *)data)[i]); break; case B_POINT_TYPE: { const MPoint * pt = &((const MPoint *)data)[i]; fprintf(file, "x=%f y=%f\n", pt->x, pt->y); } break; case B_RECT_TYPE: { const MRect * rc = &((const MRect *)data)[i]; fprintf(file, "l=%f t=%f r=%f b=%f\n", rc->left, rc->top, rc->right, rc->bottom); } break; case B_MESSAGE_TYPE: { MMessage * subMsg = ((MMessage **)field->data)[i]; if (subMsg) PrintMMessageToStreamAux(subMsg, file, indent+3); else fprintf(file, "(NULL Message)\n"); } break; case B_STRING_TYPE: { MByteBuffer * subBuf = ((MByteBuffer **)field->data)[i]; if (subBuf) fprintf(file, "[%s]\n", (const char *) (&subBuf->bytes)); else fprintf(file, "(NULL String)\n"); } break; default: { MByteBuffer * subBuf = ((MByteBuffer **)field->data)[i]; if (subBuf) { int numBytes = subBuf->numBytes; if (numBytes > 0) { const uint8 * b = &subBuf->bytes; int nb = subBuf->numBytes; int j; if (nb > 10) { fprintf(file, "(%i bytes, starting with", nb); nb = 10; } else fprintf(file, "(%i bytes, equal to",nb); for (j=0; j<nb; j++) fprintf(file, " %02x", b[j]); if (nb < subBuf->numBytes) fprintf(file, "...)\n"); else fprintf(file, ")\n"); } else fprintf(file, "(zero-length buffer)\n"); } else fprintf(file, "(NULL Buffer)\n"); } break; } } }
static uint32 FlattenMMessageField(const MMessageField * f, void * outBuf) { /* 3. Entry name length (4 bytes) */ /* 4. Entry name string (flattened String) */ /* 5. Entry type code (4 bytes) */ /* 6. Entry data length (4 bytes) */ /* 7. Entry data (n bytes) */ /* Write entry name length */ uint32 writeOffset = 0; uint8 * buffer = (uint8 *) outBuf; { uint32 networkByteOrder = B_HOST_TO_LENDIAN_INT32(f->nameBytes); WriteData(buffer, &writeOffset, &networkByteOrder, sizeof(networkByteOrder)); } /* Write entry name */ memcpy(&buffer[writeOffset], f->name, f->nameBytes); writeOffset += f->nameBytes; /* Write entry type code */ { uint32 networkByteOrder = B_HOST_TO_LENDIAN_INT32(f->typeCode); WriteData(buffer, &writeOffset, &networkByteOrder, sizeof(networkByteOrder)); } /* Write entry data length */ { uint32 networkByteOrder = B_HOST_TO_LENDIAN_INT32(GetMMessageFieldFlattenedSize(f, MFalse)); WriteData(buffer, &writeOffset, &networkByteOrder, sizeof(networkByteOrder)); } /* Write entry data */ if (IsTypeCodeVariableSize(f->typeCode)) { uint32 numItems = f->numItems; uint32 i; if (f->typeCode == B_MESSAGE_TYPE) { /* Note that NULL entries will be flattened as empty Messages, since the protocol doesn't support them directly. */ /* Note also that for this type the number-of-items-in-array field is NOT written into the buffer (sigh) */ const MMessage ** msgs = (const MMessage **) f->data; for (i=0; i<numItems; i++) { const MMessage * subMsg = msgs[i]; uint32 msgSize = subMsg ? MMGetFlattenedSize(subMsg) : (3*sizeof(uint32)); uint32 networkByteOrder = B_HOST_TO_LENDIAN_INT32(msgSize); WriteData(buffer, &writeOffset, &networkByteOrder, sizeof(networkByteOrder)); if (subMsg) { MMFlattenMessage(subMsg, &buffer[writeOffset]); writeOffset += msgSize; } else { /* No MMessage present? Then we're going to have to fake one */ /* Format: 0. Protocol revision number (4 bytes, always set to CURRENT_PROTOCOL_VERSION) */ /* 1. 'what' code (4 bytes) */ /* 2. Number of entries (4 bytes) */ /* Write current protocol version */ uint32 networkByteOrder = B_HOST_TO_LENDIAN_INT32(CURRENT_PROTOCOL_VERSION); WriteData(buffer, &writeOffset, &networkByteOrder, sizeof(networkByteOrder)); /* Write 'what' code (zero) */ networkByteOrder = B_HOST_TO_LENDIAN_INT32(0); WriteData(buffer, &writeOffset, &networkByteOrder, sizeof(networkByteOrder)); /* Write number of entries (zero) */ networkByteOrder = B_HOST_TO_LENDIAN_INT32(0); WriteData(buffer, &writeOffset, &networkByteOrder, sizeof(networkByteOrder)); } } } else { const MByteBuffer ** bufs = (const MByteBuffer **) f->data; int i; /* Write the number of items in the array */ uint32 networkByteOrder = B_HOST_TO_LENDIAN_INT32(numItems); WriteData(buffer, &writeOffset, &networkByteOrder, sizeof(networkByteOrder)); for (i=0; i<numItems; i++) { uint32 bufSize = bufs[i] ? bufs[i]->numBytes : 0; uint32 networkByteOrder = B_HOST_TO_LENDIAN_INT32(bufSize); WriteData(buffer, &writeOffset, &networkByteOrder, sizeof(networkByteOrder)); memcpy(&buffer[writeOffset], &bufs[i]->bytes, bufSize); writeOffset += bufSize; } } } else { uint32 dataSize = f->numItems*f->itemSize; MBool doMemcpy = MTrue; if (BYTE_ORDER != LITTLE_ENDIAN) { doMemcpy = MFalse; switch(f->typeCode) { case B_BOOL_TYPE: case B_INT8_TYPE: doMemcpy = MTrue; break; case B_POINT_TYPE: SwapCopy(&buffer[writeOffset], f->data, f->numItems*2, sizeof(float)); break; case B_RECT_TYPE: SwapCopy(&buffer[writeOffset], f->data, f->numItems*4, sizeof(float)); break; default: SwapCopy(&buffer[writeOffset], f->data, f->numItems, f->itemSize); break; } } if (doMemcpy) memcpy(&buffer[writeOffset], f->data, dataSize); writeOffset += dataSize; } return writeOffset; }
static void PrintMMessageFieldToStream(const MMessageField * field, int indent) { char pbuf[5]; const void * data = field->data; int i = 0; int ni = field->numItems; if (ni > 10) ni = 10; /* truncate to avoid too much spam */ MakePrettyTypeCodeString(field->typeCode, pbuf); dlog(DEBUG1,"Entry: Name=[%s] GetNumItems()=%lu, TypeCode=%s (%li) flatSize=%lu", field->name, field->numItems, pbuf, field->typeCode, GetMMessageFieldFlattenedSize(field, MFalse)); for (i=0; i<ni; i++) { switch(field->typeCode) { case B_BOOL_TYPE: dlog(DEBUG1,"%i) %i",i, (((const MBool *)data)[i])); break; case B_DOUBLE_TYPE: dlog(DEBUG1,"%i) %f", i, ((const double *)data)[i]); break; case B_FLOAT_TYPE: dlog(DEBUG1,"%i) %f", i, ((const float *)data)[i]); break; case B_INT64_TYPE: dlog(DEBUG1,"%i) %lli", i, ((const int64 *)data)[i]); break; case B_INT32_TYPE: dlog(DEBUG1,"%i) %li", i, ((const int32 *)data)[i]); break; case B_POINTER_TYPE: dlog(DEBUG1,"%i) %p", i, ((const void **)data)[i]); break; case B_INT16_TYPE: dlog(DEBUG1,"%i) %i", i, ((const int16 *)data)[i]); break; case B_INT8_TYPE: dlog(DEBUG1,"%i) %i", i, ((const int8 *)data)[i]); break; case B_POINT_TYPE: { const MPoint * pt = &((const MPoint *)data)[i]; dlog(DEBUG1,"%i) x=%f y=%f", i, pt->x, pt->y); } break; case B_RECT_TYPE: { const MRect * rc = &((const MRect *)data)[i]; dlog(DEBUG1,"%i) l=%f t=%f r=%f b=%f", i, rc->left, rc->top, rc->right, rc->bottom); } break; case B_MESSAGE_TYPE: { MMessage * subMsg = ((MMessage **)field->data)[i]; if (subMsg) PrintMMessageToStreamAux(subMsg, indent+3); else dlog(DEBUG1,"%i) (NULL Message)", i); } break; case B_STRING_TYPE: { MByteBuffer * subBuf = ((MByteBuffer **)field->data)[i]; if (subBuf) dlog(DEBUG1,"%i) [%s]", i,(const char *) (&subBuf->bytes)); else dlog(DEBUG1,"%i) (NULL String)", i); } break; default: { MByteBuffer * subBuf = ((MByteBuffer **)field->data)[i]; if (subBuf) { int numBytes = subBuf->numBytes; if (numBytes > 0) { const uint8 * b = &subBuf->bytes; int nb = subBuf->numBytes; int j; if (nb > 10) { dlog(DEBUG1,"%i) (%i bytes, starting with", i, nb); nb = 10; } else dlog(DEBUG1,"%i) (%i bytes, equal to", i, nb); for (j=0; j<nb; j++) dlog(DEBUG1," %02x", b[j]); if (nb < subBuf->numBytes) dlog(DEBUG1,"...)"); else dlog(DEBUG1,")"); } else dlog(DEBUG1,"%i) (zero-length buffer)", i); } else dlog(DEBUG1,"%i) (NULL Buffer)", i); } break; } } /* just to shut up the warnings */ if (0) { DoIndent(0); } }