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