|
Wired Networking
2.0
Objective-C implementation of the Wired 2.0 protocol
|
00001 /* $Id$ */ 00002 00003 /* 00004 * Copyright (c) 2008-2009 Axel Andersson 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions 00009 * are met: 00010 * 1. Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * 2. Redistributions in binary form must reproduce the above copyright 00013 * notice, this list of conditions and the following disclaimer in the 00014 * documentation and/or other materials provided with the distribution. 00015 * 00016 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00017 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00018 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00019 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 00020 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00021 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00022 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00023 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 00024 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00025 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00026 * POSSIBILITY OF SUCH DAMAGE. 00027 */ 00028 00029 #import <WiredNetworking/NSString-WINetworking.h> 00030 #import <WiredNetworking/WIError.h> 00031 #import <WiredNetworking/WIP7Message.h> 00032 #import <WiredNetworking/WIP7Spec.h> 00033 00034 @interface WIP7Spec(Private) 00035 00036 - (void)_setSpec:(wi_p7_spec_t *)spec; 00037 00038 @end 00039 00040 00041 @interface WIP7SpecType(Private) 00042 00043 - (id)_initWithType:(wi_p7_spec_type_t *)type; 00044 00045 @end 00046 00047 00048 @interface WIP7SpecField(Private) 00049 00050 - (id)_initWithField:(wi_p7_spec_field_t *)field; 00051 00052 @end 00053 00054 00055 @interface WIP7SpecMessage(Private) 00056 00057 - (id)_initWithMessage:(wi_p7_spec_message_t *)message; 00058 00059 @end 00060 00061 00062 @interface WIP7SpecParameter(Private) 00063 00064 - (id)_initWithParameter:(wi_p7_spec_parameter_t *)parameter; 00065 00066 @end 00067 00068 00069 00070 @implementation WIP7Spec(Private) 00071 00072 - (void)_setSpec:(wi_p7_spec_t *)spec { 00073 NSString *name; 00074 wi_enumerator_t *enumerator; 00075 wi_array_t *array; 00076 wi_p7_spec_field_t *field; 00077 00078 _spec = wi_retain(spec); 00079 00080 array = wi_p7_spec_fields(_spec); 00081 enumerator = wi_array_data_enumerator(array); 00082 00083 _fieldNames = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, NULL); 00084 _fieldIDs = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, NULL); 00085 00086 while((field = wi_enumerator_next_data(enumerator))) { 00087 name = [NSString stringWithWiredString:wi_p7_spec_field_name(field)]; 00088 00089 CFDictionarySetValue(_fieldNames, name, wi_p7_spec_field_name(field)); 00090 CFDictionarySetValue(_fieldIDs, name, (void *) wi_p7_spec_field_id(field)); 00091 } 00092 } 00093 00094 @end 00095 00096 00097 00098 @implementation WIP7Spec 00099 00100 - (id)initWithPath:(NSString *)path originator:(WIP7Originator)originator error:(WIError **)error { 00101 wi_p7_spec_t *spec; 00102 wi_pool_t *pool; 00103 wi_string_t *string; 00104 00105 self = [super init]; 00106 00107 pool = wi_pool_init(wi_pool_alloc()); 00108 string = wi_string_with_cstring([path fileSystemRepresentation]); 00109 spec = wi_p7_spec_init_with_file(wi_p7_spec_alloc(), string, originator); 00110 00111 if(!spec) { 00112 if(error) { 00113 *error = [WIError errorWithDomain:WIWiredNetworkingErrorDomain 00114 code:WIP7SpecLoadFailed 00115 userInfo:[NSDictionary dictionaryWithObjectsAndKeys: 00116 [WIError errorWithDomain:WILibWiredErrorDomain], 00117 WILibWiredErrorKey, 00118 path, 00119 WIArgumentErrorKey, 00120 NULL]]; 00121 } 00122 00123 wi_release(pool); 00124 00125 [self release]; 00126 00127 return NULL; 00128 } 00129 00130 [self _setSpec:spec]; 00131 00132 wi_release(spec); 00133 wi_release(pool); 00134 00135 return self; 00136 } 00137 00138 00139 00140 - (id)initWithString:(NSString *)string originator:(WIP7Originator)originator error:(WIError **)error { 00141 wi_p7_spec_t *spec; 00142 wi_pool_t *pool; 00143 00144 self = [super init]; 00145 00146 pool = wi_pool_init(wi_pool_alloc()); 00147 spec = wi_p7_spec_init_with_string(wi_p7_spec_alloc(), [string wiredString], originator); 00148 00149 if(!spec) { 00150 if(error) { 00151 *error = [WIError errorWithDomain:WIWiredNetworkingErrorDomain 00152 code:WIP7SpecLoadFailed 00153 userInfo:[NSDictionary dictionaryWithObjectsAndKeys: 00154 [WIError errorWithDomain:WILibWiredErrorDomain], 00155 WILibWiredErrorKey, 00156 NULL]]; 00157 } 00158 00159 wi_release(pool); 00160 00161 [self release]; 00162 00163 return NULL; 00164 } 00165 00166 [self _setSpec:spec]; 00167 00168 wi_release(spec); 00169 wi_release(pool); 00170 00171 return self; 00172 } 00173 00174 00175 00176 - (void)dealloc { 00177 wi_release(_spec); 00178 00179 if(_fieldNames) 00180 CFRelease(_fieldNames); 00181 00182 if(_fieldIDs) 00183 CFRelease(_fieldIDs); 00184 00185 [_fields release]; 00186 [_messages release]; 00187 [_parameters release]; 00188 00189 [super dealloc]; 00190 } 00191 00192 00193 00194 #pragma mark - 00195 00196 - (wi_p7_spec_t *)spec { 00197 return _spec; 00198 } 00199 00200 00201 00202 - (NSString *)protocolName { 00203 return [NSString stringWithWiredString:wi_p7_spec_name(_spec)]; 00204 } 00205 00206 00207 00208 - (NSString *)protocolVersion { 00209 return [NSString stringWithWiredString:wi_p7_spec_version(_spec)]; 00210 } 00211 00212 00213 00214 #pragma mark - 00215 00216 - (wi_string_t *)fieldNameForName:(NSString *)name { 00217 return (wi_string_t *) CFDictionaryGetValue(_fieldNames, name); 00218 } 00219 00220 00221 00222 - (NSUInteger)fieldIDForName:(NSString *)name { 00223 return (NSUInteger) CFDictionaryGetValue(_fieldIDs, name); 00224 } 00225 00226 00227 00228 #pragma mark - 00229 00230 - (NSArray *)fields { 00231 wi_pool_t *pool; 00232 wi_enumerator_t *enumerator; 00233 wi_p7_spec_field_t *field; 00234 wi_array_t *array; 00235 00236 if(!_fields) { 00237 pool = wi_pool_init(wi_pool_alloc()); 00238 00239 array = wi_p7_spec_fields(_spec); 00240 enumerator = wi_array_data_enumerator(array); 00241 00242 _fields = [[NSMutableArray alloc] initWithCapacity:wi_array_count(array)]; 00243 00244 while((field = wi_enumerator_next_data(enumerator))) 00245 [_fields addObject:[[[WIP7SpecField alloc] _initWithField:field] autorelease]]; 00246 00247 [_fields sortUsingSelector:@selector(compare:)]; 00248 00249 wi_release(pool); 00250 } 00251 00252 return _fields; 00253 } 00254 00255 00256 00257 - (NSArray *)messages { 00258 wi_pool_t *pool; 00259 wi_enumerator_t *enumerator; 00260 wi_p7_spec_message_t *message; 00261 wi_array_t *array; 00262 00263 if(!_messages) { 00264 pool = wi_pool_init(wi_pool_alloc()); 00265 00266 array = wi_p7_spec_messages(_spec); 00267 enumerator = wi_array_data_enumerator(array); 00268 00269 _messages = [[NSMutableArray alloc] initWithCapacity:wi_array_count(array)]; 00270 00271 while((message = wi_enumerator_next_data(enumerator))) 00272 [_messages addObject:[[[WIP7SpecMessage alloc] _initWithMessage:message] autorelease]]; 00273 00274 [_messages sortUsingSelector:@selector(compare:)]; 00275 00276 wi_release(pool); 00277 } 00278 00279 return _messages; 00280 } 00281 00282 00283 00284 - (WIP7SpecMessage *)messageWithName:(NSString *)name { 00285 NSEnumerator *enumerator; 00286 WIP7SpecMessage *message; 00287 00288 enumerator = [[self messages] objectEnumerator]; 00289 00290 while((message = [enumerator nextObject])) { 00291 if([name isEqualToString:[message name]]) 00292 return message; 00293 } 00294 00295 return NULL; 00296 } 00297 00298 00299 00300 #pragma mark - 00301 00302 - (BOOL)verifyMessage:(WIP7Message *)message error:(WIError **)error { 00303 wi_pool_t *pool; 00304 wi_boolean_t result; 00305 00306 pool = wi_pool_init(wi_pool_alloc()); 00307 result = wi_p7_spec_verify_message(_spec, [message message]); 00308 wi_release(pool); 00309 00310 if(!result) { 00311 if(error) 00312 *error = [WIError errorWithDomain:WILibWiredErrorDomain]; 00313 00314 return NO; 00315 } 00316 00317 return YES; 00318 } 00319 00320 @end 00321 00322 00323 00324 @implementation WIP7SpecType(Private) 00325 00326 - (id)_initWithType:(wi_p7_spec_type_t *)type { 00327 self = [super init]; 00328 00329 _type = wi_retain(type); 00330 _name = [[NSString alloc] initWithWiredString:wi_p7_spec_type_name(_type)]; 00331 _id = wi_p7_spec_type_id(_type); 00332 00333 return self; 00334 } 00335 00336 @end 00337 00338 00339 00340 @implementation WIP7SpecType 00341 00342 - (void)dealloc { 00343 [_name release]; 00344 00345 wi_release(_type); 00346 00347 [super dealloc]; 00348 } 00349 00350 00351 00352 #pragma mark - 00353 00354 - (NSComparisonResult)compare:(WIP7SpecType *)type { 00355 if([self ID] < [type ID]) 00356 return NSOrderedAscending; 00357 else if([self ID] > [type ID]) 00358 return NSOrderedDescending; 00359 00360 return NSOrderedSame; 00361 } 00362 00363 00364 00365 #pragma mark - 00366 00367 - (wi_p7_spec_type_t *)type { 00368 return _type; 00369 } 00370 00371 00372 00373 - (NSString *)name { 00374 return _name; 00375 } 00376 00377 00378 00379 - (WIP7Type)ID { 00380 return _id; 00381 } 00382 00383 @end 00384 00385 00386 00387 @implementation WIP7SpecField(Private) 00388 00389 - (id)_initWithField:(wi_p7_spec_field_t *)field { 00390 NSString *name; 00391 NSNumber *value; 00392 wi_enumerator_t *enumerator; 00393 wi_dictionary_t *dictionary; 00394 void *key; 00395 00396 self = [self init]; 00397 00398 _field = wi_retain(field); 00399 _name = [[NSString alloc] initWithWiredString:wi_p7_spec_field_name(_field)]; 00400 _id = wi_p7_spec_field_id(_field); 00401 _type = [[WIP7SpecType alloc] _initWithType:wi_p7_spec_field_type(_field)]; 00402 00403 if([_type ID] == WIP7EnumType) { 00404 _enumsByName = [[NSMutableDictionary alloc] init]; 00405 _enumsByValue = [[NSMutableDictionary alloc] init]; 00406 dictionary = wi_p7_spec_field_enums_by_name(_field); 00407 enumerator = wi_dictionary_key_enumerator(dictionary); 00408 00409 while((key = wi_enumerator_next_data(enumerator))) { 00410 name = [NSString stringWithWiredString:key]; 00411 value = [NSNumber numberWithUnsignedInteger:(wi_uinteger_t) wi_dictionary_data_for_key(dictionary, key)]; 00412 00413 [_enumsByName setObject:value forKey:name]; 00414 [_enumsByValue setObject:name forKey:value]; 00415 } 00416 } 00417 00418 return self; 00419 } 00420 00421 @end 00422 00423 00424 00425 @implementation WIP7SpecField 00426 00427 - (void)dealloc { 00428 [_name release]; 00429 [_type release]; 00430 [_enumsByName release]; 00431 [_enumsByValue release]; 00432 00433 wi_release(_field); 00434 00435 [super dealloc]; 00436 } 00437 00438 00439 00440 #pragma mark - 00441 00442 - (NSComparisonResult)compare:(WIP7SpecField *)field { 00443 if([self ID] < [field ID]) 00444 return NSOrderedAscending; 00445 else if([self ID] > [field ID]) 00446 return NSOrderedDescending; 00447 00448 return NSOrderedSame; 00449 } 00450 00451 00452 00453 #pragma mark - 00454 00455 - (wi_p7_spec_field_t *)field { 00456 return _field; 00457 } 00458 00459 00460 00461 - (NSString *)name { 00462 return _name; 00463 } 00464 00465 00466 00467 - (NSUInteger)ID { 00468 return _id; 00469 } 00470 00471 00472 00473 - (WIP7SpecType *)type { 00474 return _type; 00475 } 00476 00477 00478 00479 - (NSDictionary *)enumsByName { 00480 return _enumsByName; 00481 } 00482 00483 00484 00485 - (NSDictionary *)enumsByValue { 00486 return _enumsByValue; 00487 } 00488 00489 @end 00490 00491 00492 00493 @implementation WIP7SpecMessage(Private) 00494 00495 - (id)_initWithMessage:(wi_p7_spec_message_t *)message { 00496 wi_enumerator_t *enumerator; 00497 wi_p7_spec_parameter_t *parameter; 00498 00499 self = [self init]; 00500 00501 _message = wi_retain(message); 00502 _name = [[NSString alloc] initWithWiredString:wi_p7_spec_message_name(_message)]; 00503 _id = wi_p7_spec_message_id(_message); 00504 _parameters = [[NSMutableArray alloc] init]; 00505 00506 enumerator = wi_array_data_enumerator(wi_p7_spec_message_parameters(_message)); 00507 00508 while((parameter = wi_enumerator_next_data(enumerator))) 00509 [_parameters addObject:[[[WIP7SpecParameter alloc] _initWithParameter:parameter] autorelease]]; 00510 00511 [_parameters sortUsingSelector:@selector(compare:)]; 00512 00513 return self; 00514 } 00515 00516 @end 00517 00518 00519 00520 @implementation WIP7SpecMessage 00521 00522 - (void)dealloc { 00523 [_name release]; 00524 [_parameters release]; 00525 00526 wi_release(_message); 00527 00528 [super dealloc]; 00529 } 00530 00531 00532 00533 #pragma mark - 00534 00535 - (NSComparisonResult)compare:(WIP7SpecMessage *)message { 00536 if([self ID] < [message ID]) 00537 return NSOrderedAscending; 00538 else if([self ID] > [message ID]) 00539 return NSOrderedDescending; 00540 00541 return NSOrderedSame; 00542 } 00543 00544 00545 00546 #pragma mark - 00547 00548 - (wi_p7_spec_message_t *)message { 00549 return _message; 00550 } 00551 00552 00553 00554 - (NSString *)name { 00555 return _name; 00556 } 00557 00558 00559 00560 - (NSUInteger)ID { 00561 return _id; 00562 } 00563 00564 00565 00566 - (NSArray *)parameters { 00567 return _parameters; 00568 } 00569 00570 @end 00571 00572 00573 00574 @implementation WIP7SpecParameter(Private) 00575 00576 - (id)_initWithParameter:(wi_p7_spec_parameter_t *)parameter { 00577 self = [self init]; 00578 00579 _parameter = wi_retain(parameter); 00580 _field = [[WIP7SpecField alloc] _initWithField:wi_p7_spec_parameter_field(parameter)]; 00581 _required = wi_p7_spec_parameter_required(parameter); 00582 00583 return self; 00584 } 00585 00586 @end 00587 00588 00589 00590 @implementation WIP7SpecParameter 00591 00592 - (void)dealloc { 00593 [_field release]; 00594 00595 wi_release(_parameter); 00596 00597 [super dealloc]; 00598 } 00599 00600 00601 00602 #pragma mark - 00603 00604 - (NSComparisonResult)compare:(WIP7SpecParameter *)parameter { 00605 if([self isRequired] && ![parameter isRequired]) 00606 return NSOrderedAscending; 00607 else if(![self isRequired] && [parameter isRequired]) 00608 return NSOrderedDescending; 00609 00610 return [[[self field] name] caseInsensitiveCompare:[[parameter field] name]]; 00611 } 00612 00613 00614 00615 #pragma mark - 00616 00617 - (wi_p7_spec_parameter_t *)parameter { 00618 return _parameter; 00619 } 00620 00621 00622 00623 - (WIP7SpecField *)field { 00624 return _field; 00625 } 00626 00627 00628 00629 - (BOOL)isRequired { 00630 return _required; 00631 } 00632 00633 @end