/* * Copyright 2000-2008, François Revol, . All rights reserved. * Distributed under the terms of the MIT License. */ #include #include #include #include #include #include #include "DumpMessage.h" #include "Utils.h" //#define WHAT_ALWAYS_HEX 1 const char *msg_header_comment = "// new BMessage\n"; // avoids mime to think it's a .bmp ("BM") 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 field, index; 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 ( isalnum(message->what & 0x0ff) && isalnum((message->what >> 8) & 0x0ff) && isalnum((message->what >> 16) & 0x0ff) && isalnum((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)); for (field = 0; message->GetInfo(B_ANY_TYPE, field, GET_INFO_NAME_PTR(&field_name), &field_code, &field_count) == B_OK; field++) { 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; case B_RGB_COLOR_TYPE: { rgb_color c; if (FindRGBColor(*message, 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; case 'FONt': { BFont f; if (FindFont(*message, field_name, index, &f) >= B_OK) { #ifdef B_BEOS_VERSION_DANO stream << f; #else font_family family; font_style style; font_height height; f.GetFamilyAndStyle(&family, &style); f.GetHeight(&height); BString s; s << "BFont(" << family; s << "/" << style << "/" << f.Size(); s << ", shear=" << f.Shear(); s << ", rot=" << f.Rotation(); s << ", height=" << height.ascent; s << "+" << height.descent; s << "+" << height.leading << ")"; stream.Write(s.String(), s.Length()); #endif } stream.Write("\n", 1); } break; 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; }