/core/externals/update-engine/externals/google-toolbox-for-mac/Foundation/GTMNSDictionary+CaseInsensitive.m

http://macfuse.googlecode.com/ · Objective C · 116 lines · 77 code · 21 blank · 18 comment · 11 complexity · effa865e633fd191fbfd6bf18cb07b9d MD5 · raw file

  1. //
  2. // GTMNSDictionary+CaseInsensitive.m
  3. //
  4. // Copyright 2009 Google Inc.
  5. //
  6. // Licensed under the Apache License, Version 2.0 (the "License"); you may not
  7. // use this file except in compliance with the License. You may obtain a copy
  8. // of the License at
  9. //
  10. // http://www.apache.org/licenses/LICENSE-2.0
  11. //
  12. // Unless required by applicable law or agreed to in writing, software
  13. // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  14. // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  15. // License for the specific language governing permissions and limitations under
  16. // the License.
  17. //
  18. #import "GTMNSDictionary+CaseInsensitive.h"
  19. #import "GTMDefines.h"
  20. #import <CoreFoundation/CoreFoundation.h>
  21. @interface NSMutableDictionary (GTMNSMutableDictionaryCaseInsensitiveAdditions)
  22. // Returns a mutable equivalent to GTMNSDictionaryCaseInsensitiveAdditions.
  23. - (id)gtm_initWithDictionaryCaseInsensitive:(NSDictionary *)dictionary;
  24. @end
  25. static Boolean CaseInsensitiveEqualCallback(const void *a, const void *b) {
  26. id idA = (id)a;
  27. id idB = (id)b;
  28. Boolean ret = FALSE;
  29. if ([idA isKindOfClass:[NSString class]] &&
  30. [idB isKindOfClass:[NSString class]]) {
  31. ret = ([idA compare:idB options:NSCaseInsensitiveSearch|NSLiteralSearch]
  32. == NSOrderedSame);
  33. } else {
  34. ret = [idA isEqual:idB];
  35. }
  36. return ret;
  37. }
  38. static CFHashCode CaseInsensitiveHashCallback(const void *value) {
  39. id idValue = (id)value;
  40. CFHashCode ret = 0;
  41. if ([idValue isKindOfClass:[NSString class]]) {
  42. ret = [[idValue lowercaseString] hash];
  43. } else {
  44. ret = [idValue hash];
  45. }
  46. return ret;
  47. }
  48. @implementation NSDictionary (GTMNSDictionaryCaseInsensitiveAdditions)
  49. - (id)gtm_initWithDictionaryCaseInsensitive:(NSDictionary *)dictionary {
  50. [self release];
  51. self = nil;
  52. CFIndex count = 0;
  53. void *keys = NULL;
  54. void *values = NULL;
  55. if (dictionary) {
  56. count = CFDictionaryGetCount((CFDictionaryRef)dictionary);
  57. if (count) {
  58. keys = malloc(count * sizeof(void *));
  59. values = malloc(count * sizeof(void *));
  60. if (!keys || !values) {
  61. free(keys);
  62. free(values);
  63. return self;
  64. }
  65. CFDictionaryGetKeysAndValues((CFDictionaryRef)dictionary, keys, values);
  66. }
  67. }
  68. CFDictionaryKeyCallBacks keyCallbacks = kCFCopyStringDictionaryKeyCallBacks;
  69. _GTMDevAssert(keyCallbacks.version == 0,
  70. @"CFDictionaryKeyCallBacks structure updated");
  71. keyCallbacks.equal = CaseInsensitiveEqualCallback;
  72. keyCallbacks.hash = CaseInsensitiveHashCallback;
  73. self = (id)CFDictionaryCreate(kCFAllocatorDefault,
  74. keys, values, count, &keyCallbacks,
  75. &kCFTypeDictionaryValueCallBacks);
  76. free(keys);
  77. free(values);
  78. return self;
  79. }
  80. + (id)gtm_dictionaryWithDictionaryCaseInsensitive:(NSDictionary *)dictionary {
  81. return [[[self alloc]
  82. gtm_initWithDictionaryCaseInsensitive:dictionary] autorelease];
  83. }
  84. @end
  85. @implementation NSMutableDictionary (GTMNSMutableDictionaryCaseInsensitiveAdditions)
  86. - (id)gtm_initWithDictionaryCaseInsensitive:(NSDictionary *)dictionary {
  87. if ((self = [super gtm_initWithDictionaryCaseInsensitive:dictionary])) {
  88. id copy = (id)CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0,
  89. (CFDictionaryRef)self);
  90. [self release];
  91. self = copy;
  92. }
  93. return self;
  94. }
  95. @end