PageRenderTime 50ms CodeModel.GetById 21ms app.highlight 26ms RepoModel.GetById 1ms 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
  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
 40#define GM_APPLE_DOUBLE_HEADER_MAGIC   0x00051607
 41#define GM_APPLE_DOUBLE_HEADER_VERSION 0x00020000
 42
 43typedef struct {
 44  UInt32 magicNumber;      // Should be 0x00051607
 45  UInt32 versionNumber;    // Should be 0x00020000
 46  char filler[16];         // Zero-filled bytes.
 47  UInt16 numberOfEntries;  // Number of entries.
 48} __attribute__((packed)) DoubleHeader;
 49
 50typedef struct {
 51  UInt32 entryID;  // Defines what entry is (0 is invalid)
 52  UInt32 offset;   // Offset from beginning of file to entry data.
 53  UInt32 length;   // Length of entry data in bytes.
 54} __attribute__((packed)) DoubleEntryHeader;
 55
 56@implementation GMAppleDoubleEntry
 57
 58+ (GMAppleDoubleEntry *)entryWithID:(GMAppleDoubleEntryID)entryID 
 59                               data:(NSData *)data {
 60  return [[[GMAppleDoubleEntry alloc] 
 61           initWithEntryID:entryID data:data] autorelease];
 62}
 63
 64- (id)initWithEntryID:(GMAppleDoubleEntryID)entryID
 65                 data:(NSData *)data {
 66  if ((self = [super init])) {
 67    if (entryID == DoubleEntryInvalid || data == nil) {
 68      [self release];
 69      return nil;
 70    }
 71    entryID_ = entryID;
 72    data_ = [data retain];
 73  }
 74  return self;
 75}
 76
 77- (void)dealloc {
 78  [data_ release];
 79  [super dealloc];
 80}
 81
 82- (GMAppleDoubleEntryID)entryID {
 83  return entryID_;
 84}
 85- (NSData *)data {
 86  return data_;
 87}
 88
 89@end
 90
 91@implementation GMAppleDouble
 92
 93+ (GMAppleDouble *)appleDouble {
 94  return [[[GMAppleDouble alloc] init] autorelease];
 95}
 96
 97+ (GMAppleDouble *)appleDoubleWithData:(NSData *)data {
 98  GMAppleDouble* appleDouble = [[[GMAppleDouble alloc] init] autorelease];
 99  if ([appleDouble addEntriesFromAppleDoubleData:data]) {
100    return appleDouble;
101  }
102  return nil;
103}
104
105- (id)init {
106  if ((self = [super init])) {
107    entries_ = [[NSMutableArray alloc] init];
108  }
109  return self;  
110}
111
112- (void)dealloc {
113  [entries_ release];
114  [super dealloc];
115}
116
117- (void)addEntry:(GMAppleDoubleEntry *)entry {
118  [entries_ addObject:entry];
119}
120
121- (void)addEntryWithID:(GMAppleDoubleEntryID)entryID data:(NSData *)data {
122  GMAppleDoubleEntry* entry = [GMAppleDoubleEntry entryWithID:entryID data:data];
123  [self addEntry:entry];
124}
125
126- (BOOL)addEntriesFromAppleDoubleData:(NSData *)data {
127  const int len = [data length];
128  DoubleHeader header;
129  if (len < sizeof(header)) {
130    return NO;  // To small to even fit our header.
131  }
132  [data getBytes:&header length:sizeof(header)];
133  if (OSSwapBigToHostInt32(header.magicNumber) != GM_APPLE_DOUBLE_HEADER_MAGIC ||
134      OSSwapBigToHostInt32(header.versionNumber) != GM_APPLE_DOUBLE_HEADER_VERSION) {
135    return NO;  // Invalid header.
136  }
137  int count = OSSwapBigToHostInt16(header.numberOfEntries);
138  int offset = sizeof(DoubleHeader);
139  if (len < (offset + (count * sizeof(DoubleEntryHeader)))) {
140    return NO;  // Not enough data to hold all the DoubleEntryHeader.
141  }
142  for (int i = 0; i < count; ++i, offset += sizeof(DoubleEntryHeader)) {
143    // Extract header
144    DoubleEntryHeader entryHeader;
145    NSRange range = NSMakeRange(offset, sizeof(entryHeader));
146    [data getBytes:&entryHeader range:range];
147
148    // Extract data
149    range = NSMakeRange(OSSwapBigToHostInt32(entryHeader.offset), 
150                        OSSwapBigToHostInt32(entryHeader.length));
151    if (len < (range.location + range.length)) {
152      return NO;  // Given data too small to contain this entry.
153    }
154    NSData* entryData = [data subdataWithRange:range];
155    [self addEntryWithID:OSSwapBigToHostInt32(entryHeader.entryID) data:entryData];
156  }
157
158  return YES;
159}
160
161- (NSArray *)entries {
162  return entries_;
163}
164
165- (NSData *)data {
166  NSMutableData* entryListData = [NSMutableData data];
167  NSMutableData* entryData = [NSMutableData data];
168  int dataStartOffset = 
169    sizeof(DoubleHeader) + [entries_ count] * sizeof(DoubleEntryHeader);
170  for (int i = 0; i < [entries_ count]; ++i) {
171    GMAppleDoubleEntry* entry = [entries_ objectAtIndex:i];
172
173    DoubleEntryHeader entryHeader;
174    memset(&entryHeader, 0, sizeof(entryHeader));
175    entryHeader.entryID = OSSwapHostToBigInt32((UInt32)[entry entryID]);
176    entryHeader.offset = 
177      OSSwapHostToBigInt32((UInt32)(dataStartOffset + [entryData length]));
178    entryHeader.length = OSSwapHostToBigInt32((UInt32)[[entry data] length]);
179    [entryListData appendBytes:&entryHeader length:sizeof(entryHeader)];
180    [entryData appendData:[entry data]];
181  }
182  
183  NSMutableData* data = [NSMutableData data];
184
185  DoubleHeader header;
186  memset(&header, 0, sizeof(header));
187  header.magicNumber = OSSwapHostToBigConstInt32(GM_APPLE_DOUBLE_HEADER_MAGIC);
188  header.versionNumber = OSSwapHostToBigConstInt32(GM_APPLE_DOUBLE_HEADER_VERSION);
189  header.numberOfEntries = OSSwapHostToBigInt16((UInt16)[entries_ count]);
190  [data appendBytes:&header length:sizeof(header)];
191  [data appendData:entryListData];
192  [data appendData:entryData];
193  return data;
194}
195
196@end