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