static uint32 GetMMessageFieldFlattenedSize(const MMessageField * f, MBool includeHeaders) { uint32 sum = includeHeaders ? (sizeof(uint32) + f->nameBytes + sizeof(uint32) + sizeof(uint32)) : 0; /* Entry name length, entry name, string, type code, entry data length */ if (IsTypeCodeVariableSize(f->typeCode)) { uint32 numItems = f->numItems; uint32 i; sum += (numItems*sizeof(uint32)); /* because each sub-item is preceded by its byte-count */ if (f->typeCode == B_MESSAGE_TYPE) { /* Note that NULL entries will be flattened as empty Messages, since the protocol doesn't support them directly. */ const MMessage ** msgs = (const MMessage **) f->data; for (i=0; i<numItems; i++) sum += msgs[i] ? MMGetFlattenedSize(msgs[i]) : (3*sizeof(uint32)); } else { const MByteBuffer ** bufs = (const MByteBuffer **) f->data; sum += sizeof(uint32); /* num-items-in-array field */ for (i=0; i<numItems; i++) sum += bufs[i] ? bufs[i]->numBytes : 0; } } else sum += f->numItems*f->itemSize; /* Entry data length and data items */ return sum; }
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 PrintMMessageToStreamAux(const MMessage * msg, FILE * file, int indent) { /* Make a pretty type code string */ char buf[5]; MakePrettyTypeCodeString(msg->what, buf); fprintf(file, "MMessage: msg=%p, what='%s' ("INT32_FORMAT_SPEC"), entryCount="INT32_FORMAT_SPEC", flatSize="UINT32_FORMAT_SPEC"\n", msg, buf, msg->what, msg->numFields, MMGetFlattenedSize(msg)); indent += 2; { MMessageField * f = msg->firstField; while(f) { PrintMMessageFieldToStream(f, file, indent); f = f->nextField; } } }
static void PrintMMessageToStreamAux(const MMessage * msg, int indent) { /* Make a pretty type code string */ char buf[5]; MakePrettyTypeCodeString(msg->what, buf); dlog(DEBUG1, "MMessage: msg=%p, what='%s' (%li/0x%lx), entryCount=%li, flatSize=%lu", msg, buf, msg->what, msg->what, msg->numFields, MMGetFlattenedSize(msg)); indent += 2; { MMessageField * f = msg->firstField; while(f) { PrintMMessageFieldToStream(f, indent); f = f->nextField; } } }