xref: /haiku/src/kits/app/PropertyInfo.cpp (revision 5d9e40fe9252c8f9c5e5e41594545bfa4419fcc7)
1 //------------------------------------------------------------------------------
2 //	Copyright (c) 2001-2002, OpenBeOS
3 //
4 //	Permission is hereby granted, free of charge, to any person obtaining a
5 //	copy of this software and associated documentation files (the "Software"),
6 //	to deal in the Software without restriction, including without limitation
7 //	the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 //	and/or sell copies of the Software, and to permit persons to whom the
9 //	Software is furnished to do so, subject to the following conditions:
10 //
11 //	The above copyright notice and this permission notice shall be included in
12 //	all copies or substantial portions of the Software.
13 //
14 //	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 //	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 //	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 //	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 //	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 //	FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 //	DEALINGS IN THE SOFTWARE.
21 //
22 //	File Name:		PropertyInfo.h
23 //	Author:			Marc Flerackers (mflerackers@androme.be)
24 //	Description:	Utility class for maintain scripting information.
25 //------------------------------------------------------------------------------
26 
27 // Standard Includes -----------------------------------------------------------
28 
29 // System Includes -------------------------------------------------------------
30 #include <PropertyInfo.h>
31 #include <Message.h>
32 #include <Errors.h>
33 #include <ByteOrder.h>
34 #include <DataIO.h>
35 #include <string.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 
39 // Project Includes ------------------------------------------------------------
40 
41 // Local Includes --------------------------------------------------------------
42 
43 // Local Defines ---------------------------------------------------------------
44 
45 // Globals ---------------------------------------------------------------------
46 
47 //------------------------------------------------------------------------------
48 BPropertyInfo::BPropertyInfo(property_info *p, value_info *ci,
49 							 bool free_on_delete)
50 	:	fPropInfo(p),
51 		fValueInfo(ci),
52 		fPropCount(0),
53 		fInHeap(free_on_delete),
54 		fValueCount(0)
55 {
56 	if (fPropInfo)
57 	{
58 		while (fPropInfo[fPropCount].name)
59 			fPropCount++;
60 	}
61 
62 	if (fValueInfo)
63 	{
64 		while (fValueInfo[fValueCount].name)
65 			fValueCount++;
66 	}
67 }
68 //------------------------------------------------------------------------------
69 BPropertyInfo::~BPropertyInfo()
70 {
71 	FreeMem();
72 }
73 //------------------------------------------------------------------------------
74 int32 BPropertyInfo::FindMatch(BMessage *msg, int32 index, BMessage *spec,
75 							   int32 form, const char *prop, void *data) const
76 {
77 	int32 property_index = 0;
78 
79 	while ((fPropInfo != NULL) && (fPropInfo[property_index].name)) {
80 		property_info *propInfo = fPropInfo + property_index;
81 
82 		if ((strcmp(propInfo->name, prop) == 0) &&
83 		    (FindCommand(msg->what, index, propInfo)) &&
84 		    (FindSpecifier(form, propInfo))) {
85 			if (data)
86 				*((uint32*)data) = propInfo->extra_data;
87 			return property_index;
88 		}
89 		property_index++;
90 	}
91 
92 	return B_ERROR;
93 }
94 //------------------------------------------------------------------------------
95 bool BPropertyInfo::IsFixedSize() const
96 {
97 	return false;
98 }
99 //------------------------------------------------------------------------------
100 type_code BPropertyInfo::TypeCode() const
101 {
102 	return B_PROPERTY_INFO_TYPE;
103 }
104 //------------------------------------------------------------------------------
105 ssize_t BPropertyInfo::FlattenedSize() const
106 {
107 	size_t size = (2 * sizeof(int32)) + 1;
108 
109 	if (fPropInfo)
110 	{
111 		// Main chunks
112 		for (int32 pi = 0; fPropInfo[pi].name != NULL; pi++)
113 		{
114 			size += strlen(fPropInfo[pi].name) + 1;
115 
116 			if (fPropInfo[pi].usage)
117 				size += strlen(fPropInfo[pi].usage) + 1;
118 			else
119 				size += sizeof(char);
120 
121 			size += sizeof(int32);
122 
123 			for (int32 i = 0; i < 10 && fPropInfo[pi].commands[i] != 0; i++)
124 				size += sizeof(int32);
125 			size += sizeof(int32);
126 
127 			for (int32 i = 0; i < 10 && fPropInfo[pi].specifiers[i] != 0; i++)
128 				size += sizeof(int32);
129 			size += sizeof(int32);
130 		}
131 
132 		// Type chunks
133 		for (int32 pi = 0; fPropInfo[pi].name != NULL; pi++)
134 		{
135 			for (int32 i = 0; i < 10 && fPropInfo[pi].types[i] != 0; i++)
136 				size += sizeof(int32);
137 			size += sizeof(int32);
138 
139 			for (int32 i = 0; i < 3 && fPropInfo[pi].ctypes[i].pairs[0].name != 0; i++)
140 			{
141 				for (int32 j = 0; j < 5 && fPropInfo[pi].ctypes[i].pairs[j].name != 0; j++)
142 				{
143 					size += strlen(fPropInfo[pi].ctypes[i].pairs[j].name) + 1;
144 					size += sizeof(int32);
145 				}
146 				size += sizeof(int32);
147 			}
148 			size += sizeof(int32);
149 		}
150 	}
151 
152 	if (fValueInfo)
153 	{
154 		size += sizeof(int16);
155 
156 		// Chunks
157 		for (int32 vi = 0; fValueInfo[vi].name != NULL; vi++)
158 		{
159 			size += sizeof(int32);
160 			size += sizeof(int32);
161 
162 			size += strlen(fValueInfo[vi].name) + 1;
163 
164 			if (fValueInfo[vi].usage)
165 				size += strlen(fValueInfo[vi].usage) + 1;
166 			else
167 				size += sizeof(char);
168 
169 			size += sizeof(int32);
170 		}
171 	}
172 
173 	return size;
174 }
175 //------------------------------------------------------------------------------
176 status_t BPropertyInfo::Flatten(void *buffer, ssize_t numBytes) const
177 {
178 	if (numBytes < FlattenedSize())
179 		return B_NO_MEMORY;
180 
181 	if (buffer == NULL)
182 		return B_BAD_VALUE;
183 
184 	BMemoryIO flatData(buffer, numBytes);
185 
186 	char tmpChar = B_HOST_IS_BENDIAN;
187 	int32 tmpInt;
188 
189 	flatData.Write(&tmpChar, sizeof(tmpChar));
190 	flatData.Write(&fPropCount, sizeof(fPropCount));
191 	tmpInt = 0x01 | (fValueInfo ? 0x2 : 0x0);
192 	flatData.Write(&tmpInt, sizeof(tmpInt));
193 
194 	if (fPropInfo) { // Main chunks
195 		for (int32 pi = 0; fPropInfo[pi].name != NULL; pi++) {
196 			flatData.Write(fPropInfo[pi].name, strlen(fPropInfo[pi].name) + 1);
197 			if (fPropInfo[pi].usage != NULL) {
198 				flatData.Write(fPropInfo[pi].usage, strlen(fPropInfo[pi].usage) + 1);
199 			}
200 			else {
201 				tmpChar = 0;
202 				flatData.Write(&tmpChar, sizeof(tmpChar));
203 			}
204 
205 			flatData.Write(&fPropInfo[pi].extra_data, sizeof(fPropInfo[pi].extra_data));
206 
207 			for (int32 i = 0; i < 10 && fPropInfo[pi].commands[i] != 0; i++) {
208 				flatData.Write(&fPropInfo[pi].commands[i], sizeof(fPropInfo[pi].commands[i]));
209 			}
210 			tmpInt = 0;
211 			flatData.Write(&tmpInt, sizeof(tmpInt));
212 
213 			for (int32 i = 0; i < 10 && fPropInfo[pi].specifiers[i] != 0; i++) {
214 				flatData.Write(&fPropInfo[pi].specifiers[i], sizeof(fPropInfo[pi].specifiers[i]));
215 			}
216 			tmpInt = 0;
217 			flatData.Write(&tmpInt, sizeof(tmpInt));
218 		}
219 
220 		// Type chunks
221 		for (int32 pi = 0; fPropInfo[pi].name != NULL; pi++) {
222 			for (int32 i = 0; i < 10 && fPropInfo[pi].types[i] != 0; i++) {
223 				flatData.Write(&fPropInfo[pi].types[i], sizeof(fPropInfo[pi].types[i]));
224 			}
225 			tmpInt = 0;
226 			flatData.Write(&tmpInt, sizeof(tmpInt));
227 
228 			for (int32 i = 0; i < 3 && fPropInfo[pi].ctypes[i].pairs[0].name != 0; i++) {
229 				for (int32 j = 0; j < 5 && fPropInfo[pi].ctypes[i].pairs[j].name != 0; j++) {
230 					flatData.Write(fPropInfo[pi].ctypes[i].pairs[j].name,
231 					               strlen(fPropInfo[pi].ctypes[i].pairs[j].name) + 1);
232 					flatData.Write(&fPropInfo[pi].ctypes[i].pairs[j].type,
233 					               sizeof(fPropInfo[pi].ctypes[i].pairs[j].type));
234 				}
235 				tmpInt = 0;
236 				flatData.Write(&tmpInt, sizeof(tmpInt));
237 			}
238 			tmpInt = 0;
239 			flatData.Write(&tmpInt, sizeof(tmpInt));
240 		}
241 	}
242 
243 	if (fValueInfo) {
244 		// Value Chunks
245 		flatData.Write(&fValueCount, sizeof(fValueCount));
246 		for (int32 vi = 0; fValueInfo[vi].name != NULL; vi++) {
247 			flatData.Write(&fValueInfo[vi].kind, sizeof(fValueInfo[vi].kind));
248 			flatData.Write(&fValueInfo[vi].value, sizeof(fValueInfo[vi].value));
249 			flatData.Write(fValueInfo[vi].name, strlen(fValueInfo[vi].name) + 1);
250 			if (fValueInfo[vi].usage) {
251 				flatData.Write(fValueInfo[vi].usage, strlen(fValueInfo[vi].usage) + 1);
252 			}
253 			else {
254 				tmpChar = 0;
255 				flatData.Write(&tmpChar, sizeof(tmpChar));
256 			}
257 			flatData.Write(&fValueInfo[vi].extra_data, sizeof(fValueInfo[vi].extra_data));
258 		}
259 	}
260 
261 	return B_OK;
262 }
263 //------------------------------------------------------------------------------
264 bool BPropertyInfo::AllowsTypeCode(type_code code) const
265 {
266 	return (code == B_PROPERTY_INFO_TYPE);
267 }
268 //------------------------------------------------------------------------------
269 status_t BPropertyInfo::Unflatten(type_code code, const void *buffer,
270 								  ssize_t numBytes)
271 {
272 	if (!AllowsTypeCode(code))
273 		return B_BAD_TYPE;
274 
275 	if (buffer == NULL)
276 		return B_BAD_VALUE;
277 
278 	FreeMem();
279 
280 	BMemoryIO flatData(buffer, numBytes);
281 	char tmpChar = B_HOST_IS_BENDIAN;
282 	int32 tmpInt;
283 
284 	flatData.Read(&tmpChar, sizeof(tmpChar));
285 	bool swapRequired = (tmpChar != B_HOST_IS_BENDIAN);
286 
287 	flatData.Read(&fPropCount, sizeof(fPropCount));
288 
289 	int32 flags;
290 	flatData.Read(&flags, sizeof(flags));
291 	if (swapRequired) {
292 		fPropCount = B_SWAP_INT32(fPropCount);
293 		flags = B_SWAP_INT32(flags);
294 	}
295 
296 	if (flags & 1) {
297 		fPropInfo = static_cast<property_info *>(malloc(sizeof(property_info) * (fPropCount + 1)));
298 		memset(fPropInfo, 0, (fPropCount + 1) * sizeof(property_info));
299 
300 		// Main chunks
301 		for (int32 pi = 0; pi < fPropCount; pi++) {
302 			fPropInfo[pi].name = strdup(static_cast<const char*>(buffer) + flatData.Position());
303 			flatData.Seek(strlen(fPropInfo[pi].name) + 1, SEEK_CUR);
304 
305 			fPropInfo[pi].usage = strdup(static_cast<const char *>(buffer) + flatData.Position());
306 			flatData.Seek(strlen(fPropInfo[pi].usage) + 1, SEEK_CUR);
307 
308 			flatData.Read(&fPropInfo[pi].extra_data, sizeof(fPropInfo[pi].extra_data));
309 			if (swapRequired) {
310 				fPropInfo[pi].extra_data = B_SWAP_INT32(fPropInfo[pi].extra_data);
311 			}
312 
313 			flatData.Read(&tmpInt, sizeof(tmpInt));
314 			for (int32 i = 0; tmpInt != 0; i++) {
315 				if (swapRequired) {
316 					tmpInt = B_SWAP_INT32(tmpInt);
317 				}
318 				fPropInfo[pi].commands[i] = tmpInt;
319 				flatData.Read(&tmpInt, sizeof(tmpInt));
320 			}
321 
322 			flatData.Read(&tmpInt, sizeof(tmpInt));
323 			for (int32 i = 0; tmpInt != 0; i++) {
324 				if (swapRequired) {
325 					tmpInt = B_SWAP_INT32(tmpInt);
326 				}
327 				fPropInfo[pi].specifiers[i] = tmpInt;
328 				flatData.Read(&tmpInt, sizeof(tmpInt));
329 			}
330 		}
331 
332 		// Type chunks
333 		for (int32 pi = 0; pi < fPropCount; pi++) {
334 			flatData.Read(&tmpInt, sizeof(tmpInt));
335 			for (int32 i = 0; tmpInt != 0; i++) {
336 				if (swapRequired) {
337 					tmpInt = B_SWAP_INT32(tmpInt);
338 				}
339 				fPropInfo[pi].types[i] = tmpInt;
340 				flatData.Read(&tmpInt, sizeof(tmpInt));
341 			}
342 
343 			flatData.Read(&tmpInt, sizeof(tmpInt));
344 			for (int32 i = 0; tmpInt != 0; i++) {
345 				for (int32 j = 0; tmpInt != 0; j++) {
346 					flatData.Seek(-sizeof(tmpInt), SEEK_CUR);
347 					fPropInfo[pi].ctypes[i].pairs[j].name =
348 									strdup(static_cast<const char *>(buffer) + flatData.Position());
349 					flatData.Seek(strlen(fPropInfo[pi].ctypes[i].pairs[j].name) + 1, SEEK_CUR);
350 
351 					flatData.Read(&fPropInfo[pi].ctypes[i].pairs[j].type,
352 					              sizeof(fPropInfo[pi].ctypes[i].pairs[j].type));
353 					if (swapRequired) {
354 						fPropInfo[pi].ctypes[i].pairs[j].type =
355 										B_SWAP_INT32(fPropInfo[pi].ctypes[i].pairs[j].type);
356 					}
357 					flatData.Read(&tmpInt, sizeof(tmpInt));
358 				}
359 				flatData.Read(&tmpInt, sizeof(tmpInt));
360 			}
361 		}
362 	}
363 
364 	if (flags & 2) {
365 		flatData.Read(&fValueCount, sizeof(fValueCount));
366 		if (swapRequired) {
367 			fValueCount = B_SWAP_INT16(fValueCount);
368 		}
369 
370 		fValueInfo = static_cast<value_info *>(malloc(sizeof(value_info) * (fValueCount + 1)));
371 		memset(fValueInfo, 0, (fValueCount + 1) * sizeof(value_info));
372 
373 		for (int32 vi = 0; vi < fValueCount; vi++)
374 		{
375 			flatData.Read(&fValueInfo[vi].kind, sizeof(fValueInfo[vi].kind));
376 			flatData.Read(&fValueInfo[vi].value, sizeof(fValueInfo[vi].value));
377 
378 			fValueInfo[vi].name = strdup(static_cast<const char *>(buffer) + flatData.Position());
379 			flatData.Seek(strlen(fValueInfo[vi].name) + 1, SEEK_CUR);
380 
381 			fValueInfo[vi].usage = strdup(static_cast<const char *>(buffer) + flatData.Position());
382 			flatData.Seek(strlen(fValueInfo[vi].usage) + 1, SEEK_CUR);
383 
384 			flatData.Read(&fValueInfo[vi].extra_data, sizeof(fValueInfo[vi].extra_data));
385 			if (swapRequired) {
386 				fValueInfo[vi].kind = static_cast<value_kind>(B_SWAP_INT32(fValueInfo[vi].kind));
387 				fValueInfo[vi].value = B_SWAP_INT32(fValueInfo[vi].value);
388 				fValueInfo[vi].extra_data = B_SWAP_INT32(fValueInfo[vi].extra_data);
389 			}
390 		}
391 	}
392 
393 	return B_OK;
394 }
395 //------------------------------------------------------------------------------
396 const property_info *BPropertyInfo::Properties() const
397 {
398 	return fPropInfo;
399 }
400 //------------------------------------------------------------------------------
401 const value_info *BPropertyInfo::Values() const
402 {
403 	return fValueInfo;
404 }
405 //------------------------------------------------------------------------------
406 int32 BPropertyInfo::CountProperties() const
407 {
408 	return fPropCount;
409 }
410 //------------------------------------------------------------------------------
411 int32 BPropertyInfo::CountValues() const
412 {
413 	return fValueCount;
414 }
415 //------------------------------------------------------------------------------
416 void BPropertyInfo::PrintToStream() const
417 {
418 	printf("      property   commands                       types                specifiers\n");
419 	printf("--------------------------------------------------------------------------------\n");
420 
421 	for (int32 pi = 0; fPropInfo[pi].name != 0; pi++)
422 	{
423 		// property
424 		printf("%14s", fPropInfo[pi].name);
425 		// commands
426 		for (int32 i = 0; i < 10 && fPropInfo[pi].commands[i] != 0; i++)
427 		{
428 			uint32 command = fPropInfo[pi].commands[i];
429 
430 			printf("   %c%c%c%-28c", (command & 0xFF000000) >> 24,
431 				(command & 0xFF0000) >> 16, (command & 0xFF00) >> 8,
432 				command & 0xFF);
433 		}
434 		// types
435 		for (int32 i = 0; i < 10 && fPropInfo[pi].types[i] != 0; i++)
436 		{
437 			uint32 type = fPropInfo[pi].types[i];
438 
439 			printf("%c%c%c%c", (type & 0xFF000000) >> 24,
440 				(type & 0xFF0000) >> 16, (type & 0xFF00) >> 8, type & 0xFF);
441 		}
442 		// specifiers
443 		for (int32 i = 0; i < 10 && fPropInfo[pi].specifiers[i] != 0; i++)
444 		{
445 			uint32 spec = fPropInfo[pi].specifiers[i];
446 
447 			printf("%d", spec);
448 		}
449 		printf("\n");
450 	}
451 }
452 //------------------------------------------------------------------------------
453 bool BPropertyInfo::FindCommand(uint32 what, int32 index, property_info *p)
454 {
455 	bool result = false;
456 
457 	if (p->commands[0] == 0) {
458 		result = true;
459 	} else if (index == 0) {
460 		for (int32 i = 0; i < 10 && p->commands[i] != 0; i++) {
461 			if (p->commands[i] == what) {
462 				result = true;
463 			}
464 		}
465 	}
466 
467 	return(result);
468 }
469 //------------------------------------------------------------------------------
470 bool BPropertyInfo::FindSpecifier(uint32 form, property_info *p)
471 {
472 	bool result = false;
473 
474 	if (p->specifiers[0] == 0) {
475 		result = true;
476 	} else {
477 		for (int32 i = 0; i < 10 && p->specifiers[i] != 0; i++) {
478 			if (p->specifiers[i] == form) {
479 				result = true;
480 			}
481 		}
482 	}
483 
484 	return(result);
485 }
486 //------------------------------------------------------------------------------
487 void BPropertyInfo::_ReservedPropertyInfo1() {}
488 void BPropertyInfo::_ReservedPropertyInfo2() {}
489 void BPropertyInfo::_ReservedPropertyInfo3() {}
490 void BPropertyInfo::_ReservedPropertyInfo4() {}
491 //------------------------------------------------------------------------------
492 BPropertyInfo::BPropertyInfo(const BPropertyInfo &)
493 {
494 }
495 //------------------------------------------------------------------------------
496 BPropertyInfo &BPropertyInfo::operator=(const BPropertyInfo &)
497 {
498 	return *this;
499 }
500 //------------------------------------------------------------------------------
501 void BPropertyInfo::FreeMem()
502 {
503 	int i, j, k;
504 
505 	if (!fInHeap) {
506 		return;
507 	}
508 
509 	if (fPropInfo != NULL) {
510 		for(i = 0; i < fPropCount; i++) {
511 			if (fPropInfo[i].name != NULL) {
512 				free(fPropInfo[i].name);
513 			}
514 			if (fPropInfo[i].usage != NULL) {
515 				free(fPropInfo[i].usage);
516 			}
517 			for(j = 0; j < 3; j++) {
518 				for(k = 0; k < 5; k++) {
519 					if (fPropInfo[i].ctypes[j].pairs[k].name == NULL) {
520 						break;
521 					} else {
522 						free(fPropInfo[i].ctypes[j].pairs[k].name);
523 					}
524 				}
525 				if (fPropInfo[i].ctypes[j].pairs[0].name == NULL) {
526 					break;
527 				}
528 			}
529 		}
530 		free(fPropInfo);
531 		fPropInfo = NULL;
532 		fPropCount = 0;
533 	}
534 
535 	if (fValueInfo != NULL) {
536 		for(i = 0; i < fValueCount; i++) {
537 			if (fValueInfo[i].name != NULL) {
538 				free(fValueInfo[i].name);
539 			}
540 			if (fValueInfo[i].usage != NULL) {
541 				free(fValueInfo[i].usage);
542 			}
543 		}
544 		free(fValueInfo);
545 		fValueInfo = NULL;
546 		fValueCount = 0;
547 	}
548 
549 	fInHeap = false;
550 }
551 //------------------------------------------------------------------------------
552 
553 /*
554  * $Log $
555  *
556  * $Id  $
557  *
558  */
559