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
myisprint(int c)15 inline int myisprint(int c)
16 {
17 if (isalnum(c))
18 return 1;
19 return (c == '_')?1:0;
20 }
21
HexDumpToStream(const void * data,size_t len,BDataIO & stream,const char * prefix=NULL)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 */
LookUpFieldName(const char ** name,const char * field_name,BMessage * names)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
DumpMessageToStream(BMessage * message,BDataIO & stream,int tabCount,BMessage * names)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