PageRenderTime 9717ms CodeModel.GetById 33ms RepoModel.GetById 24ms app.codeStats 0ms

/core/sdk-objc/GMAppleDouble.m

http://macfuse.googlecode.com/
Objective C | 196 lines | 133 code | 25 blank | 38 comment | 15 complexity | 5652f181cd438dccdfaa7608f37adb39 MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause, GPL-2.0
  1. // ================================================================
  2. // Copyright (c) 2007, Google Inc.
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. // ================================================================
  31. //
  32. // GMAppleDouble.m
  33. // MacFUSE
  34. //
  35. // Created by ted on 12/29/07.
  36. //
  37. #import "GMAppleDouble.h"
  38. #import "libkern/OSByteOrder.h"
  39. #define GM_APPLE_DOUBLE_HEADER_MAGIC 0x00051607
  40. #define GM_APPLE_DOUBLE_HEADER_VERSION 0x00020000
  41. typedef struct {
  42. UInt32 magicNumber; // Should be 0x00051607
  43. UInt32 versionNumber; // Should be 0x00020000
  44. char filler[16]; // Zero-filled bytes.
  45. UInt16 numberOfEntries; // Number of entries.
  46. } __attribute__((packed)) DoubleHeader;
  47. typedef struct {
  48. UInt32 entryID; // Defines what entry is (0 is invalid)
  49. UInt32 offset; // Offset from beginning of file to entry data.
  50. UInt32 length; // Length of entry data in bytes.
  51. } __attribute__((packed)) DoubleEntryHeader;
  52. @implementation GMAppleDoubleEntry
  53. + (GMAppleDoubleEntry *)entryWithID:(GMAppleDoubleEntryID)entryID
  54. data:(NSData *)data {
  55. return [[[GMAppleDoubleEntry alloc]
  56. initWithEntryID:entryID data:data] autorelease];
  57. }
  58. - (id)initWithEntryID:(GMAppleDoubleEntryID)entryID
  59. data:(NSData *)data {
  60. if ((self = [super init])) {
  61. if (entryID == DoubleEntryInvalid || data == nil) {
  62. [self release];
  63. return nil;
  64. }
  65. entryID_ = entryID;
  66. data_ = [data retain];
  67. }
  68. return self;
  69. }
  70. - (void)dealloc {
  71. [data_ release];
  72. [super dealloc];
  73. }
  74. - (GMAppleDoubleEntryID)entryID {
  75. return entryID_;
  76. }
  77. - (NSData *)data {
  78. return data_;
  79. }
  80. @end
  81. @implementation GMAppleDouble
  82. + (GMAppleDouble *)appleDouble {
  83. return [[[GMAppleDouble alloc] init] autorelease];
  84. }
  85. + (GMAppleDouble *)appleDoubleWithData:(NSData *)data {
  86. GMAppleDouble* appleDouble = [[[GMAppleDouble alloc] init] autorelease];
  87. if ([appleDouble addEntriesFromAppleDoubleData:data]) {
  88. return appleDouble;
  89. }
  90. return nil;
  91. }
  92. - (id)init {
  93. if ((self = [super init])) {
  94. entries_ = [[NSMutableArray alloc] init];
  95. }
  96. return self;
  97. }
  98. - (void)dealloc {
  99. [entries_ release];
  100. [super dealloc];
  101. }
  102. - (void)addEntry:(GMAppleDoubleEntry *)entry {
  103. [entries_ addObject:entry];
  104. }
  105. - (void)addEntryWithID:(GMAppleDoubleEntryID)entryID data:(NSData *)data {
  106. GMAppleDoubleEntry* entry = [GMAppleDoubleEntry entryWithID:entryID data:data];
  107. [self addEntry:entry];
  108. }
  109. - (BOOL)addEntriesFromAppleDoubleData:(NSData *)data {
  110. const int len = [data length];
  111. DoubleHeader header;
  112. if (len < sizeof(header)) {
  113. return NO; // To small to even fit our header.
  114. }
  115. [data getBytes:&header length:sizeof(header)];
  116. if (OSSwapBigToHostInt32(header.magicNumber) != GM_APPLE_DOUBLE_HEADER_MAGIC ||
  117. OSSwapBigToHostInt32(header.versionNumber) != GM_APPLE_DOUBLE_HEADER_VERSION) {
  118. return NO; // Invalid header.
  119. }
  120. int count = OSSwapBigToHostInt16(header.numberOfEntries);
  121. int offset = sizeof(DoubleHeader);
  122. if (len < (offset + (count * sizeof(DoubleEntryHeader)))) {
  123. return NO; // Not enough data to hold all the DoubleEntryHeader.
  124. }
  125. for (int i = 0; i < count; ++i, offset += sizeof(DoubleEntryHeader)) {
  126. // Extract header
  127. DoubleEntryHeader entryHeader;
  128. NSRange range = NSMakeRange(offset, sizeof(entryHeader));
  129. [data getBytes:&entryHeader range:range];
  130. // Extract data
  131. range = NSMakeRange(OSSwapBigToHostInt32(entryHeader.offset),
  132. OSSwapBigToHostInt32(entryHeader.length));
  133. if (len < (range.location + range.length)) {
  134. return NO; // Given data too small to contain this entry.
  135. }
  136. NSData* entryData = [data subdataWithRange:range];
  137. [self addEntryWithID:OSSwapBigToHostInt32(entryHeader.entryID) data:entryData];
  138. }
  139. return YES;
  140. }
  141. - (NSArray *)entries {
  142. return entries_;
  143. }
  144. - (NSData *)data {
  145. NSMutableData* entryListData = [NSMutableData data];
  146. NSMutableData* entryData = [NSMutableData data];
  147. int dataStartOffset =
  148. sizeof(DoubleHeader) + [entries_ count] * sizeof(DoubleEntryHeader);
  149. for (int i = 0; i < [entries_ count]; ++i) {
  150. GMAppleDoubleEntry* entry = [entries_ objectAtIndex:i];
  151. DoubleEntryHeader entryHeader;
  152. memset(&entryHeader, 0, sizeof(entryHeader));
  153. entryHeader.entryID = OSSwapHostToBigInt32((UInt32)[entry entryID]);
  154. entryHeader.offset =
  155. OSSwapHostToBigInt32((UInt32)(dataStartOffset + [entryData length]));
  156. entryHeader.length = OSSwapHostToBigInt32((UInt32)[[entry data] length]);
  157. [entryListData appendBytes:&entryHeader length:sizeof(entryHeader)];
  158. [entryData appendData:[entry data]];
  159. }
  160. NSMutableData* data = [NSMutableData data];
  161. DoubleHeader header;
  162. memset(&header, 0, sizeof(header));
  163. header.magicNumber = OSSwapHostToBigConstInt32(GM_APPLE_DOUBLE_HEADER_MAGIC);
  164. header.versionNumber = OSSwapHostToBigConstInt32(GM_APPLE_DOUBLE_HEADER_VERSION);
  165. header.numberOfEntries = OSSwapHostToBigInt16((UInt16)[entries_ count]);
  166. [data appendBytes:&header length:sizeof(header)];
  167. [data appendData:entryListData];
  168. [data appendData:entryData];
  169. return data;
  170. }
  171. @end