BPicture: Fix archive constructor.
[haiku.git] / src / kits / app / PropertyInfo.cpp
blobe09c4863b3476877f42306cd756ff3516fe6c77c
1 /*
2 * Copyright 2001-2005, Haiku.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Marc Flerackers (mflerackers@androme.be)
7 */
10 #include <ByteOrder.h>
11 #include <DataIO.h>
12 #include <Message.h>
13 #include <PropertyInfo.h>
15 #include <string.h>
16 #include <stdio.h>
17 #include <stdlib.h>
20 BPropertyInfo::BPropertyInfo(property_info* propertyInfo, value_info* valueInfo,
21 bool freeOnDelete)
23 fPropInfo(propertyInfo),
24 fValueInfo(valueInfo),
25 fPropCount(0),
26 fInHeap(freeOnDelete),
27 fValueCount(0)
29 if (fPropInfo != NULL) {
30 while (fPropInfo[fPropCount].name)
31 fPropCount++;
34 if (fValueInfo != NULL) {
35 while (fValueInfo[fValueCount].name)
36 fValueCount++;
41 BPropertyInfo::~BPropertyInfo()
43 FreeMem();
47 int32 BPropertyInfo::FindMatch(BMessage* message, int32 index,
48 BMessage* specifier, int32 form, const char* property, void* data) const
50 int32 propertyIndex = 0;
52 while (fPropInfo != NULL && fPropInfo[propertyIndex].name != NULL) {
53 property_info* propertyInfo = fPropInfo + propertyIndex;
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;
61 return propertyIndex;
63 propertyIndex++;
66 return B_ERROR;
70 bool
71 BPropertyInfo::IsFixedSize() const
73 return false;
77 type_code
78 BPropertyInfo::TypeCode() const
80 return B_PROPERTY_INFO_TYPE;
84 ssize_t
85 BPropertyInfo::FlattenedSize() const
87 size_t size = (2 * sizeof(int32)) + 1;
89 if (fPropInfo) {
90 // Main chunks
91 for (int32 pi = 0; fPropInfo[pi].name != NULL; pi++) {
92 size += strlen(fPropInfo[pi].name) + 1;
94 if (fPropInfo[pi].usage)
95 size += strlen(fPropInfo[pi].usage) + 1;
96 else
97 size += sizeof(char);
99 size += sizeof(int32);
101 for (int32 i = 0; i < 10 && fPropInfo[pi].commands[i] != 0; i++)
102 size += sizeof(int32);
103 size += sizeof(int32);
105 for (int32 i = 0; i < 10 && fPropInfo[pi].specifiers[i] != 0; i++)
106 size += sizeof(int32);
107 size += sizeof(int32);
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);
116 for (int32 i = 0; i < 3 && fPropInfo[pi].ctypes[i].pairs[0].name != 0; i++) {
117 for (int32 j = 0; j < 5 && fPropInfo[pi].ctypes[i].pairs[j].name != 0; j++) {
118 size += strlen(fPropInfo[pi].ctypes[i].pairs[j].name) + 1;
119 size += sizeof(int32);
121 size += sizeof(int32);
123 size += sizeof(int32);
127 if (fValueInfo) {
128 size += sizeof(int16);
130 // Chunks
131 for (int32 vi = 0; fValueInfo[vi].name != NULL; vi++) {
132 size += sizeof(int32);
133 size += sizeof(int32);
135 size += strlen(fValueInfo[vi].name) + 1;
137 if (fValueInfo[vi].usage)
138 size += strlen(fValueInfo[vi].usage) + 1;
139 else
140 size += sizeof(char);
142 size += sizeof(int32);
146 return size;
150 status_t
151 BPropertyInfo::Flatten(void* buffer, ssize_t numBytes) const
153 if (numBytes < FlattenedSize())
154 return B_NO_MEMORY;
156 if (buffer == NULL)
157 return B_BAD_VALUE;
159 BMemoryIO flatData(buffer, numBytes);
161 char tmpChar = B_HOST_IS_BENDIAN;
162 int32 tmpInt;
164 flatData.Write(&tmpChar, sizeof(tmpChar));
165 flatData.Write(&fPropCount, sizeof(fPropCount));
166 tmpInt = 0x01 | (fValueInfo ? 0x2 : 0x0);
167 flatData.Write(&tmpInt, sizeof(tmpInt));
169 if (fPropInfo) {
170 // Main chunks
171 for (int32 pi = 0; fPropInfo[pi].name != NULL; pi++) {
172 flatData.Write(fPropInfo[pi].name, strlen(fPropInfo[pi].name) + 1);
173 if (fPropInfo[pi].usage != NULL) {
174 flatData.Write(fPropInfo[pi].usage, strlen(fPropInfo[pi].usage) + 1);
175 } else {
176 tmpChar = 0;
177 flatData.Write(&tmpChar, sizeof(tmpChar));
180 flatData.Write(&fPropInfo[pi].extra_data, sizeof(fPropInfo[pi].extra_data));
182 for (int32 i = 0; i < 10 && fPropInfo[pi].commands[i] != 0; i++) {
183 flatData.Write(&fPropInfo[pi].commands[i], sizeof(fPropInfo[pi].commands[i]));
185 tmpInt = 0;
186 flatData.Write(&tmpInt, sizeof(tmpInt));
188 for (int32 i = 0; i < 10 && fPropInfo[pi].specifiers[i] != 0; i++) {
189 flatData.Write(&fPropInfo[pi].specifiers[i], sizeof(fPropInfo[pi].specifiers[i]));
191 tmpInt = 0;
192 flatData.Write(&tmpInt, sizeof(tmpInt));
195 // Type chunks
196 for (int32 pi = 0; fPropInfo[pi].name != NULL; pi++) {
197 for (int32 i = 0; i < 10 && fPropInfo[pi].types[i] != 0; i++) {
198 flatData.Write(&fPropInfo[pi].types[i], sizeof(fPropInfo[pi].types[i]));
200 tmpInt = 0;
201 flatData.Write(&tmpInt, sizeof(tmpInt));
203 for (int32 i = 0; i < 3 && fPropInfo[pi].ctypes[i].pairs[0].name != 0; i++) {
204 for (int32 j = 0; j < 5 && fPropInfo[pi].ctypes[i].pairs[j].name != 0; j++) {
205 flatData.Write(fPropInfo[pi].ctypes[i].pairs[j].name,
206 strlen(fPropInfo[pi].ctypes[i].pairs[j].name) + 1);
207 flatData.Write(&fPropInfo[pi].ctypes[i].pairs[j].type,
208 sizeof(fPropInfo[pi].ctypes[i].pairs[j].type));
210 tmpInt = 0;
211 flatData.Write(&tmpInt, sizeof(tmpInt));
213 tmpInt = 0;
214 flatData.Write(&tmpInt, sizeof(tmpInt));
218 if (fValueInfo) {
219 // Value Chunks
220 flatData.Write(&fValueCount, sizeof(fValueCount));
221 for (int32 vi = 0; fValueInfo[vi].name != NULL; vi++) {
222 flatData.Write(&fValueInfo[vi].kind, sizeof(fValueInfo[vi].kind));
223 flatData.Write(&fValueInfo[vi].value, sizeof(fValueInfo[vi].value));
224 flatData.Write(fValueInfo[vi].name, strlen(fValueInfo[vi].name) + 1);
225 if (fValueInfo[vi].usage) {
226 flatData.Write(fValueInfo[vi].usage, strlen(fValueInfo[vi].usage) + 1);
227 } else {
228 tmpChar = 0;
229 flatData.Write(&tmpChar, sizeof(tmpChar));
231 flatData.Write(&fValueInfo[vi].extra_data, sizeof(fValueInfo[vi].extra_data));
235 return B_OK;
239 bool
240 BPropertyInfo::AllowsTypeCode(type_code code) const
242 return code == B_PROPERTY_INFO_TYPE;
246 status_t
247 BPropertyInfo::Unflatten(type_code code, const void* buffer,
248 ssize_t numBytes)
250 if (!AllowsTypeCode(code))
251 return B_BAD_TYPE;
253 if (buffer == NULL)
254 return B_BAD_VALUE;
256 FreeMem();
258 BMemoryIO flatData(buffer, numBytes);
259 char tmpChar = B_HOST_IS_BENDIAN;
260 int32 tmpInt;
262 flatData.Read(&tmpChar, sizeof(tmpChar));
263 bool swapRequired = (tmpChar != B_HOST_IS_BENDIAN);
265 flatData.Read(&fPropCount, sizeof(fPropCount));
267 int32 flags;
268 flatData.Read(&flags, sizeof(flags));
269 if (swapRequired) {
270 fPropCount = B_SWAP_INT32(fPropCount);
271 flags = B_SWAP_INT32(flags);
274 if (flags & 1) {
275 fPropInfo = static_cast<property_info *>(malloc(sizeof(property_info) * (fPropCount + 1)));
276 memset(fPropInfo, 0, (fPropCount + 1) * sizeof(property_info));
278 // Main chunks
279 for (int32 pi = 0; pi < fPropCount; pi++) {
280 fPropInfo[pi].name = strdup(static_cast<const char*>(buffer) + flatData.Position());
281 flatData.Seek(strlen(fPropInfo[pi].name) + 1, SEEK_CUR);
283 fPropInfo[pi].usage = strdup(static_cast<const char *>(buffer) + flatData.Position());
284 flatData.Seek(strlen(fPropInfo[pi].usage) + 1, SEEK_CUR);
286 flatData.Read(&fPropInfo[pi].extra_data, sizeof(fPropInfo[pi].extra_data));
287 if (swapRequired) {
288 fPropInfo[pi].extra_data = B_SWAP_INT32(fPropInfo[pi].extra_data);
291 flatData.Read(&tmpInt, sizeof(tmpInt));
292 for (int32 i = 0; tmpInt != 0; i++) {
293 if (swapRequired) {
294 tmpInt = B_SWAP_INT32(tmpInt);
296 fPropInfo[pi].commands[i] = tmpInt;
297 flatData.Read(&tmpInt, sizeof(tmpInt));
300 flatData.Read(&tmpInt, sizeof(tmpInt));
301 for (int32 i = 0; tmpInt != 0; i++) {
302 if (swapRequired) {
303 tmpInt = B_SWAP_INT32(tmpInt);
305 fPropInfo[pi].specifiers[i] = tmpInt;
306 flatData.Read(&tmpInt, sizeof(tmpInt));
310 // Type chunks
311 for (int32 pi = 0; pi < fPropCount; pi++) {
312 flatData.Read(&tmpInt, sizeof(tmpInt));
313 for (int32 i = 0; tmpInt != 0; i++) {
314 if (swapRequired) {
315 tmpInt = B_SWAP_INT32(tmpInt);
317 fPropInfo[pi].types[i] = tmpInt;
318 flatData.Read(&tmpInt, sizeof(tmpInt));
321 flatData.Read(&tmpInt, sizeof(tmpInt));
322 for (int32 i = 0; tmpInt != 0; i++) {
323 for (int32 j = 0; tmpInt != 0; j++) {
324 flatData.Seek(-sizeof(tmpInt), SEEK_CUR);
325 fPropInfo[pi].ctypes[i].pairs[j].name =
326 strdup(static_cast<const char *>(buffer) + flatData.Position());
327 flatData.Seek(strlen(fPropInfo[pi].ctypes[i].pairs[j].name) + 1, SEEK_CUR);
329 flatData.Read(&fPropInfo[pi].ctypes[i].pairs[j].type,
330 sizeof(fPropInfo[pi].ctypes[i].pairs[j].type));
331 if (swapRequired) {
332 fPropInfo[pi].ctypes[i].pairs[j].type =
333 B_SWAP_INT32(fPropInfo[pi].ctypes[i].pairs[j].type);
335 flatData.Read(&tmpInt, sizeof(tmpInt));
337 flatData.Read(&tmpInt, sizeof(tmpInt));
342 if (flags & 2) {
343 flatData.Read(&fValueCount, sizeof(fValueCount));
344 if (swapRequired) {
345 fValueCount = B_SWAP_INT16(fValueCount);
348 fValueInfo = static_cast<value_info *>(malloc(sizeof(value_info) * (fValueCount + 1)));
349 memset(fValueInfo, 0, (fValueCount + 1) * sizeof(value_info));
351 for (int32 vi = 0; vi < fValueCount; vi++) {
352 flatData.Read(&fValueInfo[vi].kind, sizeof(fValueInfo[vi].kind));
353 flatData.Read(&fValueInfo[vi].value, sizeof(fValueInfo[vi].value));
355 fValueInfo[vi].name = strdup(static_cast<const char *>(buffer) + flatData.Position());
356 flatData.Seek(strlen(fValueInfo[vi].name) + 1, SEEK_CUR);
358 fValueInfo[vi].usage = strdup(static_cast<const char *>(buffer) + flatData.Position());
359 flatData.Seek(strlen(fValueInfo[vi].usage) + 1, SEEK_CUR);
361 flatData.Read(&fValueInfo[vi].extra_data, sizeof(fValueInfo[vi].extra_data));
362 if (swapRequired) {
363 fValueInfo[vi].kind = static_cast<value_kind>(B_SWAP_INT32(fValueInfo[vi].kind));
364 fValueInfo[vi].value = B_SWAP_INT32(fValueInfo[vi].value);
365 fValueInfo[vi].extra_data = B_SWAP_INT32(fValueInfo[vi].extra_data);
370 return B_OK;
374 const property_info*
375 BPropertyInfo::Properties() const
377 return fPropInfo;
381 const value_info*
382 BPropertyInfo::Values() const
384 return fValueInfo;
388 int32
389 BPropertyInfo::CountProperties() const
391 return fPropCount;
395 int32
396 BPropertyInfo::CountValues() const
398 return fValueCount;
402 void
403 BPropertyInfo::PrintToStream() const
405 printf(" property commands types specifiers\n");
406 printf("--------------------------------------------------------------------------------\n");
408 for (int32 pi = 0; fPropInfo[pi].name != 0; pi++) {
409 // property
410 printf("%14s", fPropInfo[pi].name);
411 // commands
412 for (int32 i = 0; i < 10 && fPropInfo[pi].commands[i] != 0; i++) {
413 uint32 command = fPropInfo[pi].commands[i];
415 printf(" %c%c%c%-28c", int(command & 0xFF000000) >> 24,
416 int(command & 0xFF0000) >> 16, int(command & 0xFF00) >> 8,
417 int(command) & 0xFF);
419 // types
420 for (int32 i = 0; i < 10 && fPropInfo[pi].types[i] != 0; i++) {
421 uint32 type = fPropInfo[pi].types[i];
423 printf("%c%c%c%c", int(type & 0xFF000000) >> 24,
424 int(type & 0xFF0000) >> 16, int(type & 0xFF00) >> 8, (int)type & 0xFF);
426 // specifiers
427 for (int32 i = 0; i < 10 && fPropInfo[pi].specifiers[i] != 0; i++) {
428 uint32 spec = fPropInfo[pi].specifiers[i];
429 printf("%" B_PRIu32, spec);
431 printf("\n");
436 bool
437 BPropertyInfo::FindCommand(uint32 what, int32 index, property_info *propertyInfo)
439 bool result = false;
441 if (propertyInfo->commands[0] == 0) {
442 result = true;
443 } else if (index == 0) {
444 for (int32 i = 0; i < 10 && propertyInfo->commands[i] != 0; i++) {
445 if (propertyInfo->commands[i] == what) {
446 result = true;
447 break;
452 return result;
456 bool
457 BPropertyInfo::FindSpecifier(uint32 form, property_info *propertyInfo)
459 bool result = false;
461 if (propertyInfo->specifiers[0] == 0) {
462 result = true;
463 } else {
464 for (int32 i = 0; i < 10 && propertyInfo->specifiers[i] != 0; i++) {
465 if (propertyInfo->specifiers[i] == form) {
466 result = true;
467 break;
472 return result;
476 void BPropertyInfo::_ReservedPropertyInfo1() {}
477 void BPropertyInfo::_ReservedPropertyInfo2() {}
478 void BPropertyInfo::_ReservedPropertyInfo3() {}
479 void BPropertyInfo::_ReservedPropertyInfo4() {}
482 BPropertyInfo::BPropertyInfo(const BPropertyInfo &)
487 BPropertyInfo&
488 BPropertyInfo::operator=(const BPropertyInfo &)
490 return *this;
494 void
495 BPropertyInfo::FreeMem()
497 int i, j, k;
499 if (!fInHeap)
500 return;
502 if (fPropInfo != NULL) {
503 for (i = 0; i < fPropCount; i++) {
504 free((char *)fPropInfo[i].name);
505 free((char *)fPropInfo[i].usage);
507 for (j = 0; j < 3; j++) {
508 for (k = 0; k < 5; k++) {
509 if (fPropInfo[i].ctypes[j].pairs[k].name == NULL)
510 break;
512 free((char *)fPropInfo[i].ctypes[j].pairs[k].name);
515 if (fPropInfo[i].ctypes[j].pairs[0].name == NULL)
516 break;
519 free(fPropInfo);
520 fPropInfo = NULL;
521 fPropCount = 0;
524 if (fValueInfo != NULL) {
525 for (i = 0; i < fValueCount; i++) {
526 free((char *)fValueInfo[i].name);
527 free((char *)fValueInfo[i].usage);
529 free(fValueInfo);
530 fValueInfo = NULL;
531 fValueCount = 0;
534 fInHeap = false;