#include #include #include #include #include #include #include #include "DumpMessage.h" //#define WHAT_ALWAYS_HEX 1 const char *msg_header_comment = "// new BMessage\n"; // avoids mime to think it's a .bmp ("BM") // '_' also widely used in what codes inline int myisprint(int c) { if (isalnum(c)) return 1; return (c == '_')?1:0; } status_t HexDumpToStream(const void *data, size_t len, BDataIO &stream, const char *prefix = NULL) { const unsigned char *p = (unsigned char *)data; char buffer[100]; size_t i, j; for (i=0; i= len) sprintf(buffer, " "); //else if (p[i+j] < 255 && p[i+j] >= 0x20) else if (isalpha(p[i+j])) sprintf(buffer, "%c", p[i+j]); else sprintf(buffer, "."); stream.Write(buffer, 1); } sprintf(buffer, "'\n"); stream.Write(buffer, strlen(buffer)); } return B_OK; } /* look up human readable names from an other BMessage */ bool LookUpFieldName(const char **name, const char *field_name, BMessage *names) { if (names == NULL) return false; if (names->FindString(field_name, name) == B_OK) return true; return false; } status_t DumpMessageToStream(BMessage *message, BDataIO &stream, int tabCount, BMessage *names) { int32 index; void *cookie = NULL; const char *field_name; type_code field_code; int32 field_count; char buffer[80]; char tabs[20]; const char *easy_name; if (message == NULL) return EINVAL; if (tabCount < 1) stream.Write(msg_header_comment, strlen(msg_header_comment)); memset(tabs, '\t', (++tabCount) + 1); tabs[tabCount+1] = '\0'; //tabCount; #ifndef WHAT_ALWAYS_HEX if ( myisprint(message->what & 0x0ff) && myisprint((message->what >> 8) & 0x0ff) && myisprint((message->what >> 16) & 0x0ff) && myisprint((message->what >> 24) & 0x0ff)) sprintf(buffer, "BMessage('%c%c%c%c') {\n", (char)(message->what >> 24) & 0x0ff, (char)(message->what >> 16) & 0x0ff, (char)(message->what >> 8) & 0x0ff, (char)message->what & 0x0ff); else #endif sprintf(buffer, "BMessage(0x%08lx) {\n", message->what); // stream.Write(tabs+2, tabCount-2); stream.Write(buffer, strlen(buffer)); #ifdef B_BEOS_VERSION_DANO while (message->GetNextName(&cookie, &field_name, &field_code, &field_count) == B_OK) { #else #warning mem leak likely! (name=char *) for (int which=0; message->GetInfo(B_ANY_TYPE, which, (char **)&field_name, &field_code, &field_count) == B_OK; which++) { #endif if (LookUpFieldName(&easy_name, field_name, names)) { stream.Write(tabs+1, tabCount); stream.Write("// ", 3); stream.Write(easy_name, strlen(easy_name)); stream.Write("\n", 1); } for (index=0; index < field_count; index++) { stream.Write(tabs+1, tabCount); stream.Write(field_name, strlen(field_name)); if (field_count > 1) { sprintf(buffer, "[%ld]", index); stream.Write(buffer, strlen(buffer)); } stream.Write(" = ", 3); switch (field_code) { case 'MSGG': { BMessage m; if (message->FindMessage(field_name, index, &m) >= B_OK) DumpMessageToStream(&m, stream, tabCount, names); } break; #ifdef B_BEOS_VERSION_DANO case 'FONt': { BFont f; if (message->FindFlat(field_name, index, &f) >= B_OK) stream << f; stream.Write("\n", 1); } break; case B_RGB_COLOR_TYPE: { rgb_color c; if (message->FindRGBColor(field_name, index, &c) >= B_OK) { sprintf(buffer, "rgb_color(%d,%d,%d,%d)", c.red, c.green, c.blue, c.alpha); stream.Write(buffer, strlen(buffer)); } stream.Write("\n", 1); } break; #else #warning IMPLEMENT ME #endif case B_BOOL_TYPE: { bool value; if (message->FindBool(field_name, index, &value) >= B_OK) { sprintf(buffer, "bool(%s)", value?"true":"false"); stream.Write(buffer, strlen(buffer)); } stream.Write("\n", 1); } break; case B_INT32_TYPE: { int32 value; if (message->FindInt32(field_name, index, &value) >= B_OK) { #if 1 if (value == 0) sprintf(buffer, "int32(0 or (nil))"); else #endif // sprintf(buffer, "int32(%d)", value); sprintf(buffer, "int32(%ld or 0x%lx)", value, value); stream.Write(buffer, strlen(buffer)); } stream.Write("\n", 1); } break; case B_FLOAT_TYPE: { float value; if (message->FindFloat(field_name, index, &value) >= B_OK) { sprintf(buffer, "float(%f)", value); stream.Write(buffer, strlen(buffer)); } stream.Write("\n", 1); } break; case B_STRING_TYPE: { const char *value; if (message->FindString(field_name, index, &value) >= B_OK) { BString str(value); str.CharacterEscape("\\\"\n", '\\'); //sprintf(buffer, "string(\"%s\", %ld bytes)", str.String(), strlen(value)); // DO NOT use buffer! str.Prepend("string(\""); str << "\", " << strlen(value) << " bytes)"; stream.Write(str.String(), strlen(str.String())); } stream.Write("\n", 1); } break; case B_POINT_TYPE: { BPoint value; if (message->FindPoint(field_name, index, &value) >= B_OK) { sprintf(buffer, "BPoint(%1.1f, %1.1f)", value.x, value.y); stream.Write(buffer, strlen(buffer)); } stream.Write("\n", 1); } break; default: { const void *data; ssize_t numBytes = 0; if (message->FindData(field_name, field_code, index, &data, &numBytes) != B_OK) { //stream.Write("\n", 1); break; } if ( isalnum(field_code & 0x0ff) && isalnum((field_code >> 8) & 0x0ff) && isalnum((field_code >> 16) & 0x0ff) && isalnum((field_code >> 24) & 0x0ff)) sprintf(buffer, "'%c%c%c%c' %ld bytes:\n", (char)(field_code >> 24) & 0x0ff, (char)(field_code >> 16) & 0x0ff, (char)(field_code >> 8) & 0x0ff, (char)field_code & 0x0ff, numBytes); else sprintf(buffer, "0x%08lx %ld bytes:\n", field_code, numBytes); stream.Write(buffer, strlen(buffer)); stream.Write("\n", 1); HexDumpToStream(data, numBytes, stream, tabs); } break; } } } stream.Write(tabs+2, tabCount-1); stream.Write("}\n", 2); return B_OK; }