1 #include <string.h> 2 #include <stdio.h> 3 #include <ctype.h> 4 #include <BeBuild.h> 5 #include <Font.h> 6 #include <Message.h> 7 #include <String.h> 8 #include "DumpMessage.h" 9 10 //#define WHAT_ALWAYS_HEX 1 11 12 const char *msg_header_comment = "// new BMessage\n"; // avoids mime to think it's a .bmp ("BM") 13 14 // '_' also widely used in what codes 15 inline int myisprint(int c) 16 { 17 if (isalnum(c)) 18 return 1; 19 return (c == '_')?1:0; 20 } 21 22 status_t HexDumpToStream(const void *data, size_t len, BDataIO &stream, const char *prefix = NULL) 23 { 24 const unsigned char *p = (unsigned char *)data; 25 char buffer[100]; 26 size_t i, j; 27 for (i=0; i<len; i+=16) { 28 if (prefix) stream.Write(prefix, strlen(prefix)); 29 sprintf(buffer, "0x%06lx: ", i); 30 stream.Write(buffer, strlen(buffer)); 31 for (j=0; j<16; j++) { 32 if (i+j < len) 33 sprintf(buffer, "%02x", p[i+j]); 34 else 35 sprintf(buffer, " "); 36 if (j % 4 == 3) 37 sprintf(buffer+strlen(buffer), " "); 38 stream.Write(buffer, strlen(buffer)); 39 } 40 sprintf(buffer, " '"); 41 stream.Write(buffer, strlen(buffer)); 42 for (j=0; j<16; j++) { 43 if (i+j >= len) 44 sprintf(buffer, " "); 45 //else if (p[i+j] < 255 && p[i+j] >= 0x20) 46 else if (isalpha(p[i+j])) 47 sprintf(buffer, "%c", p[i+j]); 48 else 49 sprintf(buffer, "."); 50 stream.Write(buffer, 1); 51 } 52 sprintf(buffer, "'\n"); 53 stream.Write(buffer, strlen(buffer)); 54 } 55 return B_OK; 56 } 57 58 /* look up human readable names from an other BMessage */ 59 bool LookUpFieldName(const char **name, const char *field_name, BMessage *names) 60 { 61 if (names == NULL) 62 return false; 63 if (names->FindString(field_name, name) == B_OK) 64 return true; 65 return false; 66 } 67 68 status_t DumpMessageToStream(BMessage *message, BDataIO &stream, int tabCount, BMessage *names) 69 { 70 int32 index; 71 void *cookie = NULL; 72 const char *field_name; 73 type_code field_code; 74 int32 field_count; 75 char buffer[80]; 76 char tabs[20]; 77 const char *easy_name; 78 79 if (message == NULL) 80 return EINVAL; 81 82 if (tabCount < 1) 83 stream.Write(msg_header_comment, strlen(msg_header_comment)); 84 85 memset(tabs, '\t', (++tabCount) + 1); 86 tabs[tabCount+1] = '\0'; 87 //tabCount; 88 89 #ifndef WHAT_ALWAYS_HEX 90 if ( myisprint(message->what & 0x0ff) && 91 myisprint((message->what >> 8) & 0x0ff) && 92 myisprint((message->what >> 16) & 0x0ff) && 93 myisprint((message->what >> 24) & 0x0ff)) 94 sprintf(buffer, "BMessage('%c%c%c%c') {\n", 95 (char)(message->what >> 24) & 0x0ff, 96 (char)(message->what >> 16) & 0x0ff, 97 (char)(message->what >> 8) & 0x0ff, 98 (char)message->what & 0x0ff); 99 else 100 #endif 101 sprintf(buffer, "BMessage(0x%08lx) {\n", message->what); 102 // stream.Write(tabs+2, tabCount-2); 103 stream.Write(buffer, strlen(buffer)); 104 105 #ifdef B_BEOS_VERSION_DANO 106 while (message->GetNextName(&cookie, 107 &field_name, 108 &field_code, 109 &field_count) == B_OK) { 110 #else 111 #warning mem leak likely! (name=char *) 112 for (int which=0; message->GetInfo(B_ANY_TYPE, which, 113 (char **)&field_name, &field_code, &field_count) == B_OK; which++) { 114 #endif 115 if (LookUpFieldName(&easy_name, field_name, names)) { 116 stream.Write(tabs+1, tabCount); 117 stream.Write("// ", 3); 118 stream.Write(easy_name, strlen(easy_name)); 119 stream.Write("\n", 1); 120 } 121 122 for (index=0; index < field_count; index++) { 123 stream.Write(tabs+1, tabCount); 124 stream.Write(field_name, strlen(field_name)); 125 if (field_count > 1) { 126 sprintf(buffer, "[%ld]", index); 127 stream.Write(buffer, strlen(buffer)); 128 } 129 stream.Write(" = ", 3); 130 131 switch (field_code) { 132 case 'MSGG': 133 { 134 BMessage m; 135 if (message->FindMessage(field_name, index, &m) >= B_OK) 136 DumpMessageToStream(&m, stream, tabCount, names); 137 } 138 break; 139 #ifdef B_BEOS_VERSION_DANO 140 case 'FONt': 141 { 142 BFont f; 143 if (message->FindFlat(field_name, index, &f) >= B_OK) 144 stream << f; 145 stream.Write("\n", 1); 146 } 147 break; 148 case B_RGB_COLOR_TYPE: 149 { 150 rgb_color c; 151 if (message->FindRGBColor(field_name, index, &c) >= B_OK) { 152 sprintf(buffer, "rgb_color(%d,%d,%d,%d)", 153 c.red, c.green, c.blue, c.alpha); 154 stream.Write(buffer, strlen(buffer)); 155 } 156 stream.Write("\n", 1); 157 } 158 break; 159 #else 160 #warning IMPLEMENT ME 161 #endif 162 case B_BOOL_TYPE: 163 { 164 bool value; 165 if (message->FindBool(field_name, index, &value) >= B_OK) { 166 sprintf(buffer, "bool(%s)", value?"true":"false"); 167 stream.Write(buffer, strlen(buffer)); 168 } 169 stream.Write("\n", 1); 170 } 171 break; 172 case B_INT32_TYPE: 173 { 174 int32 value; 175 if (message->FindInt32(field_name, index, &value) >= B_OK) { 176 #if 1 177 if (value == 0) 178 sprintf(buffer, "int32(0 or (nil))"); 179 else 180 #endif 181 // sprintf(buffer, "int32(%d)", value); 182 sprintf(buffer, "int32(%ld or 0x%lx)", value, value); 183 stream.Write(buffer, strlen(buffer)); 184 } 185 stream.Write("\n", 1); 186 } 187 break; 188 case B_FLOAT_TYPE: 189 { 190 float value; 191 if (message->FindFloat(field_name, index, &value) >= B_OK) { 192 sprintf(buffer, "float(%f)", value); 193 stream.Write(buffer, strlen(buffer)); 194 } 195 stream.Write("\n", 1); 196 } 197 break; 198 case B_STRING_TYPE: 199 { 200 const char *value; 201 if (message->FindString(field_name, index, &value) >= B_OK) { 202 BString str(value); 203 str.CharacterEscape("\\\"\n", '\\'); 204 //sprintf(buffer, "string(\"%s\", %ld bytes)", str.String(), strlen(value)); 205 // DO NOT use buffer! 206 str.Prepend("string(\""); 207 str << "\", " << strlen(value) << " bytes)"; 208 stream.Write(str.String(), strlen(str.String())); 209 } 210 stream.Write("\n", 1); 211 } 212 break; 213 case B_POINT_TYPE: 214 { 215 BPoint value; 216 if (message->FindPoint(field_name, index, &value) >= B_OK) { 217 sprintf(buffer, "BPoint(%1.1f, %1.1f)", value.x, value.y); 218 stream.Write(buffer, strlen(buffer)); 219 } 220 stream.Write("\n", 1); 221 } 222 break; 223 default: 224 { 225 const void *data; 226 ssize_t numBytes = 0; 227 if (message->FindData(field_name, field_code, index, &data, &numBytes) != B_OK) { 228 //stream.Write("\n", 1); 229 break; 230 } 231 232 if ( isalnum(field_code & 0x0ff) && 233 isalnum((field_code >> 8) & 0x0ff) && 234 isalnum((field_code >> 16) & 0x0ff) && 235 isalnum((field_code >> 24) & 0x0ff)) 236 sprintf(buffer, "'%c%c%c%c' %ld bytes:\n", 237 (char)(field_code >> 24) & 0x0ff, 238 (char)(field_code >> 16) & 0x0ff, 239 (char)(field_code >> 8) & 0x0ff, 240 (char)field_code & 0x0ff, 241 numBytes); 242 else 243 sprintf(buffer, "0x%08lx %ld bytes:\n", field_code, numBytes); 244 stream.Write(buffer, strlen(buffer)); 245 stream.Write("\n", 1); 246 HexDumpToStream(data, numBytes, stream, tabs); 247 } 248 break; 249 } 250 } 251 } 252 stream.Write(tabs+2, tabCount-1); 253 stream.Write("}\n", 2); 254 return B_OK; 255 } 256 257