xref: /haiku/src/kits/app/PropertyInfo.cpp (revision a3e794ae459fec76826407f8ba8c94cd3535f128)
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 
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 
41 BPropertyInfo::~BPropertyInfo()
42 {
43 	FreeMem();
44 }
45 
46 
47 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
71 BPropertyInfo::IsFixedSize() const
72 {
73 	return false;
74 }
75 
76 
77 type_code
78 BPropertyInfo::TypeCode() const
79 {
80 	return B_PROPERTY_INFO_TYPE;
81 }
82 
83 
84 ssize_t
85 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
153 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
252 BPropertyInfo::AllowsTypeCode(type_code code) const
253 {
254 	return code == B_PROPERTY_INFO_TYPE;
255 }
256 
257 
258 status_t
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*
400 BPropertyInfo::Properties() const
401 {
402 	return fPropInfo;
403 }
404 
405 
406 const value_info*
407 BPropertyInfo::Values() const
408 {
409 	return fValueInfo;
410 }
411 
412 
413 int32
414 BPropertyInfo::CountProperties() const
415 {
416 	return fPropCount;
417 }
418 
419 
420 int32
421 BPropertyInfo::CountValues() const
422 {
423 	return fValueCount;
424 }
425 
426 
427 void
428 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
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
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 
505 void BPropertyInfo::_ReservedPropertyInfo1() {}
506 void BPropertyInfo::_ReservedPropertyInfo2() {}
507 void BPropertyInfo::_ReservedPropertyInfo3() {}
508 void BPropertyInfo::_ReservedPropertyInfo4() {}
509 
510 
511 BPropertyInfo::BPropertyInfo(const BPropertyInfo &)
512 {
513 }
514 
515 
516 BPropertyInfo&
517 BPropertyInfo::operator=(const BPropertyInfo &)
518 {
519 	return *this;
520 }
521 
522 
523 void
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