1 /*
2 * Copyright 2001-2005 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Marc Flerackers (mflerackers@androme.be)
7 */
8
9
10 #include <ByteOrder.h>
11 #include <DataIO.h>
12 #include <Message.h>
13 #include <PropertyInfo.h>
14
15 #include <string.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18
19
BPropertyInfo(property_info * propertyInfo,value_info * valueInfo,bool freeOnDelete)20 BPropertyInfo::BPropertyInfo(property_info* propertyInfo, value_info* valueInfo,
21 bool freeOnDelete)
22 :
23 fPropInfo(propertyInfo),
24 fValueInfo(valueInfo),
25 fPropCount(0),
26 fInHeap(freeOnDelete),
27 fValueCount(0)
28 {
29 if (fPropInfo != NULL) {
30 while (fPropInfo[fPropCount].name)
31 fPropCount++;
32 }
33
34 if (fValueInfo != NULL) {
35 while (fValueInfo[fValueCount].name)
36 fValueCount++;
37 }
38 }
39
40
~BPropertyInfo()41 BPropertyInfo::~BPropertyInfo()
42 {
43 FreeMem();
44 }
45
46
FindMatch(BMessage * message,int32 index,BMessage * specifier,int32 form,const char * property,void * data) const47 int32 BPropertyInfo::FindMatch(BMessage* message, int32 index,
48 BMessage* specifier, int32 form, const char* property, void* data) const
49 {
50 int32 propertyIndex = 0;
51
52 while (fPropInfo != NULL && fPropInfo[propertyIndex].name != NULL) {
53 property_info* propertyInfo = fPropInfo + propertyIndex;
54
55 if (!strcmp(propertyInfo->name, property)
56 && FindCommand(message->what, index, propertyInfo)
57 && FindSpecifier(form, propertyInfo)) {
58 if (data)
59 *((uint32*)data) = propertyInfo->extra_data;
60
61 return propertyIndex;
62 }
63 propertyIndex++;
64 }
65
66 return B_ERROR;
67 }
68
69
70 bool
IsFixedSize() const71 BPropertyInfo::IsFixedSize() const
72 {
73 return false;
74 }
75
76
77 type_code
TypeCode() const78 BPropertyInfo::TypeCode() const
79 {
80 return B_PROPERTY_INFO_TYPE;
81 }
82
83
84 ssize_t
FlattenedSize() const85 BPropertyInfo::FlattenedSize() const
86 {
87 size_t size = (2 * sizeof(int32)) + 1;
88
89 if (fPropInfo) {
90 // Main chunks
91 for (int32 pi = 0; fPropInfo[pi].name != NULL; pi++) {
92 size += strlen(fPropInfo[pi].name) + 1;
93
94 if (fPropInfo[pi].usage)
95 size += strlen(fPropInfo[pi].usage) + 1;
96 else
97 size += sizeof(char);
98
99 size += sizeof(int32);
100
101 for (int32 i = 0; i < 10 && fPropInfo[pi].commands[i] != 0; i++)
102 size += sizeof(int32);
103 size += sizeof(int32);
104
105 for (int32 i = 0; i < 10 && fPropInfo[pi].specifiers[i] != 0; i++)
106 size += sizeof(int32);
107 size += sizeof(int32);
108 }
109
110 // Type chunks
111 for (int32 pi = 0; fPropInfo[pi].name != NULL; pi++) {
112 for (int32 i = 0; i < 10 && fPropInfo[pi].types[i] != 0; i++)
113 size += sizeof(int32);
114 size += sizeof(int32);
115
116 for (int32 i = 0; i < 3
117 && fPropInfo[pi].ctypes[i].pairs[0].name != 0; i++) {
118 for (int32 j = 0; j < 5
119 && fPropInfo[pi].ctypes[i].pairs[j].name != 0; j++) {
120 size += strlen(fPropInfo[pi].ctypes[i].pairs[j].name) + 1;
121 size += sizeof(int32);
122 }
123 size += sizeof(int32);
124 }
125 size += sizeof(int32);
126 }
127 }
128
129 if (fValueInfo) {
130 size += sizeof(int16);
131
132 // Chunks
133 for (int32 vi = 0; fValueInfo[vi].name != NULL; vi++) {
134 size += sizeof(int32);
135 size += sizeof(int32);
136
137 size += strlen(fValueInfo[vi].name) + 1;
138
139 if (fValueInfo[vi].usage)
140 size += strlen(fValueInfo[vi].usage) + 1;
141 else
142 size += sizeof(char);
143
144 size += sizeof(int32);
145 }
146 }
147
148 return size;
149 }
150
151
152 status_t
Flatten(void * buffer,ssize_t numBytes) const153 BPropertyInfo::Flatten(void* buffer, ssize_t numBytes) const
154 {
155 if (numBytes < FlattenedSize())
156 return B_NO_MEMORY;
157
158 if (buffer == NULL)
159 return B_BAD_VALUE;
160
161 BMemoryIO flatData(buffer, numBytes);
162
163 char tmpChar = B_HOST_IS_BENDIAN;
164 int32 tmpInt;
165
166 flatData.Write(&tmpChar, sizeof(tmpChar));
167 flatData.Write(&fPropCount, sizeof(fPropCount));
168 tmpInt = 0x01 | (fValueInfo ? 0x2 : 0x0);
169 flatData.Write(&tmpInt, sizeof(tmpInt));
170
171 if (fPropInfo) {
172 // Main chunks
173 for (int32 pi = 0; fPropInfo[pi].name != NULL; pi++) {
174 flatData.Write(fPropInfo[pi].name, strlen(fPropInfo[pi].name) + 1);
175 if (fPropInfo[pi].usage != NULL) {
176 flatData.Write(fPropInfo[pi].usage, strlen(fPropInfo[pi].usage)
177 + 1);
178 } else {
179 tmpChar = 0;
180 flatData.Write(&tmpChar, sizeof(tmpChar));
181 }
182
183 flatData.Write(&fPropInfo[pi].extra_data,
184 sizeof(fPropInfo[pi].extra_data));
185
186 for (int32 i = 0; i < 10 && fPropInfo[pi].commands[i] != 0; i++) {
187 flatData.Write(&fPropInfo[pi].commands[i],
188 sizeof(fPropInfo[pi].commands[i]));
189 }
190 tmpInt = 0;
191 flatData.Write(&tmpInt, sizeof(tmpInt));
192
193 for (int32 i = 0; i < 10 && fPropInfo[pi].specifiers[i] != 0; i++) {
194 flatData.Write(&fPropInfo[pi].specifiers[i],
195 sizeof(fPropInfo[pi].specifiers[i]));
196 }
197 tmpInt = 0;
198 flatData.Write(&tmpInt, sizeof(tmpInt));
199 }
200
201 // Type chunks
202 for (int32 pi = 0; fPropInfo[pi].name != NULL; pi++) {
203 for (int32 i = 0; i < 10 && fPropInfo[pi].types[i] != 0; i++) {
204 flatData.Write(&fPropInfo[pi].types[i],
205 sizeof(fPropInfo[pi].types[i]));
206 }
207 tmpInt = 0;
208 flatData.Write(&tmpInt, sizeof(tmpInt));
209
210 for (int32 i = 0; i < 3
211 && fPropInfo[pi].ctypes[i].pairs[0].name != 0; i++) {
212 for (int32 j = 0; j < 5
213 && fPropInfo[pi].ctypes[i].pairs[j].name != 0; j++) {
214 flatData.Write(fPropInfo[pi].ctypes[i].pairs[j].name,
215 strlen(fPropInfo[pi].ctypes[i].pairs[j].name) + 1);
216 flatData.Write(&fPropInfo[pi].ctypes[i].pairs[j].type,
217 sizeof(fPropInfo[pi].ctypes[i].pairs[j].type));
218 }
219 tmpInt = 0;
220 flatData.Write(&tmpInt, sizeof(tmpInt));
221 }
222 tmpInt = 0;
223 flatData.Write(&tmpInt, sizeof(tmpInt));
224 }
225 }
226
227 if (fValueInfo) {
228 // Value Chunks
229 flatData.Write(&fValueCount, sizeof(fValueCount));
230 for (int32 vi = 0; fValueInfo[vi].name != NULL; vi++) {
231 flatData.Write(&fValueInfo[vi].kind, sizeof(fValueInfo[vi].kind));
232 flatData.Write(&fValueInfo[vi].value, sizeof(fValueInfo[vi].value));
233 flatData.Write(fValueInfo[vi].name, strlen(fValueInfo[vi].name)
234 + 1);
235 if (fValueInfo[vi].usage) {
236 flatData.Write(fValueInfo[vi].usage,
237 strlen(fValueInfo[vi].usage) + 1);
238 } else {
239 tmpChar = 0;
240 flatData.Write(&tmpChar, sizeof(tmpChar));
241 }
242 flatData.Write(&fValueInfo[vi].extra_data,
243 sizeof(fValueInfo[vi].extra_data));
244 }
245 }
246
247 return B_OK;
248 }
249
250
251 bool
AllowsTypeCode(type_code code) const252 BPropertyInfo::AllowsTypeCode(type_code code) const
253 {
254 return code == B_PROPERTY_INFO_TYPE;
255 }
256
257
258 status_t
Unflatten(type_code code,const void * buffer,ssize_t numBytes)259 BPropertyInfo::Unflatten(type_code code, const void* buffer,
260 ssize_t numBytes)
261 {
262 if (!AllowsTypeCode(code))
263 return B_BAD_TYPE;
264
265 if (buffer == NULL)
266 return B_BAD_VALUE;
267
268 FreeMem();
269
270 BMemoryIO flatData(buffer, numBytes);
271 char tmpChar = B_HOST_IS_BENDIAN;
272 int32 tmpInt;
273
274 flatData.Read(&tmpChar, sizeof(tmpChar));
275 bool swapRequired = (tmpChar != B_HOST_IS_BENDIAN);
276
277 flatData.Read(&fPropCount, sizeof(fPropCount));
278
279 int32 flags;
280 flatData.Read(&flags, sizeof(flags));
281 if (swapRequired) {
282 fPropCount = B_SWAP_INT32(fPropCount);
283 flags = B_SWAP_INT32(flags);
284 }
285
286 if (flags & 1) {
287 fPropInfo = static_cast<property_info *>(malloc(sizeof(property_info)
288 * (fPropCount + 1)));
289 memset(fPropInfo, 0, (fPropCount + 1) * sizeof(property_info));
290
291 // Main chunks
292 for (int32 pi = 0; pi < fPropCount; pi++) {
293 fPropInfo[pi].name = strdup(static_cast<const char*>(buffer)
294 + flatData.Position());
295 flatData.Seek(strlen(fPropInfo[pi].name) + 1, SEEK_CUR);
296
297 fPropInfo[pi].usage = strdup(static_cast<const char *>(buffer)
298 + flatData.Position());
299 flatData.Seek(strlen(fPropInfo[pi].usage) + 1, SEEK_CUR);
300
301 flatData.Read(&fPropInfo[pi].extra_data,
302 sizeof(fPropInfo[pi].extra_data));
303 if (swapRequired) {
304 fPropInfo[pi].extra_data
305 = B_SWAP_INT32(fPropInfo[pi].extra_data);
306 }
307
308 flatData.Read(&tmpInt, sizeof(tmpInt));
309 for (int32 i = 0; tmpInt != 0; i++) {
310 if (swapRequired) {
311 tmpInt = B_SWAP_INT32(tmpInt);
312 }
313 fPropInfo[pi].commands[i] = tmpInt;
314 flatData.Read(&tmpInt, sizeof(tmpInt));
315 }
316
317 flatData.Read(&tmpInt, sizeof(tmpInt));
318 for (int32 i = 0; tmpInt != 0; i++) {
319 if (swapRequired) {
320 tmpInt = B_SWAP_INT32(tmpInt);
321 }
322 fPropInfo[pi].specifiers[i] = tmpInt;
323 flatData.Read(&tmpInt, sizeof(tmpInt));
324 }
325 }
326
327 // Type chunks
328 for (int32 pi = 0; pi < fPropCount; pi++) {
329 flatData.Read(&tmpInt, sizeof(tmpInt));
330 for (int32 i = 0; tmpInt != 0; i++) {
331 if (swapRequired) {
332 tmpInt = B_SWAP_INT32(tmpInt);
333 }
334 fPropInfo[pi].types[i] = tmpInt;
335 flatData.Read(&tmpInt, sizeof(tmpInt));
336 }
337
338 flatData.Read(&tmpInt, sizeof(tmpInt));
339 for (int32 i = 0; tmpInt != 0; i++) {
340 for (int32 j = 0; tmpInt != 0; j++) {
341 flatData.Seek(-sizeof(tmpInt), SEEK_CUR);
342 fPropInfo[pi].ctypes[i].pairs[j].name =
343 strdup(static_cast<const char *>(buffer)
344 + flatData.Position());
345 flatData.Seek(strlen(fPropInfo[pi].ctypes[i].pairs[j].name)
346 + 1, SEEK_CUR);
347
348 flatData.Read(&fPropInfo[pi].ctypes[i].pairs[j].type,
349 sizeof(fPropInfo[pi].ctypes[i].pairs[j].type));
350 if (swapRequired) {
351 fPropInfo[pi].ctypes[i].pairs[j].type =
352 B_SWAP_INT32(fPropInfo[pi].ctypes[i].pairs[j].type);
353 }
354 flatData.Read(&tmpInt, sizeof(tmpInt));
355 }
356 flatData.Read(&tmpInt, sizeof(tmpInt));
357 }
358 }
359 }
360
361 if (flags & 2) {
362 flatData.Read(&fValueCount, sizeof(fValueCount));
363 if (swapRequired) {
364 fValueCount = B_SWAP_INT16(fValueCount);
365 }
366
367 fValueInfo = static_cast<value_info *>(malloc(sizeof(value_info)
368 * (fValueCount + 1)));
369 memset(fValueInfo, 0, (fValueCount + 1) * sizeof(value_info));
370
371 for (int32 vi = 0; vi < fValueCount; vi++) {
372 flatData.Read(&fValueInfo[vi].kind, sizeof(fValueInfo[vi].kind));
373 flatData.Read(&fValueInfo[vi].value, sizeof(fValueInfo[vi].value));
374
375 fValueInfo[vi].name = strdup(static_cast<const char *>(buffer)
376 + flatData.Position());
377 flatData.Seek(strlen(fValueInfo[vi].name) + 1, SEEK_CUR);
378
379 fValueInfo[vi].usage = strdup(static_cast<const char *>(buffer)
380 + flatData.Position());
381 flatData.Seek(strlen(fValueInfo[vi].usage) + 1, SEEK_CUR);
382
383 flatData.Read(&fValueInfo[vi].extra_data,
384 sizeof(fValueInfo[vi].extra_data));
385 if (swapRequired) {
386 fValueInfo[vi].kind = static_cast<value_kind>(
387 B_SWAP_INT32(fValueInfo[vi].kind));
388 fValueInfo[vi].value = B_SWAP_INT32(fValueInfo[vi].value);
389 fValueInfo[vi].extra_data
390 = B_SWAP_INT32(fValueInfo[vi].extra_data);
391 }
392 }
393 }
394
395 return B_OK;
396 }
397
398
399 const property_info*
Properties() const400 BPropertyInfo::Properties() const
401 {
402 return fPropInfo;
403 }
404
405
406 const value_info*
Values() const407 BPropertyInfo::Values() const
408 {
409 return fValueInfo;
410 }
411
412
413 int32
CountProperties() const414 BPropertyInfo::CountProperties() const
415 {
416 return fPropCount;
417 }
418
419
420 int32
CountValues() const421 BPropertyInfo::CountValues() const
422 {
423 return fValueCount;
424 }
425
426
427 void
PrintToStream() const428 BPropertyInfo::PrintToStream() const
429 {
430 printf(" property commands types "
431 " specifiers\n");
432 printf("-------------------------------------------------------------------"
433 "-------------\n");
434
435 for (int32 pi = 0; fPropInfo[pi].name != 0; pi++) {
436 // property
437 printf("%14s", fPropInfo[pi].name);
438 // commands
439 for (int32 i = 0; i < 10 && fPropInfo[pi].commands[i] != 0; i++) {
440 uint32 command = fPropInfo[pi].commands[i];
441
442 printf(" %c%c%c%-28c", int(command & 0xFF000000) >> 24,
443 int(command & 0xFF0000) >> 16, int(command & 0xFF00) >> 8,
444 int(command) & 0xFF);
445 }
446 // types
447 for (int32 i = 0; i < 10 && fPropInfo[pi].types[i] != 0; i++) {
448 uint32 type = fPropInfo[pi].types[i];
449
450 printf("%c%c%c%c", int(type & 0xFF000000) >> 24,
451 int(type & 0xFF0000) >> 16, int(type & 0xFF00) >> 8,
452 (int)type & 0xFF);
453 }
454 // specifiers
455 for (int32 i = 0; i < 10 && fPropInfo[pi].specifiers[i] != 0; i++) {
456 uint32 spec = fPropInfo[pi].specifiers[i];
457 printf("%" B_PRIu32, spec);
458 }
459 printf("\n");
460 }
461 }
462
463
464 bool
FindCommand(uint32 what,int32 index,property_info * propertyInfo)465 BPropertyInfo::FindCommand(uint32 what, int32 index,
466 property_info* propertyInfo)
467 {
468 bool result = false;
469
470 if (propertyInfo->commands[0] == 0) {
471 result = true;
472 } else if (index == 0) {
473 for (int32 i = 0; i < 10 && propertyInfo->commands[i] != 0; i++) {
474 if (propertyInfo->commands[i] == what) {
475 result = true;
476 break;
477 }
478 }
479 }
480
481 return result;
482 }
483
484
485 bool
FindSpecifier(uint32 form,property_info * propertyInfo)486 BPropertyInfo::FindSpecifier(uint32 form, property_info* propertyInfo)
487 {
488 bool result = false;
489
490 if (propertyInfo->specifiers[0] == 0) {
491 result = true;
492 } else {
493 for (int32 i = 0; i < 10 && propertyInfo->specifiers[i] != 0; i++) {
494 if (propertyInfo->specifiers[i] == form) {
495 result = true;
496 break;
497 }
498 }
499 }
500
501 return result;
502 }
503
504
_ReservedPropertyInfo1()505 void BPropertyInfo::_ReservedPropertyInfo1() {}
_ReservedPropertyInfo2()506 void BPropertyInfo::_ReservedPropertyInfo2() {}
_ReservedPropertyInfo3()507 void BPropertyInfo::_ReservedPropertyInfo3() {}
_ReservedPropertyInfo4()508 void BPropertyInfo::_ReservedPropertyInfo4() {}
509
510
BPropertyInfo(const BPropertyInfo &)511 BPropertyInfo::BPropertyInfo(const BPropertyInfo &)
512 {
513 }
514
515
516 BPropertyInfo&
operator =(const BPropertyInfo &)517 BPropertyInfo::operator=(const BPropertyInfo &)
518 {
519 return *this;
520 }
521
522
523 void
FreeMem()524 BPropertyInfo::FreeMem()
525 {
526 int i, j, k;
527
528 if (!fInHeap)
529 return;
530
531 if (fPropInfo != NULL) {
532 for (i = 0; i < fPropCount; i++) {
533 free((char *)fPropInfo[i].name);
534 free((char *)fPropInfo[i].usage);
535
536 for (j = 0; j < 3; j++) {
537 for (k = 0; k < 5; k++) {
538 if (fPropInfo[i].ctypes[j].pairs[k].name == NULL)
539 break;
540
541 free((char *)fPropInfo[i].ctypes[j].pairs[k].name);
542 }
543
544 if (fPropInfo[i].ctypes[j].pairs[0].name == NULL)
545 break;
546 }
547 }
548 free(fPropInfo);
549 fPropInfo = NULL;
550 fPropCount = 0;
551 }
552
553 if (fValueInfo != NULL) {
554 for (i = 0; i < fValueCount; i++) {
555 free((char *)fValueInfo[i].name);
556 free((char *)fValueInfo[i].usage);
557 }
558 free(fValueInfo);
559 fValueInfo = NULL;
560 fValueCount = 0;
561 }
562
563 fInHeap = false;
564 }
565