text: /*
   *  Copyright (c) 2013, Alun Bestor (alun.bestor@gmail.com)
   *  All rights reserved.
   *
   *  Redistribution and use in source and binary forms, with or without modification,
   *  are permitted provided that the following conditions are met:
   *
   *		Redistributions of source code must retain the above copyright notice, this
   *	    list of conditions and the following disclaimer.
   *
   *		Redistributions in binary form must reproduce the above copyright notice,
   *	    this list of conditions and the following disclaimer in the documentation
   *      and/or other materials provided with the distribution.
   *
   *	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
   *	ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   *	WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   *	IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
   *	INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   *	BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
   *	OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   *	WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   *	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   *	POSSIBILITY OF SUCH DAMAGE.
   */
  
  #import "DDHidUsage+ADBUsageExtensions.h"
  
  
  @implementation DDHidUsage (ADBUsageExtensions)
  
  + (id) usageWithName: (NSString *)usageName
  {
      static NSMutableDictionary *namedUsages = nil;
      if (!namedUsages)
      {
  #define NUM_USAGE_PAGES 4
  #define NUM_IDS (kHIDUsage_GD_DPadLeft + kHIDUsage_Sim_RearBrake + kHIDUsage_KeyboardRightGUI + 30)
          
          unsigned usagePages[NUM_USAGE_PAGES][2] = {
              {kHIDPage_GenericDesktop,   kHIDUsage_GD_DPadLeft},
              {kHIDPage_Simulation,       kHIDUsage_Sim_RearBrake},
              {kHIDPage_KeyboardOrKeypad, kHIDUsage_KeyboardRightGUI},
              {kHIDPage_Button,           30} //Only enumerate the first 30 buttons
          };
          
          //Build a reverse lookup table of usages by usage name,
          //iterating over the usage tables we care about
          namedUsages = [[NSMutableDictionary alloc] initWithCapacity: NUM_IDS];
          
          unsigned i, currentID;
          for (i=0; i < NUM_USAGE_PAGES; i++)
          {
              unsigned currentPage = usagePages[i][0], numIDs = usagePages[i][1];
              for (currentID=0; currentID <= numIDs; currentID++)
              {
                  DDHidUsage *usage = [DDHidUsage usageWithUsagePage: currentPage
                                                             usageId: currentID];
                  
                  [namedUsages setObject: usage
                                  forKey: [usage usageName]];
              }
          }
      }
      
      return [namedUsages objectForKey: usageName];
  }
  
  - (id) initWithCoder: (NSCoder *)coder
  {
      if ((self = [super init]))
      {
          mUsagePage  = (unsigned)[coder decodeIntegerForKey: @"usagePage"];
          mUsageId    = (unsigned)[coder decodeIntegerForKey: @"usageID"];
      }
      
      return self;
  }
  
  - (void) encodeWithCoder: (NSCoder *)coder
  {
      [coder encodeInteger: mUsagePage forKey: @"usagePage"];
      [coder encodeInteger: mUsageId forKey: @"usageID"];
  }
  
  - (id) copyWithZone: (NSZone *)zone
  {
  	//DDHidUsage is immutable, so it's OK for us to retain rather than copying
  	return [self retain];
  }
  
  - (BOOL) isEqualToUsage: (DDHidUsage *)usage
  {
  	return [self isEqualToUsagePage: usage.usagePage
                              usageId: usage.usageId];
  }
  
  - (BOOL) isEqual: (id)object
  {
  	if ([object isKindOfClass: [DDHidUsage class]] && [self isEqualToUsage: object]) return YES;
  	else return [super isEqual: object];
  }
  
  
  - (NSComparisonResult) compare: (DDHidUsage *)usage;
  {
      unsigned myUsagePage = self.usagePage;
      unsigned otherUsagePage = usage.usagePage;
      
      if (myUsagePage < otherUsagePage)
          return NSOrderedAscending;
      else if (myUsagePage > otherUsagePage)
          return NSOrderedDescending;
      
      unsigned myUsageId = self.usageId;
      unsigned otherUsageId = usage.usageId;
      
      if (myUsageId < otherUsageId)
          return NSOrderedAscending;
      else if (myUsageId > otherUsageId)
          return NSOrderedDescending;
      
      return NSOrderedSame;
  }
  
  @end
  
  
  DDHidUsage * ADBUsageFromID(unsigned int usagePage, unsigned int usageID)
  {
      return [DDHidUsage usageWithUsagePage: usagePage usageId: usageID];
  }
  
  DDHidUsage * ADBUsageFromName(NSString *usageName)
  {
      return [DDHidUsage usageWithName: usageName];
  }
  