1 /* 2 * Copyright 2001-2005, Haiku. 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 && 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); 120 } 121 size += sizeof(int32); 122 } 123 size += sizeof(int32); 124 } 125 } 126 127 if (fValueInfo) { 128 size += sizeof(int16); 129 130 // Chunks 131 for (int32 vi = 0; fValueInfo[vi].name != NULL; vi++) { 132 size += sizeof(int32); 133 size += sizeof(int32); 134 135 size += strlen(fValueInfo[vi].name) + 1; 136 137 if (fValueInfo[vi].usage) 138 size += strlen(fValueInfo[vi].usage) + 1; 139 else 140 size += sizeof(char); 141 142 size += sizeof(int32); 143 } 144 } 145 146 return size; 147 } 148 149 150 status_t 151 BPropertyInfo::Flatten(void* buffer, ssize_t numBytes) const 152 { 153 if (numBytes < FlattenedSize()) 154 return B_NO_MEMORY; 155 156 if (buffer == NULL) 157 return B_BAD_VALUE; 158 159 BMemoryIO flatData(buffer, numBytes); 160 161 char tmpChar = B_HOST_IS_BENDIAN; 162 int32 tmpInt; 163 164 flatData.Write(&tmpChar, sizeof(tmpChar)); 165 flatData.Write(&fPropCount, sizeof(fPropCount)); 166 tmpInt = 0x01 | (fValueInfo ? 0x2 : 0x0); 167 flatData.Write(&tmpInt, sizeof(tmpInt)); 168 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)); 178 } 179 180 flatData.Write(&fPropInfo[pi].extra_data, sizeof(fPropInfo[pi].extra_data)); 181 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])); 184 } 185 tmpInt = 0; 186 flatData.Write(&tmpInt, sizeof(tmpInt)); 187 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])); 190 } 191 tmpInt = 0; 192 flatData.Write(&tmpInt, sizeof(tmpInt)); 193 } 194 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])); 199 } 200 tmpInt = 0; 201 flatData.Write(&tmpInt, sizeof(tmpInt)); 202 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)); 209 } 210 tmpInt = 0; 211 flatData.Write(&tmpInt, sizeof(tmpInt)); 212 } 213 tmpInt = 0; 214 flatData.Write(&tmpInt, sizeof(tmpInt)); 215 } 216 } 217 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)); 230 } 231 flatData.Write(&fValueInfo[vi].extra_data, sizeof(fValueInfo[vi].extra_data)); 232 } 233 } 234 235 return B_OK; 236 } 237 238 239 bool 240 BPropertyInfo::AllowsTypeCode(type_code code) const 241 { 242 return code == B_PROPERTY_INFO_TYPE; 243 } 244 245 246 status_t 247 BPropertyInfo::Unflatten(type_code code, const void* buffer, 248 ssize_t numBytes) 249 { 250 if (!AllowsTypeCode(code)) 251 return B_BAD_TYPE; 252 253 if (buffer == NULL) 254 return B_BAD_VALUE; 255 256 FreeMem(); 257 258 BMemoryIO flatData(buffer, numBytes); 259 char tmpChar = B_HOST_IS_BENDIAN; 260 int32 tmpInt; 261 262 flatData.Read(&tmpChar, sizeof(tmpChar)); 263 bool swapRequired = (tmpChar != B_HOST_IS_BENDIAN); 264 265 flatData.Read(&fPropCount, sizeof(fPropCount)); 266 267 int32 flags; 268 flatData.Read(&flags, sizeof(flags)); 269 if (swapRequired) { 270 fPropCount = B_SWAP_INT32(fPropCount); 271 flags = B_SWAP_INT32(flags); 272 } 273 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)); 277 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); 282 283 fPropInfo[pi].usage = strdup(static_cast<const char *>(buffer) + flatData.Position()); 284 flatData.Seek(strlen(fPropInfo[pi].usage) + 1, SEEK_CUR); 285 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); 289 } 290 291 flatData.Read(&tmpInt, sizeof(tmpInt)); 292 for (int32 i = 0; tmpInt != 0; i++) { 293 if (swapRequired) { 294 tmpInt = B_SWAP_INT32(tmpInt); 295 } 296 fPropInfo[pi].commands[i] = tmpInt; 297 flatData.Read(&tmpInt, sizeof(tmpInt)); 298 } 299 300 flatData.Read(&tmpInt, sizeof(tmpInt)); 301 for (int32 i = 0; tmpInt != 0; i++) { 302 if (swapRequired) { 303 tmpInt = B_SWAP_INT32(tmpInt); 304 } 305 fPropInfo[pi].specifiers[i] = tmpInt; 306 flatData.Read(&tmpInt, sizeof(tmpInt)); 307 } 308 } 309 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); 316 } 317 fPropInfo[pi].types[i] = tmpInt; 318 flatData.Read(&tmpInt, sizeof(tmpInt)); 319 } 320 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); 328 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); 334 } 335 flatData.Read(&tmpInt, sizeof(tmpInt)); 336 } 337 flatData.Read(&tmpInt, sizeof(tmpInt)); 338 } 339 } 340 } 341 342 if (flags & 2) { 343 flatData.Read(&fValueCount, sizeof(fValueCount)); 344 if (swapRequired) { 345 fValueCount = B_SWAP_INT16(fValueCount); 346 } 347 348 fValueInfo = static_cast<value_info *>(malloc(sizeof(value_info) * (fValueCount + 1))); 349 memset(fValueInfo, 0, (fValueCount + 1) * sizeof(value_info)); 350 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)); 354 355 fValueInfo[vi].name = strdup(static_cast<const char *>(buffer) + flatData.Position()); 356 flatData.Seek(strlen(fValueInfo[vi].name) + 1, SEEK_CUR); 357 358 fValueInfo[vi].usage = strdup(static_cast<const char *>(buffer) + flatData.Position()); 359 flatData.Seek(strlen(fValueInfo[vi].usage) + 1, SEEK_CUR); 360 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); 366 } 367 } 368 } 369 370 return B_OK; 371 } 372 373 374 const property_info* 375 BPropertyInfo::Properties() const 376 { 377 return fPropInfo; 378 } 379 380 381 const value_info* 382 BPropertyInfo::Values() const 383 { 384 return fValueInfo; 385 } 386 387 388 int32 389 BPropertyInfo::CountProperties() const 390 { 391 return fPropCount; 392 } 393 394 395 int32 396 BPropertyInfo::CountValues() const 397 { 398 return fValueCount; 399 } 400 401 402 void 403 BPropertyInfo::PrintToStream() const 404 { 405 printf(" property commands types specifiers\n"); 406 printf("--------------------------------------------------------------------------------\n"); 407 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]; 414 415 printf(" %c%c%c%-28c", int(command & 0xFF000000) >> 24, 416 int(command & 0xFF0000) >> 16, int(command & 0xFF00) >> 8, 417 int(command) & 0xFF); 418 } 419 // types 420 for (int32 i = 0; i < 10 && fPropInfo[pi].types[i] != 0; i++) { 421 uint32 type = fPropInfo[pi].types[i]; 422 423 printf("%c%c%c%c", int(type & 0xFF000000) >> 24, 424 int(type & 0xFF0000) >> 16, int(type & 0xFF00) >> 8, (int)type & 0xFF); 425 } 426 // specifiers 427 for (int32 i = 0; i < 10 && fPropInfo[pi].specifiers[i] != 0; i++) { 428 uint32 spec = fPropInfo[pi].specifiers[i]; 429 printf("%lu", spec); 430 } 431 printf("\n"); 432 } 433 } 434 435 436 bool 437 BPropertyInfo::FindCommand(uint32 what, int32 index, property_info *propertyInfo) 438 { 439 bool result = false; 440 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; 448 } 449 } 450 } 451 452 return result; 453 } 454 455 456 bool 457 BPropertyInfo::FindSpecifier(uint32 form, property_info *propertyInfo) 458 { 459 bool result = false; 460 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; 468 } 469 } 470 } 471 472 return result; 473 } 474 475 476 void BPropertyInfo::_ReservedPropertyInfo1() {} 477 void BPropertyInfo::_ReservedPropertyInfo2() {} 478 void BPropertyInfo::_ReservedPropertyInfo3() {} 479 void BPropertyInfo::_ReservedPropertyInfo4() {} 480 481 482 BPropertyInfo::BPropertyInfo(const BPropertyInfo &) 483 { 484 } 485 486 487 BPropertyInfo& 488 BPropertyInfo::operator=(const BPropertyInfo &) 489 { 490 return *this; 491 } 492 493 494 void 495 BPropertyInfo::FreeMem() 496 { 497 int i, j, k; 498 499 if (!fInHeap) 500 return; 501 502 if (fPropInfo != NULL) { 503 for (i = 0; i < fPropCount; i++) { 504 free(fPropInfo[i].name); 505 free(fPropInfo[i].usage); 506 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; 511 512 free(fPropInfo[i].ctypes[j].pairs[k].name); 513 } 514 515 if (fPropInfo[i].ctypes[j].pairs[0].name == NULL) 516 break; 517 } 518 } 519 free(fPropInfo); 520 fPropInfo = NULL; 521 fPropCount = 0; 522 } 523 524 if (fValueInfo != NULL) { 525 for (i = 0; i < fValueCount; i++) { 526 free(fValueInfo[i].name); 527 free(fValueInfo[i].usage); 528 } 529 free(fValueInfo); 530 fValueInfo = NULL; 531 fValueCount = 0; 532 } 533 534 fInHeap = false; 535 } 536 537