1/* 2 File: IrIASService.cpp 3 4 Contains: Implementation of IrDA's silly name server 5 6*/ 7 8#include "IrIASService.h" 9#include "CListIterator.h" 10#include "CBuffer.h" 11#include "IrDALog.h" 12 13// consider splitting these into n-tables, one for each class? 14 15#if (hasTracing > 0 && hasIASServiceTracing > 0) 16 17enum tracecodes { 18 kLogServiceNew = 1, 19 kLogServiceFree, 20 kLogClassNew, 21 kLogClassFree, 22 kLogAttrNew, 23 kLogAttrFree, 24 kLogNamedListFree, 25 kLogElementNew, 26 kLogElementFree 27}; 28 29static 30EventTraceCauseDesc TraceEvents[] = { 31 {kLogServiceNew, "IrService: service new, obj="}, 32 {kLogServiceFree, "IrService: service free, obj="}, 33 {kLogClassNew, "IrService: class new, obj="}, 34 {kLogClassFree, "IrService: class free, obj="}, 35 {kLogAttrNew, "IrService: attr new, obj="}, 36 {kLogAttrFree, "IrService: attr free, obj="}, 37 {kLogNamedListFree, "IrService: named list free, obj="}, 38 {kLogElementNew, "IrService: element new, obj="}, 39 {kLogElementFree, "IrService: element free, obj="} 40}; 41 42#define XTRACE(x, y, z) IrDALogAdd( x, y, ((uintptr_t)z & 0xffff), TraceEvents, true ) 43#else 44#define XTRACE(x, y, z) ((void)0) 45#endif 46 47#pragma mark 48//============== TIASService ============== 49 50//-------------------------------------------------------------------------------- 51// TIASService 52//-------------------------------------------------------------------------------- 53#define super TIASNamedList 54OSDefineMetaClassAndStructors(TIASService, TIASNamedList); 55 56/*static*/ 57TIASService * 58TIASService::tIASService(void) 59{ 60 TIASService *obj = new TIASService; 61 62 XTRACE(kLogServiceNew, 0, obj); 63 64 if (obj && !obj->Init()) { // this named list has no name 65 obj->release(); 66 obj = nil; 67 } 68 return obj; 69} 70 71 72//-------------------------------------------------------------------------------- 73// free 74//-------------------------------------------------------------------------------- 75void TIASService::free() 76{ 77 long index; 78 79 XTRACE(kLogServiceFree, 0, this); 80 81 // Iterate thru the list of classes and delete each one. Note that I'm not 82 // removing them because I'm depending on the CList destructor to do that for me. 83 for (index = 0; index < this->GetArraySize(); index++) { 84 TIASClass* theClass = (TIASClass*)this->At(index); 85 theClass->release(); 86 } 87 88 super::free(); 89 90} // TIASService::free 91 92 93//-------------------------------------------------------------------------------- 94// AddIntegerEntry 95//-------------------------------------------------------------------------------- 96IrDAErr TIASService::AddIntegerEntry(const UChar* className, const UChar* attributeName, ULong intValue) 97{ 98 TIASElement* theEntry; 99 100 // Create, initialize the new entry 101 theEntry = TIASElement::tIASElement(intValue); // create and initialize 102 require(theEntry, Fail_Element_New); 103 104 // Let AddAttributeEntry finish the job (it will free theEntry if there are any errors) 105 return AddAttributeEntry(className, attributeName, theEntry); 106 107Fail_Element_New: 108 return kIrDAErrNoMemory; 109 110} // TIASService::AddIntegerEntry 111 112 113//-------------------------------------------------------------------------------- 114// AddStringEntry 115//-------------------------------------------------------------------------------- 116IrDAErr TIASService::AddStringEntry(const UChar* className, const UChar* attributeName, 117 const UChar* stringValue, const UChar charSet, const ULong length) 118{ 119 TIASElement *theEntry; 120 121 // Create, initialize the new entry 122 theEntry = TIASElement::tIASElement(stringValue, charSet, length); // create and initialize 123 require(theEntry, Fail_Element_New); 124 125 // Let AddAttributeEntry finish the job (it will free theEntry if there are any errors) 126 return AddAttributeEntry(className, attributeName, theEntry); 127 128Fail_Element_New: 129 return kIrDAErrNoMemory; 130 131} // TIASService::AddStringEntry 132 133 134//-------------------------------------------------------------------------------- 135// AddNBytesEntry 136//-------------------------------------------------------------------------------- 137IrDAErr TIASService::AddNBytesEntry(const UChar* className, const UChar* attributeName, const UChar* aFewBytes, ULong length) 138{ 139 TIASElement* theEntry; 140 141 // Create, initialize the new entry 142 theEntry = TIASElement::tIASElement(aFewBytes, length); // create and initialize 143 require(theEntry, Fail_Element_New); 144 145 // Let AddAttributeEntry finish the job (it will free theEntry if there are any errors) 146 return AddAttributeEntry(className, attributeName, theEntry); 147 148Fail_Element_New: 149 return kIrDAErrNoMemory; 150 151} // TIASService::AddNBytesEntry 152 153 154//-------------------------------------------------------------------------------- 155// AddAttributeEntry 156//-------------------------------------------------------------------------------- 157IrDAErr TIASService::AddAttributeEntry(const UChar* className, const UChar* attributeName, TIASElement* theEntry) 158{ 159 IrDAErr result = kIrDAErrNoMemory; 160 ULong flags; 161 TIASAttribute *theAttr; 162 163 // Make sure the class and attribute exist 164 theAttr = AddAttribute(className, attributeName, flags); 165 XREQUIRE(theAttr, Fail_ClassAttr_New); 166 167 // Insert the new entry 168 result = theAttr->Insert(theEntry); 169 XREQUIRENOT(result, Fail_Entry_Insert); 170 171 return noErr; 172 173Fail_Entry_Insert: 174 RemoveAttribute(className, attributeName, flags); 175 176Fail_ClassAttr_New: 177 theEntry->release(); 178 179 return result; 180 181} // TIASService::AddAttributeEntry 182 183 184//-------------------------------------------------------------------------------- 185// AddAttribute 186//-------------------------------------------------------------------------------- 187TIASAttribute* TIASService::AddAttribute(const UChar* className, const UChar* attributeName, ULong& flags) 188{ 189 IrDAErr result; 190 TIASClass* theClass; 191 TIASAttribute* theAttr; 192 193 theClass = AddClass(className, flags); 194 XREQUIRE(theClass, Fail_Class_New); 195 196 // Does the attribute already exist in this class 197 theAttr = theClass->FindAttribute(attributeName); 198 199 // If attribute exists, done 200 if (theAttr != nil) { 201 return theAttr; 202 } 203 204 // Create, initialize the new attribute 205 theAttr = TIASAttribute::tIASAttribute(attributeName); 206 require(theAttr, Fail_Attribute_New); 207 208 result = theClass->Insert(theAttr); 209 XREQUIRENOT(result, Fail_Attribute_Insert); 210 211 // I created the attribute, let caller know so then can delete it if necessary 212 flags |= kIASAddedAttribute; 213 214 return theAttr; 215 216Fail_Attribute_Insert: 217 theAttr->release(); 218 219Fail_Attribute_New: 220 RemoveClass(className, flags); 221 222Fail_Class_New: 223 return nil; 224 225} // TIASService::AddAttribute 226 227 228//-------------------------------------------------------------------------------- 229// AddClass 230//-------------------------------------------------------------------------------- 231TIASClass* TIASService::AddClass(const UChar* className, ULong& flags) 232{ 233 IrDAErr result; 234 TIASClass *theClass; 235 236 // Init flags 237 flags = 0; 238 239 // Does the class already exist in the name service 240 theClass = FindClass(className); 241 242 // If class exists, done 243 if (theClass != nil) { 244 return theClass; 245 } 246 247 // Create, initialize the new class 248 theClass = TIASClass::tIASClass(className); 249 require(theClass, Fail_Class_New); 250 251 result = this->Insert(theClass); 252 XREQUIRENOT(result, Fail_Class_Insert); 253 254 // I created the class, let caller know so then can delete it if necessary 255 flags |= kIASAddedClass; 256 257 return theClass; 258 259Fail_Class_Insert: 260 theClass->release(); 261 262Fail_Class_New: 263 return nil; 264 265} // TIASService::AddClass 266 267 268//-------------------------------------------------------------------------------- 269// RemoveClass 270//-------------------------------------------------------------------------------- 271IrDAErr TIASService::RemoveClass(const UChar* className, ULong flags) 272{ 273 TIASClass *theClass; 274 275 theClass = FindClass(className); 276 if (theClass && (flags & kIASDeleteClass)) { 277 this->Remove(theClass); 278 theClass->release(); 279 } 280 return noErr; 281 282} // TIASService::RemoveClass 283 284 285//-------------------------------------------------------------------------------- 286// RemoveAttribute 287//-------------------------------------------------------------------------------- 288IrDAErr TIASService::RemoveAttribute(const UChar* className, const UChar* attributeName, ULong flags) 289{ 290 TIASClass* theClass; 291 TIASAttribute* theAttr; 292 293 theClass = FindClass(className); 294 if (theClass) { 295 theAttr = theClass->FindAttribute(attributeName); 296 if (theAttr && (flags & kIASDeleteAttribute)) { 297 theClass->Remove(theAttr); 298 theAttr->release(); 299 } 300 if (flags & kIASDeleteClass) { 301 this->Remove(theClass); 302 theClass->release(); 303 } 304 } 305 return noErr; 306 307} // TIASService::RemoveAttribute 308 309 310//-------------------------------------------------------------------------------- 311// FindClass 312//-------------------------------------------------------------------------------- 313TIASClass* TIASService::FindClass(const UChar* className) 314{ 315 return (TIASClass*)this->Search(className); 316 317} // TIASService::FindClass 318 319 320//-------------------------------------------------------------------------------- 321// FindAttribute 322//-------------------------------------------------------------------------------- 323TIASAttribute* TIASService::FindAttribute(const UChar* className, const UChar* attributeName) 324{ 325 TIASClass* theClass; 326 TIASAttribute* theAttr = nil; 327 328 theClass = FindClass(className); 329 if (theClass) { 330 theAttr = theClass->FindAttribute(attributeName); 331 } 332 return theAttr; 333 334} // TIASService::FindAttribute 335 336 337#pragma mark 338//============== TIASClass ================ 339 340#undef super 341#define super TIASNamedList 342OSDefineMetaClassAndStructors(TIASClass, TIASNamedList); 343 344 345//-------------------------------------------------------------------------------- 346// TIASClass 347//-------------------------------------------------------------------------------- 348/*static*/ 349TIASClass * 350TIASClass::tIASClass(const UChar *name) 351{ 352 TIASClass *obj = new TIASClass; 353 354 XTRACE(kLogClassNew, 0, obj); 355 356 if (obj && !obj->Init(name)) { 357 obj->release(); 358 obj = nil; 359 } 360 return obj; 361} 362 363 364//-------------------------------------------------------------------------------- 365// free 366//-------------------------------------------------------------------------------- 367void TIASClass::free() 368{ 369 long index; 370 371 XTRACE(kLogClassFree, 0, this); 372 373 // Iterate thru the list of attributes and delete each one. Note that I'm not 374 // removing them because I'm depending on the list destructor to do that for me. 375 for (index = 0; index < this->GetArraySize(); index++) { 376 TIASAttribute* theAttr = (TIASAttribute*)this->At(index); 377 theAttr->release(); 378 } 379 380 super::free(); 381 382} // TIASClass::free 383 384 385//-------------------------------------------------------------------------------- 386// Insert 387//-------------------------------------------------------------------------------- 388IrDAErr TIASClass::Insert(TIASAttribute* attribute) 389{ 390 return CList::Insert((void*)attribute); 391 392} // TIASClass::Insert 393 394 395//-------------------------------------------------------------------------------- 396// FindAttribute 397//-------------------------------------------------------------------------------- 398TIASAttribute* TIASClass::FindAttribute(const UChar* attributeName) 399{ 400 return (TIASAttribute*)this->Search(attributeName); 401 402} // TIASClass::FindAttribute 403 404 405#pragma mark 406//============== TIASAttribute ============ 407 408#undef super 409#define super TIASNamedList 410OSDefineMetaClassAndStructors(TIASAttribute, TIASNamedList); 411 412 413//-------------------------------------------------------------------------------- 414// TIASAttribute 415//-------------------------------------------------------------------------------- 416/*static*/ 417TIASAttribute * 418TIASAttribute::tIASAttribute(const UChar *name) 419{ 420 TIASAttribute *obj = new TIASAttribute; 421 422 XTRACE(kLogAttrNew, 0, obj); 423 424 if (obj && !obj->Init(name)) { 425 obj->release(); 426 obj = nil; 427 } 428 return obj; 429} 430 431/*static*/ 432TIASAttribute * 433TIASAttribute::tIASAttribute(CBuffer *buffer) 434{ 435 TIASAttribute *obj = new TIASAttribute; 436 437 XTRACE(kLogAttrNew, 0, obj); 438 439 if (obj && !obj->InitFromBuffer(buffer)) { 440 obj->release(); 441 obj = nil; 442 } 443 return obj; 444} 445 446 447//-------------------------------------------------------------------------------- 448// free 449//-------------------------------------------------------------------------------- 450void TIASAttribute::free() 451{ 452 long index; 453 454 XTRACE(kLogAttrFree, 0, this); 455 456 // Iterate thru the list of elements and delete each one. Note that I'm not 457 // removing them because I'm depending on the list destructor to do that for me. 458 for (index = 0; index < this->GetArraySize(); index++) { 459 TIASElement* theElement = (TIASElement*)this->At(index); 460 theElement->release(); 461 } 462 super::free(); 463 464} // TIASAttribute::free 465 466 467//-------------------------------------------------------------------------------- 468// Insert 469//-------------------------------------------------------------------------------- 470IrDAErr TIASAttribute::Insert(TIASElement* element) 471{ 472 return CList::Insert((void*)element); 473 474} // TIASAttribute::Insert 475 476 477//-------------------------------------------------------------------------------- 478// AddInfoToBuffer 479//-------------------------------------------------------------------------------- 480void TIASAttribute::AddInfoToBuffer(CBuffer* buffer) 481{ 482 long index; 483 ULong arraySize = this->GetArraySize(); 484 485 // Write out the number of elements (as a 16 byte quantity) 486 buffer->Put((int)((arraySize >> 8) & 0xFF)); // Hi byte of short 487 buffer->Put((int)((arraySize >> 0) & 0xFF)); // Lo byte of short 488 489 // No iterate thru the elements and let each of them add themselves to the buffer 490 for (index = 0; index < this->GetArraySize(); index++) { 491 TIASElement* theElement = (TIASElement*)this->At(index); 492 theElement->AddInfoToBuffer(buffer); 493 } 494 495} // TIASAttribute::AddInfoToBuffer 496 497 498//-------------------------------------------------------------------------------- 499// InitFromBuffer 500//-------------------------------------------------------------------------------- 501Boolean TIASAttribute::InitFromBuffer(CBuffer* buffer) 502{ 503 ULong entryIndex; 504 ULong listLength; 505 UByte listLenBuf[2]; // Defined as a Big Endian UShort by protocol 506 TIASElement* element; 507 508 if (!super::Init()) return false; 509 510 // All (successful) replies have a list length field 511 if (buffer->Getn(listLenBuf, sizeof(listLenBuf)) != sizeof(listLenBuf)) { 512 return false; 513 } 514 listLength = (ULong)(listLenBuf[0] * 256) + (ULong)listLenBuf[1]; 515 516 // Get each attribute entry and add it to the attribute 517 for (entryIndex = 0; entryIndex < listLength; entryIndex++) { 518 IrDAErr result; 519 520 // Create an attribute entry from the buffer info 521 element = TIASElement::tIASElement(buffer); 522 require(element, Fail); 523 524 // Add the attr entry to the attribute (list) 525 result = this->Insert(element); 526 if (result != noErr) { 527 element->release(); 528 return false; 529 } 530 } 531 532 return true; 533 534Fail: 535 return false; 536 537} // TIASAttribute::ExtractInfoFromBuffer 538 539 540#pragma mark 541//============== TIASNamedList ============ 542 543#undef super 544#define super CList 545OSDefineMetaClassAndStructors(TIASNamedList, CList); 546 547 548// never created directly, no factories here! 549 550//-------------------------------------------------------------------------------- 551// free 552//-------------------------------------------------------------------------------- 553void TIASNamedList::free() 554{ 555 XTRACE(kLogNamedListFree, 0, this); 556 557 if (fName != nil) { 558 IOFree(fName, fNameLen); 559 fName = nil; 560 } 561 562 super::free(); 563 564} // TIASNamedList::free 565 566 567//-------------------------------------------------------------------------------- 568// Init 569//-------------------------------------------------------------------------------- 570Boolean TIASNamedList::Init(const UChar *theName) 571{ 572 fName = nil; 573 574 if (!super::init()) return false; 575 576 fNameLen = strlen((const char*)theName) + 1; 577 if (fNameLen) { 578 fName = (UChar*)IOMalloc(strlen((const char*)theName) + 1); 579 require(fName, Fail); 580 } 581 strlcpy((char*)fName, (const char*)theName, fNameLen); 582 return true; 583 584Fail: 585 return false; 586} // TIASNamedList::Init 587 588// 589// init w/out a name, seems kinda silly, but here we are 590// 591Boolean TIASNamedList::Init(void) 592{ 593 fName = nil; 594 return super::init(); 595} 596 597//-------------------------------------------------------------------------------- 598// Search 599//-------------------------------------------------------------------------------- 600void* TIASNamedList::Search(const UChar* matchName) 601{ 602 CListIterator *iter = CListIterator::cListIterator(this); 603 TIASNamedList* item; 604 void* result = nil; 605 //int review_consider_putting_in_dynamic_cast; // to make sure list items are named lists 606 607 for (item = (TIASNamedList*)iter->FirstItem(); iter->More(); item = (TIASNamedList*)iter->NextItem()) { 608 if (strcmp((const char*)(item->fName), (const char*)matchName) == 0) { 609 result = (void*)item; 610 break; 611 } 612 } 613 iter->release(); 614 615 return result; 616 617} // TIASNamedList::Search 618 619 620#pragma mark 621//============== TIASElement ============== 622 623#undef super 624#define super OSObject 625OSDefineMetaClassAndStructors(TIASElement, OSObject); 626 627//-------------------------------------------------------------------------------- 628// TIASElement 629//-------------------------------------------------------------------------------- 630/*static*/ 631TIASElement * TIASElement::tIASElement(ULong theValue) 632{ 633 TIASElement *obj = new TIASElement; 634 635 XTRACE(kLogElementNew, 0, obj); 636 637 if (obj && !obj->init_with_long(theValue)) { 638 obj->release(); 639 obj = nil; 640 } 641 return obj; 642} 643 644/*static*/ 645TIASElement * TIASElement::tIASElement(const UChar* theBytes, ULong length) 646{ 647 TIASElement *obj = new TIASElement; 648 649 XTRACE(kLogElementNew, 0, obj); 650 651 if (obj && !obj->init_with_nbytes(theBytes, length)) { 652 obj->release(); 653 obj = nil; 654 } 655 return obj; 656} 657 658/*static*/ 659TIASElement * TIASElement::tIASElement(const UChar* theString, UChar charSet, ULong length) 660{ 661 TIASElement *obj = new TIASElement; 662 663 XTRACE(kLogElementNew, 0, obj); 664 665 if (obj && !obj->init_with_string(theString, charSet, length)) { 666 obj->release(); 667 obj = nil; 668 } 669 return obj; 670} 671 672/*static*/ 673TIASElement * TIASElement::tIASElement(CBuffer* buffer) 674{ 675 TIASElement *obj = new TIASElement; 676 677 XTRACE(kLogElementNew, 0, obj); 678 679 if (obj && !obj->init_with_buffer(buffer)) { 680 obj->release(); 681 obj = nil; 682 } 683 return obj; 684} 685 686 687 688//-------------------------------------------------------------------------------- 689// free 690//-------------------------------------------------------------------------------- 691void TIASElement::free() 692{ 693 int len; 694 695 696 XTRACE(kLogElementFree, 0, this); 697 698 if (nameOrBytes && (nameOrBytes != (UByte*)&valueOrBytes)) { // if we allocated memory 699 len = length; 700 if (type == kIASValueString) // if a unicode string, then allocated memory is length+2 701 len += 2; 702 IOFree(nameOrBytes, len); 703 nameOrBytes = nil; 704 } 705 706 super::free(); 707} 708 709 710//// Inits 711Boolean TIASElement::init_with_long(ULong theValue) 712{ 713 type = kIASValueMissing; 714 length = 0; 715 valueOrBytes = 0; 716 nameOrBytes = nil; 717 characterSet = kIASCharSetAscii; 718 719 if (!super::init()) return false; 720 721 return SetInteger(theValue); 722} 723 724Boolean TIASElement::init_with_nbytes(const UChar* theBytes, ULong length) 725{ 726 type = kIASValueMissing; 727 length = 0; 728 valueOrBytes = 0; 729 nameOrBytes = nil; 730 characterSet = kIASCharSetAscii; 731 732 if (!super::init()) return false; 733 734 return SetNBytes(theBytes, length); 735} 736 737Boolean TIASElement::init_with_string(const UChar* theString, UChar charSet, ULong length) 738{ 739 type = kIASValueMissing; 740 length = 0; 741 valueOrBytes = 0; 742 nameOrBytes = nil; 743 characterSet = kIASCharSetAscii; 744 745 if (!super::init()) return false; 746 747 return SetString(theString, charSet, length); 748} 749 750Boolean TIASElement::init_with_buffer(CBuffer* buffer) 751{ 752 type = kIASValueMissing; 753 length = 0; 754 valueOrBytes = 0; 755 nameOrBytes = nil; 756 characterSet = kIASCharSetAscii; 757 758 if (!super::init()) return false; 759 760 return ExtractInfoFromBuffer(buffer); 761} 762 763 764 765//-------------------------------------------------------------------------------- 766// SetInteger 767//-------------------------------------------------------------------------------- 768Boolean TIASElement::SetInteger(ULong theValue) 769{ 770 type = kIASValueInteger; 771 length = 4; 772 valueOrBytes = htonl(theValue); 773 nameOrBytes = (UByte*)&valueOrBytes; 774 return true; 775} // TIASElement::SetInteger 776 777 778//-------------------------------------------------------------------------------- 779// SetNBytes 780//-------------------------------------------------------------------------------- 781Boolean TIASElement::SetNBytes(const UChar * theBytes, ULong theBytesLength) 782{ 783 type = kIASValueNBytes; 784 length = theBytesLength; 785 nameOrBytes = (UByte*)IOMalloc(length); 786 require(nameOrBytes, Fail); 787 BlockMove(theBytes, nameOrBytes, length); 788 return true; 789 790Fail: 791 return false; 792} // TIASElement::SetNBytes 793 794 795//-------------------------------------------------------------------------------- 796// SetString 797//-------------------------------------------------------------------------------- 798Boolean TIASElement::SetString(const UChar* theString, const UChar charSet, const ULong len) 799{ 800 type = kIASValueString; 801 if (charSet != kIASCharSetUniCode) // if not unicode, use strlen to compute length 802 length = (ULong)strlen((const char*)theString); 803 else 804 length = len; // if unicode, use supplied length 805 806 valueOrBytes = 0; 807 characterSet = charSet; 808 809 // allocate room for string and two nulls (unicode or C) at end 810 nameOrBytes = (UByte*)IOMalloc((unsigned int)(length+2)); 811 require(nameOrBytes, Fail); 812 813 //strcpy((char*)nameOrBytes, (const char*)theString); 814 BlockMove(theString, nameOrBytes, length); // copy the string 815 // would normally just have one null at the end of a C string, but 816 // unicode "end of string" appears to want two nulls, since it's 817 // a 16-bit encoding. So always append two nulls. 818 nameOrBytes[length] = 0; 819 nameOrBytes[length+1] = 0; 820 return true; 821 822Fail: 823 return false; 824 825} // TIASElement::SetString 826 827 828//-------------------------------------------------------------------------------- 829// GetInteger 830//-------------------------------------------------------------------------------- 831IrDAErr TIASElement::GetInteger(ULong *theValue) 832{ 833 if (type != kIASValueInteger) { 834 return kIrDAErrGeneric; // ***FIXME: Better error return 835 } 836 *theValue = ntohl(valueOrBytes); 837 return noErr; 838 839} // TIASElement::GetInteger 840 841 842//-------------------------------------------------------------------------------- 843// GetNBytes 844//-------------------------------------------------------------------------------- 845IrDAErr TIASElement::GetNBytes(UByte **theBytes, ULong *theLength) 846{ 847 if (type != kIASValueNBytes) { 848 return kIrDAErrGeneric; // ***FIXME: Better error return 849 } 850 *theBytes = nameOrBytes; // return pointer directly to our buffer 851 *theLength = length; 852 return noErr; 853 854} // TIASElement::GetNBytes 855 856//-------------------------------------------------------------------------------- 857// GetString 858//-------------------------------------------------------------------------------- 859IrDAErr TIASElement::GetString(UByte **theString, UByte *charSet, ULong *len) 860{ 861 if (type != kIASValueString) { 862 return kIrDAErrGeneric; // ***FIXME: Better error return 863 } 864 *theString = nameOrBytes; // return pointer to our copy! 865 866 if (charSet != nil) // if caller is asking for character set 867 *charSet = characterSet; // return it too 868 869 if (len != nil) // if caller supplied a length buffer 870 *len = length; // return the length too (needed for unicode) 871 872 return noErr; // hope the client doesn't clobber me :-) 873 874} // TIASElement::GetString 875 876 877//-------------------------------------------------------------------------------- 878// AddInfoToBuffer 879//-------------------------------------------------------------------------------- 880void TIASElement::AddInfoToBuffer(CBuffer* buffer) 881{ 882 UByte header[5]; 883 UByte* pHdr = &header[0]; 884 885 // Fill in the object id - not really exists, faking it if I can get away with it 886 *pHdr++ = 0; 887 *pHdr++ = 0; 888 889 // Fill in the type 890 *pHdr++ = type; 891 892 XASSERT(length < 256); 893 894 // Fill in ascii char set/lengths 895 if (type == kIASValueNBytes) { 896 *pHdr++ = 0; // Hi byte of length 897 *pHdr++ = (UByte)length; // Lo byte of length 898 } 899 else if (type == kIASValueString) { 900 *pHdr++ = characterSet; // Character set (defaults to ascii) 901 *pHdr++ = (UByte)length; // Length of string 902 } 903 904 // Put out the header 905 buffer->Putn(header, pHdr - header); 906 907 // Put out the integer/string/octet sequence 908 buffer->Putn(nameOrBytes, length); 909 910} // TIASElement::AddInfoToBuffer 911 912 913//-------------------------------------------------------------------------------- 914// ExtractInfoFromBuffer 915//-------------------------------------------------------------------------------- 916Boolean TIASElement::ExtractInfoFromBuffer(CBuffer* buffer) 917{ 918 UByte entryHeader[3]; // UShort object id followed by attr value type id 919 UByte lengthInfo[2]; // high length byte, then low length byte 920 UByte charSet; // character set 921 ULong length; 922 ULong intValue; 923 Boolean rc; 924 unsigned char buf[1024]; // max nBytes is 1024 (no null at end) 925 926 927 // Each entry must have at least a 2-byte object id and an attr value type id byte 928 if (buffer->Getn(entryHeader, sizeof(entryHeader)) != sizeof(entryHeader)) { 929 return false; 930 } 931 932 // Determine how many bytes to input and "set" the appropriate type/value 933 switch(entryHeader[2] /*type*/ ) { 934 case kIASValueMissing: 935 // This is the default value of an attr element - all done 936 rc = true; 937 break; 938 939 case kIASValueInteger: 940 if (buffer->Getn((UByte*)&intValue, sizeof(intValue)) != sizeof(intValue)) { 941 return kIrDAErrGeneric; // FIXME: Return better error code 942 } 943 intValue = ntohl(intValue); // convert to host before saving 944 rc = SetInteger(intValue); 945 break; 946 947 case kIASValueNBytes: 948 // first get the 16-bit length 949 if (buffer->Getn(lengthInfo, sizeof(lengthInfo)) != sizeof(lengthInfo)) { 950 return false; 951 } 952 length = lengthInfo[0] << 8 | lengthInfo[1]; // could read directly into a short 953 check(length <= 1024); // according to spec 954 check(length <= sizeof(buf)); // sanity 955 if ((UInt32)buffer->Getn(buf, length) != length) 956 return false; 957 rc = SetNBytes(buf, length); 958 break; 959 960 case kIASValueString: 961 // first get the character set code, length bytes 962 if (buffer->Getn(lengthInfo, sizeof(lengthInfo)) != sizeof(lengthInfo)) { 963 return kIrDAErrGeneric; // FIXME: Return better error code 964 } 965 charSet = lengthInfo[0]; // 1st byte is the character set 966 length = lengthInfo[1]; // 2nd byte is the length 967 if ((UInt32)buffer->Getn(buf, length) != length) 968 return false; 969 buf[length] = 0; // turn into C string before calling SetString 970 // since length parm is ignored unless unicode charset 971 rc = SetString(buf, charSet, length); // copy it into the attribute 972 break; 973 974 default: 975 // Unknown type 976 //DebugPrintf("extract info from buffer type %d", entryHeader[2]); // jdg 977 rc = false; 978 break; 979 } 980 981 return rc; 982 983} // TIASElement::ExtractInfoFromBuffer 984 985