[
  {
    "path": ".gitignore",
    "content": "# General\n.DS_Store\n\n# Xcode\n#\nbuild/\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.perspectivev3\n!default.perspectivev3\nxcuserdata\n*.xccheckout\n*.moved-aside\nDerivedData\n*.hmap\n*.ipa\n*.xcuserstate\n\n# CocoaPods\n#\n# We recommend against adding the Pods directory to your .gitignore. However\n# you should judge for yourself, the pros and cons are mentioned at:\n# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control\n\nPods/\n\n# Carthage\n#\n# Add this line if you want to avoid checking in source code from Carthage dependencies.\n# Carthage/Checkouts\n\nCarthage/Build\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: objective-c\nosx_image: xcode7.3\nenv:\n  - UDID=\"D72029C0-E8E1-4349-B423-E458466135B3\", IOS_DEVICE=\"iPhone 4s (8.1)\"\n  - UDID=\"5752202B-E7A2-4B6C-9D7B-B211C2F54654\", IOS_DEVICE=\"iPhone 6s (9.3)\"\n\nscript:\n    - xcrun instruments -s devices\n    - open -a \"simulator\" --args -CurrentDeviceUDID $UDID\n    - xcodebuild test -project ./Demo/iOSDemo/JSPatchDemo.xcodeproj -scheme JSPatchDemo -sdk iphonesimulator -destination \"platform=iOS Simulator,id=$UDID\"\n    - osascript -e 'tell app \"Simulator\" to quit'\n"
  },
  {
    "path": "Demo/DribbbleDemo/Podfile",
    "content": "platform :ios, '7.0'\ntarget 'dribbbleDemo' do\n        pod \"AFNetworking\", \"~> 2.0\"\n\t\tpod \"SDWebImage\"\nend"
  },
  {
    "path": "Demo/DribbbleDemo/README.md",
    "content": "# JSPatch Dribbble Demo\n\n![Screenshot](https://raw.github.com/bang590/JSPatch/master/Demo/DribbbleDemo/Screenshot.gif)\n\nA Dribbble iOS client write in JSPatch.\n\nPlease install the cocoapods and run `pod install`."
  },
  {
    "path": "Demo/DribbbleDemo/dribbbleDemo/AppDelegate.h",
    "content": "//\n//  AppDelegate.h\n//  dribbbleDemo\n//\n//  Created by bang on 15/9/1.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface AppDelegate : UIResponder <UIApplicationDelegate>\n\n@property (strong, nonatomic) UIWindow *window;\n\n\n@end\n\n"
  },
  {
    "path": "Demo/DribbbleDemo/dribbbleDemo/AppDelegate.m",
    "content": "//\n//  AppDelegate.m\n//  dribbbleDemo\n//\n//  Created by bang on 15/9/1.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import \"AppDelegate.h\"\n#import \"JPEngine.h\"\n\n@interface AppDelegate ()\n\n@end\n\n@implementation AppDelegate\n\n\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {\n    \n    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];\n    [self.window makeKeyAndVisible];\n    \n    [JPEngine startEngine];\n    NSString *sourcePath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@\"dribbble/main.js\"];\n    [JPEngine evaluateScriptWithPath:sourcePath];\n    \n    [self initRootViewController];\n    return YES;\n}\n\n- (void)initRootViewController\n{\n}\n\n- (void)applicationWillResignActive:(UIApplication *)application {\n    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.\n    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.\n}\n\n- (void)applicationDidEnterBackground:(UIApplication *)application {\n    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.\n    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.\n}\n\n- (void)applicationWillEnterForeground:(UIApplication *)application {\n    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.\n}\n\n- (void)applicationDidBecomeActive:(UIApplication *)application {\n    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.\n}\n\n- (void)applicationWillTerminate:(UIApplication *)application {\n    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.\n}\n\n@end\n"
  },
  {
    "path": "Demo/DribbbleDemo/dribbbleDemo/Images.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"60x60\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"60x60\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"76x76\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"76x76\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"83.5x83.5\",\n      \"scale\" : \"2x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Demo/DribbbleDemo/dribbbleDemo/Images.xcassets/Contents.json",
    "content": "{\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Demo/DribbbleDemo/dribbbleDemo/Images.xcassets/LaunchImage-1.launchimage/Contents.json",
    "content": "{\n  \"images\" : [\n\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Demo/DribbbleDemo/dribbbleDemo/Images.xcassets/LaunchImage.launchimage/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"extent\" : \"full-screen\",\n      \"idiom\" : \"iphone\",\n      \"subtype\" : \"736h\",\n      \"filename\" : \"Default-576@2x.png\",\n      \"minimum-system-version\" : \"8.0\",\n      \"orientation\" : \"portrait\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"extent\" : \"full-screen\",\n      \"idiom\" : \"iphone\",\n      \"subtype\" : \"736h\",\n      \"filename\" : \"Default-736@3x.png\",\n      \"minimum-system-version\" : \"8.0\",\n      \"orientation\" : \"landscape\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"extent\" : \"full-screen\",\n      \"idiom\" : \"iphone\",\n      \"subtype\" : \"667h\",\n      \"filename\" : \"Default-667@2x.png\",\n      \"minimum-system-version\" : \"8.0\",\n      \"orientation\" : \"portrait\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"orientation\" : \"portrait\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Default@2x.png\",\n      \"extent\" : \"full-screen\",\n      \"minimum-system-version\" : \"7.0\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"extent\" : \"full-screen\",\n      \"idiom\" : \"iphone\",\n      \"subtype\" : \"retina4\",\n      \"filename\" : \"Default-568h@2x.png\",\n      \"minimum-system-version\" : \"7.0\",\n      \"orientation\" : \"portrait\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"orientation\" : \"portrait\",\n      \"idiom\" : \"ipad\",\n      \"extent\" : \"full-screen\",\n      \"minimum-system-version\" : \"7.0\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"orientation\" : \"landscape\",\n      \"idiom\" : \"ipad\",\n      \"extent\" : \"full-screen\",\n      \"minimum-system-version\" : \"7.0\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"orientation\" : \"portrait\",\n      \"idiom\" : \"ipad\",\n      \"extent\" : \"full-screen\",\n      \"minimum-system-version\" : \"7.0\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"orientation\" : \"landscape\",\n      \"idiom\" : \"ipad\",\n      \"extent\" : \"full-screen\",\n      \"minimum-system-version\" : \"7.0\",\n      \"scale\" : \"2x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Demo/DribbbleDemo/dribbbleDemo/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>com.jspatch..$(PRODUCT_NAME:rfc1034identifier)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n\t<key>LSRequiresIPhoneOS</key>\n\t<true/>\n\t<key>NSAppTransportSecurity</key>\n\t<dict>\n\t\t<key>NSAllowsArbitraryLoads</key>\n\t\t<true/>\n\t</dict>\n\t<key>UIRequiredDeviceCapabilities</key>\n\t<array>\n\t\t<string>armv7</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations~ipad</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationPortraitUpsideDown</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "Demo/DribbbleDemo/dribbbleDemo/dribbble/CommonDefine.js",
    "content": "global.SCREEN_WIDTH = require('UIScreen').mainScreen().bounds().width;\nglobal.SCREEN_HEIGHT = require('UIScreen').mainScreen().bounds().height;\n\nglobal.UIHelper = {\n  bottomY: function(view) {\n    var f = view.frame();\n    return f.height + f.y;\n  },\n  rightX: function(view) {\n    var f = view.frame();\n    return f.width + f.x;\n  },\n  setWidth: function(view, width) {\n    var f = view.frame();\n    f.width = width\n    view.setFrame(f)\t\n  },\n  setHeight: function(view, height) {\n    var f = view.frame();\n    f.height = height\n    view.setFrame(f)\t\n  },\n  setX: function(view, x) {\n    var f = view.frame();\n    f.x = x\n    view.setFrame(f)\t\n  },\n  setY: function(view, y) {\n    var f = view.frame();\n    f.y = y\n    view.setFrame(f)\t\n  }\n}"
  },
  {
    "path": "Demo/DribbbleDemo/dribbbleDemo/dribbble/DBDataSource.js",
    "content": "var _dataSourceShareInstance;\ndefineJSClass('DBDataSource', {\n  init: function(){\n    this.dribbbleHost = 'https://api.dribbble.com/v1';\n    this.requestManager = require('AFHTTPRequestOperationManager').manager();\n    this.requestManager.requestSerializer().setValue_forHTTPHeaderField('Bearer deeb37c0823d3866650db12df9e36730a0453a5a7b8e6493e0ac5ece15929613', 'Authorization');\n    return this;\n  },\n\n  _get: function(path, params, succ, fail){\n    var url = this.dribbbleHost + path\n    this.requestManager.GET_parameters_success_failure(url, params, \n      block('AFHTTPRequestOperation *, id', function(operation, responseObject) {\n          if (succ) succ(responseObject);\n      }), \n      block('AFHTTPRequestOperation *, NSError *', function(operation, error) {\n          if (fail) fail(error);\n      })\n    );\n  },\n  loadPublicShots: function(page, per_page, succ, fail) {\n    var path = '/shots';\n    this._get(path, {page: page, per_page:per_page}, succ, fail)\n  },\n  loadComments: function(id, page, per_page, succ, fail) {\n    var path = '/shots/' + id + '/comments';\n    this._get(path, {page: page, per_page:per_page}, succ, fail)\n  },\n\n  loadUserShots: function(userId, page, per_page, succ, fail) {\n    var path = '/users/' + userId + '/shots';\n    this._get(path, {page: page, per_page:per_page}, succ, fail)\n  },\n\n}, {\n  shareInstance: function(){\n    if (!_dataSourceShareInstance) {\n      _dataSourceShareInstance = DBDataSource.alloc().init();\n    }\n    return _dataSourceShareInstance;\n  },\n})\n\n\n/*item struct:\n\n{\n    \"id\": 2619381,\n    \"title\": \"Seaborn Oyster Co.\",\n    \"description\": null,\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher.jpg\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher_1x.jpg\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher_teaser.jpg\"\n    },\n    \"views_count\": 2166,\n    \"likes_count\": 235,\n    \"comments_count\": 2,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 11,\n    \"created_at\": \"2016-03-29T17:12:41Z\",\n    \"updated_at\": \"2016-03-29T17:12:53Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619381-Seaborn-Oyster-Co\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619381/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619381/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619381/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619381/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619381/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619381/rebounds\",\n    \"animated\": false,\n    \"tags\": [\n      \"charleston\",\n      \"company\",\n      \"ocean\",\n      \"oyster\",\n      \"sea\",\n      \"wave\"\n    ],\n    \"user\": {\n      \"id\": 52758,\n      \"name\": \"Jay Fletcher\",\n      \"username\": \"jfletcherdesign\",\n      \"html_url\": \"https://dribbble.com/jfletcherdesign\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/52758/avatars/normal/J_FLETCHER_DESIGN_LOGO-01.jpg?1401983283\",\n      \"bio\": \"\",\n      \"location\": \"Charleston, SC\",\n      \"links\": {\n        \"web\": \"http://www.jfletcherdesign.com\",\n        \"twitter\": \"https://twitter.com/jfletcherdesign\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 5239,\n      \"followers_count\": 13803,\n      \"followings_count\": 558,\n      \"likes_count\": 6531,\n      \"likes_received_count\": 104895,\n      \"projects_count\": 10,\n      \"rebounds_received_count\": 325,\n      \"shots_count\": 481,\n      \"teams_count\": 0,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/52758/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/52758/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/52758/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/52758/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/52758/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/52758/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/52758/teams\",\n      \"created_at\": \"2011-08-13T23:30:38Z\",\n      \"updated_at\": \"2016-03-29T17:12:53Z\"\n    },\n    \"team\": null\n  },\n\n  */"
  },
  {
    "path": "Demo/DribbbleDemo/dribbbleDemo/dribbble/DBDetailController.js",
    "content": "include('DBDetailViews.js')\ninclude('DBUserController.js')\n\ndefineClass('DBDetailViewController: UITableViewController', [\n  'loadingView', \n  'isLoading',\n  'commentsData',\n  'itemData',\n  'currPage'\n  ], {\n  initWithItem: function(item){\n    self = self.super().init();\n    if (self) {\n      self.tableView().setSeparatorStyle(0);\n      self.setTitle(item['title']);\n\n      var headerView = DBDetailHeaderView.alloc().initWithItem(item);\n      var slf = self;\n      headerView.setTapUserCallback(function(user){\n        slf._handleGotoUser(user);\n      })\n      self.tableView().setTableHeaderView(headerView);\n\n\n      var loadingView = require('UIActivityIndicatorView').alloc().initWithActivityIndicatorStyle(2);\n      loadingView.setFrame({x: (SCREEN_WIDTH - 40) / 2, y:headerView.frame().height + 30, width:40, height:40});\n      loadingView.startAnimating();\n      self.view().addSubview(loadingView);\n      self.setLoadingView(loadingView);\n\n      self.setCommentsData([]);\n      self.setItemData(item);\n      self.setCurrPage(1);\n      self._loadComment();\n    }\n    return self;\n  },\n\n  _loadComment: function(){\n    self.setIsLoading(1)\n    var item = self.itemData();\n    var perPage = 10;\n    var slf = self;\n    DBDataSource.shareInstance().loadComments(item['id'], self.currPage(), perPage, function(comments){\n      slf.loadingView().removeFromSuperview();\n      slf.setCommentsData(slf.commentsData().concat(comments));\n      slf.setCurrPage(slf.currPage() + 1);\n      slf.setIsLoading(0);\n\n      if (comments.length >= perPage) {\n        slf.tableView().setTableFooterView(DBLoadMoreView.alloc().init());\n      } else {\n        slf.tableView().setTableFooterView(null);\n      }\n      slf.tableView().reloadData();\n    }, function(){\n      //fail\n    })\n  },\n  numberOfSectionsInTableView: function(tableView) {\n    return 1;\n  },\n  tableView_numberOfRowsInSection: function(tableView, section) {\n    if (!self.commentsData()) return 0;\n    return self.commentsData().length;\n  },\n  tableView_cellForRowAtIndexPath: function(tableView, indexPath) {\n    var cell = tableView.dequeueReusableCellWithIdentifier(\"cell\") \n    if (!cell) {\n      cell = DBCommentViewCell.alloc().initWithStyle_reuseIdentifier(0, \"cell\")\n      var slf = self;\n      cell.setTapUserCallback(function(user){\n        slf._handleGotoUser(user);\n      })\n    }\n\n    cell.renderWithComment(self.commentsData()[indexPath.row()]);\n    return cell\n  },\n  tableView_heightForRowAtIndexPath: function(tableView, indexPath) {\n    var comment = self.commentsData()[indexPath.row()];\n    if (!comment['contentHeight']) {\n      comment['contentHeight'] = DBCommentViewCell.heightWithComment(comment);\n    }\n    return comment['contentHeight'];\n  },\n\n  scrollViewDidScroll: function(scrollView) {\n    var contentOffset = scrollView.contentOffset();\n    var contentSize = scrollView.contentSize();\n    if (!self.isLoading() && self.tableView().tableFooterView() && contentOffset.y - contentSize.height > -SCREEN_HEIGHT) {\n      self._loadComment();\n    }\n  },\n\n  _handleGotoUser: function(user) {\n    var userVC = DBUserViewController.alloc().initWithUser(user);\n    self.navigationController().pushViewController_animated(userVC, YES);\n  }\n})"
  },
  {
    "path": "Demo/DribbbleDemo/dribbbleDemo/dribbble/DBDetailViews.js",
    "content": "require('UIView, UIImage')\nvar gap = 10;\nvar avatarSize = 40;\ndefineClass('DBDetailHeaderView: UIView', ['tapUserCallback', 'itemData'], {\n  initWithItem: function(item) {\n    self = self.super().init();\n    if (self) {\n      self.setItemData(item);\n\n      var avatarButton = require('UIButton')\n                              .alloc()\n                              .initWithFrame({x:gap, y:gap, width:avatarSize, height:avatarSize});\n      avatarButton.addTarget_action_forControlEvents(self, 'handleTapUser', 1 <<  6);\n\n      var nameLabel = UILabel\n                        .alloc()\n                        .initWithFrame({x: gap * 2 + avatarSize, y:gap, width:SCREEN_WIDTH - avatarSize - gap * 3 , height:20});\n      nameLabel.setFont(UIFont.systemFontOfSize(14));\n\n      var timeLabel = UILabel\n                        .alloc()\n                        .initWithFrame({x: gap * 2 + avatarSize, y:gap + 20, width:SCREEN_WIDTH - avatarSize - gap * 3 , height:20});\n      timeLabel.setFont(UIFont.systemFontOfSize(12));\n      timeLabel.setTextColor(UIColor.grayColor());\n\n      var contentImageView = require('UIImageView')\n                              .alloc()\n                              .initWithFrame({x: gap, y:gap*2 + avatarSize, width:SCREEN_WIDTH - gap*2, height:(SCREEN_WIDTH - gap*2)*3/4});\n\n      self.addSubview(avatarButton);\n      self.addSubview(nameLabel);\n      self.addSubview(timeLabel);\n      self.addSubview(contentImageView);\n\n      var panelView = self._genPanelViewWithItem(item);\n      var panelFrame = panelView.frame();\n      panelFrame.x = SCREEN_WIDTH - (gap + panelFrame.width);\n      panelFrame.y = contentImageView.frame().y + contentImageView.frame().height + gap;\n      panelView.setFrame(panelFrame);\n      self.addSubview(panelView);\n\n      avatarButton.sd__setImageWithURL_forState(require('NSURL').URLWithString(item['user']['avatar_url']), 0);\n      contentImageView.sd__setImageWithURL(require('NSURL').URLWithString(item['images']['normal']));\n      nameLabel.setText(item['user']['name'])\n\n      var d = new Date(item['created_at']);\n      var dateStr = d.getFullYear() + '年' + (d.getMonth() + 1) + '月' + d.getDate() + '日' + ' ' + d.getHours() + ':' + d.getMinutes();\n      timeLabel.setText(dateStr);\n\n      self.setFrame({x:0, y:0, width: SCREEN_WIDTH, height:panelView.frame().y + panelView.frame().height});\n    }\n    return self;\n  },\n  handleTapUser : function(){\n    var cb = self.tapUserCallback();\n    if (cb) cb(self.itemData()['user']);\n  },\n  _genPanelViewWithItem : function(item) {\n    var panelView = UIView\n                      .alloc()\n                      .init();\n\n    var iconSize = 12;\n    var viewImageView = UIImageView\n                          .alloc()\n                          .initWithFrame({x:0, y:0, width:15, height: 15});\n    viewImageView.setImage(UIImage.imageWithContentsOfFile(resourcePath('imgs/view.png')));\n    panelView.addSubview(viewImageView);\n\n    var viewLabel = self._genPanelLabel(item['views_count'], {x: UIHelper.rightX(viewImageView) + 5, y:0, width:40, height:iconSize});\n    panelView.addSubview(viewLabel);\n\n\n\n    var commentImageView = UIImageView\n                          .alloc()\n                          .initWithFrame({x:UIHelper.rightX(viewLabel) + 10, y:3, width:iconSize, height: iconSize});\n    commentImageView.setImage(UIImage.imageWithContentsOfFile(resourcePath('imgs/comment.png')));\n    panelView.addSubview(commentImageView);\n\n    var commentLabel = self._genPanelLabel(item['comments_count'], {x: UIHelper.rightX(commentImageView) + 5, y:0, width:40, height:iconSize});\n    panelView.addSubview(commentLabel);\n\n\n\n\n    var likeImageView = UIImageView\n                          .alloc()\n                          .initWithFrame({x:UIHelper.rightX(commentLabel) + 10, y:3, width:iconSize, height: iconSize});\n    likeImageView.setImage(UIImage.imageWithContentsOfFile(resourcePath('imgs/like.png')));\n    panelView.addSubview(likeImageView);\n\n\n    var commentLabel = self._genPanelLabel(item['likes_count'], {x: UIHelper.rightX(likeImageView) + 5, y:0, width:40, height:iconSize});\n    panelView.addSubview(commentLabel);\n\n    panelView.setFrame({x:0, y:0, width:UIHelper.rightX(commentLabel), height:40});\n\n    return panelView;\n  },\n  _genPanelLabel: function(val, frame) {\n    var viewLabel = UILabel.alloc().initWithFrame(frame)\n    viewLabel.setText(val.toString());\n    viewLabel.setFont(UIFont.systemFontOfSize(14));\n    viewLabel.setTextColor(UIColor.colorWithWhite_alpha(.5, 1))\n    viewLabel.sizeToFit();\n    return viewLabel;\n  }\n})\n\n\n\n\ndefineClass('DBCommentViewCell: UITableViewCell', [\n    'avatarButton', \n    'nameLabel',\n    'timeLabel',\n    'contentLabel',\n    'tapUserCallback',\n    'commentData',\n], {\n  initWithStyle_reuseIdentifier: function(style, reuseIdentifier) {\n    self = self.super().initWithStyle_reuseIdentifier(style, reuseIdentifier);\n    if (self) {\n      self.setSelectionStyle(0);\n\n      var avatarButton = require('UIButton')\n                              .alloc()\n                              .initWithFrame({x:gap, y:gap, width:avatarSize, height:avatarSize});\n      avatarButton.addTarget_action_forControlEvents(self, 'handleTapUser', 1 <<  6);\n\n      var nameLabel = UILabel\n                        .alloc()\n                        .initWithFrame({x: gap * 2 + avatarSize, y:gap, width:SCREEN_WIDTH - avatarSize - gap * 3 , height:20});\n      nameLabel.setFont(UIFont.systemFontOfSize(14));\n      nameLabel.setTextColor(UIColor.colorWithWhite_alpha(.5, 1))\n\n      var timeLabel = UILabel\n                        .alloc()\n                        .initWithFrame({x: SCREEN_WIDTH - gap - 200, y:gap, width:200 , height:20});\n      timeLabel.setFont(UIFont.systemFontOfSize(12));\n      timeLabel.setTextColor(UIColor.colorWithWhite_alpha(.7, 1));\n      timeLabel.setTextAlignment(2);\n\n      var contentLabel = DBCommentViewCell._genContentLabel();\n      self.addSubview(avatarButton);\n      self.addSubview(nameLabel);\n      self.addSubview(timeLabel);\n      self.addSubview(contentLabel);\n\n      self.setAvatarButton(avatarButton);\n      self.setNameLabel(nameLabel);\n      self.setTimeLabel(timeLabel);\n      self.setContentLabel(contentLabel);\n    }\n    return self;\n  },\n  renderWithComment: function(comment) {\n    self.avatarButton().sd__setImageWithURL_forState(require('NSURL').URLWithString(comment['user']['avatar_url']), 0);\n    self.nameLabel().setText(comment['user']['name'])\n\n    var d = new Date(comment['created_at']);\n    var dateStr = d.getFullYear() + '-' + (d.getMonth() + 1) + '-' + d.getDate() + '-';// + ' ' + d.getHours() + ':' + d.getMinutes();\n    self.timeLabel().setText(dateStr);\n\n    DBCommentViewCell._renderContentLabel(comment, self.contentLabel());\n\n    self.setCommentData(comment);\n  },\n\n  handleTapUser : function(){\n    var cb = self.tapUserCallback();\n    if (cb) cb(self.commentData()['user']);\n  },\n  \n\n}, {\n\n  heightWithComment: function(comment) {\n    var contentLabel = self._genContentLabel();\n    self._renderContentLabel(comment, contentLabel);\n    var contentFrame = contentLabel.frame();\n    return contentFrame.height + contentFrame.y + gap;\n  },\n\n  _renderContentLabel: function(comment, contentLabel) {\n    if (!comment['bodyText']) {\n      comment['bodyText'] = comment['body'].replace('\\n', '').replace('</p>', '\\n').replace(/<[^>]+>/g,\"\")\n    }\n    contentLabel.setText(comment['bodyText']);\n\n    var size = contentLabel.sizeThatFits({width:contentLabel.frame().width, height:1000});\n    var frame = contentLabel.frame();\n    frame.height = size.height;\n    contentLabel.setFrame(frame);\n  },\n\n  _genContentLabel: function() {\n    var contentLabel = require('UILabel')\n                                  .alloc()\n                                  .initWithFrame({x:gap * 2 + avatarSize, y: gap*2 + 15, width:SCREEN_WIDTH - gap * 3 - avatarSize, height:0});\n\n    contentLabel.setFont(UIFont.systemFontOfSize(16));\n    contentLabel.setNumberOfLines(0);\n    return contentLabel;\n  }\n})"
  },
  {
    "path": "Demo/DribbbleDemo/dribbbleDemo/dribbble/DBTimelineController.js",
    "content": "include('DBTimelineViews.js')\ninclude('DBDetailController.js')\n\ndefineClass('WBTimelineViewController: UITableViewController', [\n  'loadingView', \n  'isLoading',\n  'shots',\n  'currPage'\n], {\n  init: function(){\n    self = self.super().init();\n\n    var loadingView = require('UIActivityIndicatorView').alloc().initWithActivityIndicatorStyle(2);\n    loadingView.setFrame({x: (SCREEN_WIDTH - 40) / 2, y:(SCREEN_HEIGHT - 40 - 64) / 2, width:40, height:40});\n    loadingView.startAnimating();\n    self.view().addSubview(loadingView);\n    self.setLoadingView(loadingView);\n\n    self.tableView().setBackgroundColor(UIColor.colorWithWhite_alpha(.9, 1));\n    self.tableView().setSeparatorStyle(0);\n    self.setTitle('Dribbble');\n\n    self.setShots([]);\n    self.setCurrPage(1);\n    self._loadShots();\n    return self;\n  },\n\n  _loadShots: function() {\n    self.setIsLoading(1)\n    var perPage = 20;\n    var slf = self;\n    DBDataSource.shareInstance().loadPublicShots(self.currPage(), perPage, function(shots){\n      slf.loadingView().removeFromSuperview();\n      slf.setShots(slf.shots().concat(shots));\n      slf.setCurrPage(slf.currPage() + 1);\n      slf.setIsLoading(0);\n\n      if (shots.length >= perPage) {\n        slf.tableView().setTableFooterView(DBLoadMoreView.alloc().init());\n      } else {\n        slf.tableView().setTableFooterView(null);\n      }\n      slf.tableView().reloadData();\n    }, function(){\n      //fail\n    })\n  },\n  numberOfSectionsInTableView: function(tableView) {\n    return 1;\n  },\n  tableView_numberOfRowsInSection: function(tableView, section) {\n    return self.shots().length / 2;\n  },\n  tableView_cellForRowAtIndexPath: function(tableView, indexPath) {\n    var cell = tableView.dequeueReusableCellWithIdentifier(\"cell\") \n    if (!cell) {\n      cell = DBTimelineViewCell.alloc().initWithStyle_reuseIdentifier(0, \"cell\")\n      var slf = self;\n      cell.setTapCallback(function(item){\n        slf._handleGotoItem(item);\n      })\n    }\n\n    cell.renderWithItems(self.shots()[indexPath.row()*2],\n                         self.shots()[indexPath.row()*2 + 1]);\n    return cell\n  },\n  tableView_heightForRowAtIndexPath: function(tableView, indexPath) {\n    return (SCREEN_WIDTH / 2) *3/4 + 30;\n  },\n\n  scrollViewDidScroll: function(scrollView) {\n    var contentOffset = scrollView.contentOffset();\n    var contentSize = scrollView.contentSize();\n    if (!self.isLoading() && contentOffset.y - contentSize.height > -SCREEN_HEIGHT) {\n      self._loadShots();\n    }\n  },\n\n  _handleGotoItem: function(item) {\n    var detailVC = DBDetailViewController.alloc().initWithItem(item);\n    self.navigationController().pushViewController_animated(detailVC, YES);\n  }\n})"
  },
  {
    "path": "Demo/DribbbleDemo/dribbbleDemo/dribbble/DBTimelineViews.js",
    "content": "var gap = 10;\nvar avatarSize = 40;\nrequire('UILabel, UIColor, UIFont, UITextView');\n\n\ndefineClass('DBTimelineItemView: UIView', [\n    'avatarImageView', \n    'nameLabel',\n    'contentImageBtn',\n    'tapCallback'\n], {\n  init: function(){\n    self = self.super().init();\n\n    var imgGap = 5;\n    var width = (SCREEN_WIDTH - 10 * 3) / 2;\n    self.setFrame({x: 0, y: 0, width:width, height: width * 3/4 + 30});\n    self.setBackgroundColor(UIColor.whiteColor());\n\n    var contentImageBtn = require('UIButton')\n                            .alloc()\n                            .initWithFrame({x: imgGap, y:imgGap, width:width - 2*imgGap, height:(width - 2*imgGap)*3/4});\n    self.addSubview(contentImageBtn);\n    self.setContentImageBtn(contentImageBtn);\n    contentImageBtn.addTarget_action_forControlEvents(self, 'handleTap', 1 <<  6);\n\n    var avatarSize = 18;\n\n    var avatarImageView = require('UIImageView')\n                            .alloc()\n                            .initWithFrame({x:imgGap, y:contentImageBtn.frame().height + contentImageBtn.frame().y + imgGap + 2, width:avatarSize, height:avatarSize});\n    self.addSubview(avatarImageView);\n    self.setAvatarImageView(avatarImageView);\n\n    var nameLabel = UILabel\n                      .alloc()\n                      .initWithFrame({x: imgGap + avatarSize + 5, y:avatarImageView.frame().y, width:width - avatarSize - imgGap*2 - 5 , height:avatarSize});\n    nameLabel.setFont(UIFont.systemFontOfSize(12));\n    nameLabel.setTextColor(UIColor.grayColor());\n    self.addSubview(nameLabel);\n    self.setNameLabel(nameLabel);\n\n    return self;\n  },\n\n  handleTap: function() {\n    var cb = self.tapCallback();\n    if (cb) cb();\n  },\n\n  renderWithItem: function(item) {\n    self.contentImageBtn().sd__setImageWithURL_forState(require('NSURL').URLWithString(item['images']['normal']), 0);\n    self.avatarImageView().sd__setImageWithURL(require('NSURL').URLWithString(item['user']['avatar_url']));\n    self.nameLabel().setText(item['user']['name']);\n  },\n\n})\n\ndefineClass('DBTimelineViewCell: UITableViewCell', [\n    'itemView1', \n    'itemView2',\n    'tapCallback',\n], {\n  initWithStyle_reuseIdentifier: function(style, reuseIdentifier) {\n      self = self.super().initWithStyle_reuseIdentifier(style, reuseIdentifier);\n      if (self) {\n        self.setSelectionStyle(0);\n        self.contentView().setBackgroundColor(UIColor.colorWithWhite_alpha(.9, 1));\n        self._initItemView();\n      }\n      return self;\n  },\n  _initItemView: function(){\n    var itemView1 = DBTimelineItemView.alloc().init();\n    var itemView2 = DBTimelineItemView.alloc().init();\n\n    itemView1.setFrame({x:gap, y: gap, width: itemView1.frame().width, height: itemView1.frame().height});\n    itemView2.setFrame({x:gap*2 + itemView1.frame().width, y: gap, width: itemView2.frame().width, height: itemView2.frame().height});\n\n    self.setItemView1(itemView1);\n    self.setItemView2(itemView2);\n\n    self.addSubview(itemView1);\n    self.addSubview(itemView2);\n  },\n  renderWithItems: function(item1, item2) {\n    if (item1) {\n      self.itemView1().renderWithItem(item1);\n    }\n    if (item2) {\n      self.itemView2().renderWithItem(item2);\n    }\n    self.itemView1().setHidden(!item1);\n    self.itemView2().setHidden(!item2);\n\n    var slf = self\n    self.itemView1().setTapCallback(function(){\n      var cb = slf.tapCallback();\n      if (cb) cb(item1);\n    })\n    self.itemView2().setTapCallback(function(){\n      var cb = slf.tapCallback();\n      if (cb) cb(item2);\n    })\n  }\n})\n\ndefineClass('DBLoadMoreView:UIView', {\n  init: function(){\n    self = self.super().init();\n    \n    var loadingView = require('UIActivityIndicatorView').alloc().initWithActivityIndicatorStyle(2);\n    loadingView.startAnimating();\n    loadingView.setFrame({x:(SCREEN_WIDTH - 140) / 2, y: 10, width:40, height: 40});\n\n    var loadingLabel = require('UILabel').alloc().init();\n    loadingLabel.setText('Loading...');\n    loadingLabel.setFrame({x:(SCREEN_WIDTH - 140) / 2 + 40, y: 10, width:90, height: 40});\n    loadingLabel.setTextColor(require('UIColor').grayColor());\n\n    self.addSubview(loadingView);\n    self.addSubview(loadingLabel);\n\n    self.setFrame({x:0, y:0, width:SCREEN_WIDTH, height: 60});\n    return self;\n  },\n})"
  },
  {
    "path": "Demo/DribbbleDemo/dribbbleDemo/dribbble/DBUserController.js",
    "content": "include('DBTimelineViews.js')\ninclude('DBUserViews.js')\n\ndefineClass('DBUserViewController: UITableViewController', [\n  'loadingView', \n  'isLoading',\n  'commentsData',\n  'user',\n  'shots',\n  'currPage'\n  ], {\n  initWithUser: function(user){\n    self = self.super().init();\n    if (self) {\n      self.tableView().setSeparatorStyle(0);\n      self.tableView().setBackgroundColor(UIColor.colorWithWhite_alpha(.9, 1));\n      self.setTitle(user['name']);\n\n      var headerView = DBUserHeaderView.alloc().initWithUser(user);\n      self.tableView().setTableHeaderView(headerView);\n\n      var loadingView = require('UIActivityIndicatorView').alloc().initWithActivityIndicatorStyle(2);\n      loadingView.setFrame({x: (SCREEN_WIDTH - 40) / 2, y:headerView.frame().height + 30, width:40, height:40});\n      loadingView.startAnimating();\n      self.view().addSubview(loadingView);\n      self.setLoadingView(loadingView);\n\n      self.setShots([]);\n      self.setUser(user);\n      self.setCurrPage(1);\n      self._loadShots();\n    }\n    return self;\n  },\n\n  _loadShots: function(){\n    self.setIsLoading(1)\n    var user = self.user();\n    var perPage = 10;\n    var slf = self;\n    DBDataSource.shareInstance().loadUserShots(user['id'], self.currPage(), perPage, function(newShots){\n      slf.loadingView().removeFromSuperview();\n      slf.setShots(slf.shots().concat(newShots));\n      slf.setCurrPage(slf.currPage() + 1);\n      slf.setIsLoading(0);\n\n      if (newShots.length >= perPage) {\n        slf.tableView().setTableFooterView(DBLoadMoreView.alloc().init());\n      } else {\n        slf.tableView().setTableFooterView(null);\n      }\n      slf.tableView().reloadData();\n    }, function(){\n      //fail\n    })\n  },\n  numberOfSectionsInTableView: function(tableView) {\n    return 1;\n  },\n  tableView_numberOfRowsInSection: function(tableView, section) {\n    if (!self.shots()) return 0;\n    return self.shots().length / 2;\n  },\n  tableView_cellForRowAtIndexPath: function(tableView, indexPath) {\n    var cell = tableView.dequeueReusableCellWithIdentifier(\"cell\") \n    if (!cell) {\n      cell = DBUserViewCell.alloc().initWithStyle_reuseIdentifier(0, \"cell\")\n      var slf = self;\n      cell.setTapCallback(function(item){\n        slf._handleGotoItem(item);\n      })\n    }\n\n    cell.renderWithItems(self.shots()[indexPath.row()*2],\n                         self.shots()[indexPath.row()*2 + 1]);\n    return cell\n  },\n  tableView_heightForRowAtIndexPath: function(tableView, indexPath) {\n    return (SCREEN_WIDTH / 2) *3/4;\n  },\n\n  scrollViewDidScroll: function(scrollView) {\n    var contentOffset = scrollView.contentOffset();\n    var contentSize = scrollView.contentSize();\n    if (!self.isLoading() && self.tableView().tableFooterView() && contentOffset.y - contentSize.height > -SCREEN_HEIGHT) {\n      self._loadShots();\n    }\n  },\n\n  _handleGotoItem: function(item) {\n    if (!item.user) item.user = self.user();\n    var detailVC = DBDetailViewController.alloc().initWithItem(item);\n    self.navigationController().pushViewController_animated(detailVC, YES);\n  }\n})"
  },
  {
    "path": "Demo/DribbbleDemo/dribbbleDemo/dribbble/DBUserViews.js",
    "content": "var gap = 10;\n\ndefineClass('DBUserHeaderView: UIView', {\n  initWithUser: function(user) {\n    self = self.super().init();\n    if (self) {\n      var avatarSize = 100;\n      var avatarImageView = require('UIImageView')\n                              .alloc()\n                              .initWithFrame({x:(SCREEN_WIDTH - avatarSize) / 2, y:30, width:avatarSize, height:avatarSize});\n\n\n      var nameLabel = UILabel\n                        .alloc()\n                        .initWithFrame({x: 0, y:UIHelper.bottomY(avatarImageView) + 10, width:SCREEN_WIDTH, height:30});\n      nameLabel.setFont(UIFont.systemFontOfSize(18));\n      nameLabel.setTextAlignment(1);\n\n\n      var panelView = UIView\n                        .alloc()\n                        .initWithFrame({x:0, y:UIHelper.bottomY(nameLabel) + 10,width:SCREEN_WIDTH, height:80});\n\n      var followerView = self._genUserDataView('follower', user['followers_count']);\n      var shotsView = self._genUserDataView('shots', user['shots_count']);\n      var likeView = self._genUserDataView('likes', user['likes_received_count']);\n\n      UIHelper.setX(shotsView, UIHelper.rightX(followerView));\n      UIHelper.setX(likeView, UIHelper.rightX(shotsView));\n\n      panelView.addSubview(followerView);\n      panelView.addSubview(shotsView);\n      panelView.addSubview(likeView);\n\n      self.addSubview(avatarImageView);\n      self.addSubview(nameLabel);\n      self.addSubview(panelView);\n\n      avatarImageView.sd__setImageWithURL(require('NSURL').URLWithString(user['avatar_url']));\n      nameLabel.setText(user['name']);\n\n      self.setFrame({x:0, y:0, width:SCREEN_WIDTH, height: UIHelper.bottomY(panelView)});\n    }\n    return self;\n  },\n  _genUserDataView : function(name, num) {\n    var width = SCREEN_WIDTH / 3\n    var panelView = UIView\n                      .alloc()\n                      .initWithFrame({x:0,y:0,width:width,height:80});\n\n    var numLabel = UILabel.alloc().initWithFrame({x:0,y:0,width:width,height:40})\n    numLabel.setText(self._formatNum(num));\n    numLabel.setFont(UIFont.systemFontOfSize(22));\n    numLabel.setTextAlignment(1);\n\n    var nameLabel = UILabel.alloc().initWithFrame({x:0,y:35,width:width,height:30})\n    nameLabel.setText(name);\n    nameLabel.setFont(UIFont.systemFontOfSize(15));\n    nameLabel.setTextColor(UIColor.colorWithWhite_alpha(.5, 1))\n    nameLabel.setTextAlignment(1);\n\n    panelView.addSubview(numLabel);\n    panelView.addSubview(nameLabel);\n\n    return panelView;\n  },\n  _formatNum: function(num){\n    if (num >= 1000) {\n      return (num/1000).toFixed(1) + 'k'\n    }\n    return num ? num.toString() : 0;\n  }\n})\n\n\n\n\ndefineClass('DBUserItemView: DBTimelineItemView', {\n  init: function() {\n    self = self.super().init();\n    self.avatarImageView().removeFromSuperview();\n    self.nameLabel().removeFromSuperview();\n    var width = (SCREEN_WIDTH - 10 * 3) / 2;\n    self.setFrame({x: 0, y: 0, width:width, height: width * 3/4 + 5});\n    return self;\n  },\n  renderWithItem: function(item) {\n    self.contentImageBtn().sd__setImageWithURL_forState(require('NSURL').URLWithString(item['images']['normal']), 0);\n  },\n\n});\n\n\n\ndefineClass('DBUserViewCell: DBTimelineViewCell', {\n  _initItemView: function() {\n    var itemView1 = DBUserItemView.alloc().init();\n    var itemView2 = DBUserItemView.alloc().init();\n\n    itemView1.setFrame({x:gap, y: gap, width: itemView1.frame().width, height: itemView1.frame().height});\n    itemView2.setFrame({x:gap*2 + itemView1.frame().width, y: gap, width: itemView2.frame().width, height: itemView2.frame().height});\n\n    self.setItemView1(itemView1);\n    self.setItemView2(itemView2);\n\n    self.addSubview(itemView1);\n    self.addSubview(itemView2);\n  },\n\n});\n\n\n\n"
  },
  {
    "path": "Demo/DribbbleDemo/dribbbleDemo/dribbble/main.js",
    "content": "autoConvertOCType(1)\ninclude('CommonDefine.js')\ninclude('DBDataSource.js')\ninclude('DBTimelineController.js')\n\ndefineClass('AppDelegate', {\n  initRootViewController: function() {\n    var tableViewCtrl = WBTimelineViewController.alloc().init()\n    var navCtrl = require('UINavigationController').alloc().initWithRootViewController(tableViewCtrl);\n    self.window().setRootViewController(navCtrl);\n  }\n})\n"
  },
  {
    "path": "Demo/DribbbleDemo/dribbbleDemo/dribbble/tmpData.js",
    "content": "\nvar tmpData = [\n  {\n    \"id\": 2619381,\n    \"title\": \"Seaborn Oyster Co.\",\n    \"description\": null,\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher.jpg\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher_1x.jpg\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher_teaser.jpg\"\n    },\n    \"views_count\": 2166,\n    \"likes_count\": 235,\n    \"comments_count\": 2,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 11,\n    \"created_at\": \"2016-03-29T17:12:41Z\",\n    \"updated_at\": \"2016-03-29T17:12:53Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619381-Seaborn-Oyster-Co\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619381/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619381/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619381/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619381/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619381/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619381/rebounds\",\n    \"animated\": false,\n    \"tags\": [\n      \"charleston\",\n      \"company\",\n      \"ocean\",\n      \"oyster\",\n      \"sea\",\n      \"wave\"\n    ],\n    \"user\": {\n      \"id\": 52758,\n      \"name\": \"Jay Fletcher\",\n      \"username\": \"jfletcherdesign\",\n      \"html_url\": \"https://dribbble.com/jfletcherdesign\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/52758/avatars/normal/J_FLETCHER_DESIGN_LOGO-01.jpg?1401983283\",\n      \"bio\": \"\",\n      \"location\": \"Charleston, SC\",\n      \"links\": {\n        \"web\": \"http://www.jfletcherdesign.com\",\n        \"twitter\": \"https://twitter.com/jfletcherdesign\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 5239,\n      \"followers_count\": 13803,\n      \"followings_count\": 558,\n      \"likes_count\": 6531,\n      \"likes_received_count\": 104895,\n      \"projects_count\": 10,\n      \"rebounds_received_count\": 325,\n      \"shots_count\": 481,\n      \"teams_count\": 0,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/52758/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/52758/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/52758/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/52758/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/52758/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/52758/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/52758/teams\",\n      \"created_at\": \"2011-08-13T23:30:38Z\",\n      \"updated_at\": \"2016-03-29T17:12:53Z\"\n    },\n    \"team\": null\n  },\n  {\n    \"id\": 2619494,\n    \"title\": \"Mystery Project 72.1\",\n    \"description\": \"<p>We're excited to be onboard for a new year of Outside Lands festival branding! Stay tuned for weekly updates including Ranger Dave's new patch series, the 2016 lineup, and more!</p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/31348/screenshots/2619494/patches-30.jpg\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/31348/screenshots/2619494/patches-30_1x.jpg\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/31348/screenshots/2619494/patches-30_teaser.jpg\"\n    },\n    \"views_count\": 2304,\n    \"likes_count\": 252,\n    \"comments_count\": 4,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 11,\n    \"created_at\": \"2016-03-29T18:05:57Z\",\n    \"updated_at\": \"2016-03-29T18:07:21Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619494-Mystery-Project-72-1\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619494/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619494/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619494/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619494/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619494/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619494/rebounds\",\n    \"rebound_source_url\": \"https://api.dribbble.com/v1/shots/2454166\",\n    \"animated\": false,\n    \"tags\": [\n      \"badge\",\n      \"branding\",\n      \"bridge\",\n      \"city\",\n      \"dan kuhlken\",\n      \"dkng\",\n      \"logo\",\n      \"nathan goldman\",\n      \"patch\",\n      \"san francisco\",\n      \"vector\"\n    ],\n    \"user\": {\n      \"id\": 31348,\n      \"name\": \"DKNG\",\n      \"username\": \"DKNG\",\n      \"html_url\": \"https://dribbble.com/DKNG\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/31348/avatars/original/dkng_twitter.jpg?1305140827\",\n      \"bio\": \"Established in 2005, DKNG is a design studio based in Los Angeles, California with a focus on the music and entertainment industries.\",\n      \"location\": \"Los Angeles, CA\",\n      \"links\": {\n        \"web\": \"http://www.dkngstudios.com\",\n        \"twitter\": \"https://twitter.com/DKNGstudios\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 5274,\n      \"followers_count\": 24704,\n      \"followings_count\": 256,\n      \"likes_count\": 197,\n      \"likes_received_count\": 125646,\n      \"projects_count\": 47,\n      \"rebounds_received_count\": 324,\n      \"shots_count\": 479,\n      \"teams_count\": 0,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/31348/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/31348/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/31348/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/31348/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/31348/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/31348/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/31348/teams\",\n      \"created_at\": \"2011-04-28T20:48:48Z\",\n      \"updated_at\": \"2016-03-29T18:07:21Z\"\n    },\n    \"team\": null\n  },\n  {\n    \"id\": 2619183,\n    \"title\": \"Bonsai\",\n    \"description\": null,\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/44323/screenshots/2619183/bonsai.png\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/44323/screenshots/2619183/bonsai_1x.png\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/44323/screenshots/2619183/bonsai_teaser.png\"\n    },\n    \"views_count\": 2143,\n    \"likes_count\": 259,\n    \"comments_count\": 11,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 18,\n    \"created_at\": \"2016-03-29T15:48:38Z\",\n    \"updated_at\": \"2016-03-29T15:49:04Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619183-Bonsai\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619183/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619183/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619183/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619183/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619183/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619183/rebounds\",\n    \"animated\": false,\n    \"tags\": [\n      \"bonsai\",\n      \"illustration\",\n      \"nature\",\n      \"plant\",\n      \"pot\",\n      \"tree\",\n      \"zen\"\n    ],\n    \"user\": {\n      \"id\": 44323,\n      \"name\": \"Zach Roszczewski\",\n      \"username\": \"ZachRoszczewski\",\n      \"html_url\": \"https://dribbble.com/ZachRoszczewski\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/44323/avatars/normal/18f509c70a25627b40d5e3499b1cba2f.png?1419195740\",\n      \"bio\": \"Iconographer &amp; Illustrator. Creator of <a href=\\\"http://www.flaticons.co\\\" rel=\\\"nofollow noreferrer\\\">www.flaticons.co</a> &amp; <a href=\\\"http://www.mojiapp.net\\\" rel=\\\"nofollow noreferrer\\\">www.mojiapp.net</a>.\",\n      \"location\": \"Encinitas, California\",\n      \"links\": {\n        \"web\": \"http://zachroszczewski.com\",\n        \"twitter\": \"https://twitter.com/ZachRoszczewski\"\n      },\n      \"buckets_count\": 10,\n      \"comments_received_count\": 1682,\n      \"followers_count\": 9067,\n      \"followings_count\": 1541,\n      \"likes_count\": 14094,\n      \"likes_received_count\": 34409,\n      \"projects_count\": 7,\n      \"rebounds_received_count\": 14,\n      \"shots_count\": 113,\n      \"teams_count\": 2,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/44323/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/44323/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/44323/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/44323/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/44323/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/44323/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/44323/teams\",\n      \"created_at\": \"2011-07-07T14:49:07Z\",\n      \"updated_at\": \"2016-03-29T15:49:04Z\"\n    },\n    \"team\": null\n  },\n  {\n    \"id\": 2619255,\n    \"title\": \"Canvas—A new space for big ideas\",\n    \"description\": \"<p>A month ago the our team launched Canvas, a product for brands to tell their story and highlight products. It's been amazing to see your excitement for the creative possibilities and we can't wait to see how you use it. </p>\\n\\n<p>One of the best aspects of working on ads at Facebook is striving to find the sweet spot between the goals of our advertisers and those of people browsing their feed. Canvas allows businesses to create a more compelling experience for people, and in turn provides people with an ad they actually enjoy. Stay tuned for more :) </p>\\n\\n<p>If your interested in learning more about Canvas, or building one, you should check out <a href=\\\"https://canvas.facebook.com/\\\" target=\\\"_blank\\\" rel=\\\"noreferrer\\\">https://canvas.facebook.com/</a>\\n<br />To learn more about our process check out Jaime Rovira's medium post <a href=\\\"https://medium.com/facebook-design/canvas-how-we-crafted-facebook-s-new-immersive-ads-696870e66b3f#.jy9w9l51m\\\" target=\\\"_blank\\\" rel=\\\"noreferrer\\\">https://medium.com/facebook-design/canvas-how-we-crafted-facebook-s-new-immersive-ads-696870e66b3f#.jy9w9l51m</a></p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/476251/screenshots/2619255/startdribbble.gif\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/476251/screenshots/2619255/startdribbble_1x.gif\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/476251/screenshots/2619255/startdribbble_teaser.gif\"\n    },\n    \"views_count\": 3502,\n    \"likes_count\": 262,\n    \"comments_count\": 9,\n    \"attachments_count\": 2,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 12,\n    \"created_at\": \"2016-03-29T16:18:33Z\",\n    \"updated_at\": \"2016-03-29T16:19:50Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619255-Canvas-A-new-space-for-big-ideas\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619255/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619255/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619255/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619255/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619255/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619255/rebounds\",\n    \"animated\": true,\n    \"tags\": [\n      \"android\",\n      \"animation\",\n      \"creative\",\n      \"illustration\",\n      \"ios\",\n      \"mobile\",\n      \"tool\"\n    ],\n    \"user\": {\n      \"id\": 476251,\n      \"name\": \"ali griffin\",\n      \"username\": \"aligdanger\",\n      \"html_url\": \"https://dribbble.com/aligdanger\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/476251/avatars/normal/ali.png?1404762398\",\n      \"bio\": \"Designing product <a href=\\\"https://dribbble.com/Facebook\\\">@Facebook</a>\",\n      \"location\": \"San Francisco, CA\",\n      \"links\": {\n        \"twitter\": \"https://twitter.com/aligdanger\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 203,\n      \"followers_count\": 513,\n      \"followings_count\": 289,\n      \"likes_count\": 1302,\n      \"likes_received_count\": 2487,\n      \"projects_count\": 3,\n      \"rebounds_received_count\": 9,\n      \"shots_count\": 22,\n      \"teams_count\": 1,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/476251/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/476251/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/476251/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/476251/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/476251/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/476251/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/476251/teams\",\n      \"created_at\": \"2014-01-10T18:37:14Z\",\n      \"updated_at\": \"2016-03-30T04:07:49Z\"\n    },\n    \"team\": {\n      \"id\": 333588,\n      \"name\": \"Facebook\",\n      \"username\": \"Facebook\",\n      \"html_url\": \"https://dribbble.com/Facebook\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/333588/avatars/normal/9a9d5301e289975fa16abd070f1615c0.png?1440610176\",\n      \"bio\": \"\",\n      \"location\": \"1 Hacker Way, Menlo Park, CA\",\n      \"links\": {\n        \"web\": \"https://www.facebook.com/design\",\n        \"twitter\": \"https://twitter.com/facebookdesign\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 0,\n      \"followers_count\": 14039,\n      \"followings_count\": 0,\n      \"likes_count\": 2,\n      \"likes_received_count\": 0,\n      \"projects_count\": 0,\n      \"rebounds_received_count\": 0,\n      \"shots_count\": 121,\n      \"can_upload_shot\": true,\n      \"type\": \"Team\",\n      \"pro\": false,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/333588/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/333588/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/333588/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/333588/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/333588/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/333588/shots\",\n      \"created_at\": \"2013-05-15T23:13:37Z\",\n      \"updated_at\": \"2016-03-30T04:07:49Z\",\n      \"members_count\": 39,\n      \"members_url\": \"https://api.dribbble.com/v1/teams/333588/members\",\n      \"team_shots_url\": \"https://api.dribbble.com/v1/teams/333588/shots\"\n    }\n  },\n  {\n    \"id\": 2619346,\n    \"title\": \"Sunset\",\n    \"description\": \"<p>Baker Beach sunset from this weekend.</p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/3460/screenshots/2619346/sunset.png\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/3460/screenshots/2619346/sunset_1x.png\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/3460/screenshots/2619346/sunset_teaser.png\"\n    },\n    \"views_count\": 2897,\n    \"likes_count\": 231,\n    \"comments_count\": 3,\n    \"attachments_count\": 1,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 6,\n    \"created_at\": \"2016-03-29T16:55:27Z\",\n    \"updated_at\": \"2016-03-29T16:56:47Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619346-Sunset\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619346/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619346/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619346/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619346/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619346/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619346/rebounds\",\n    \"animated\": false,\n    \"tags\": [\n      \"beach\",\n      \"cartoon\",\n      \"comics\",\n      \"hand-darwn\",\n      \"illustration\",\n      \"nature\",\n      \"sketch\",\n      \"sunset\"\n    ],\n    \"user\": {\n      \"id\": 3460,\n      \"name\": \"Ryan Putnam\",\n      \"username\": \"RypeArts\",\n      \"html_url\": \"https://dribbble.com/RypeArts\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/3460/avatars/normal/4ed7a7a4737e971e3fa37f0705f5cc51.png?1457564367\",\n      \"bio\": \"designer, illustrator, potter, and father\",\n      \"location\": \"San Francisco, CA\",\n      \"links\": {\n        \"web\": \"http://ryanputn.am\",\n        \"twitter\": \"https://twitter.com/RypeArts\"\n      },\n      \"buckets_count\": 3,\n      \"comments_received_count\": 9722,\n      \"followers_count\": 46667,\n      \"followings_count\": 518,\n      \"likes_count\": 10207,\n      \"likes_received_count\": 211321,\n      \"projects_count\": 34,\n      \"rebounds_received_count\": 373,\n      \"shots_count\": 589,\n      \"teams_count\": 1,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/3460/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/3460/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/3460/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/3460/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/3460/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/3460/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/3460/teams\",\n      \"created_at\": \"2010-07-16T12:48:16Z\",\n      \"updated_at\": \"2016-03-29T16:56:47Z\"\n    },\n    \"team\": null\n  },\n  {\n    \"id\": 2619340,\n    \"title\": \"Skies Like These \",\n    \"description\": \"<p>In anticipation for their release of the paperback version of the book, Skies Like These, Macmillan commissioned us to redesign the cover artwork. </p>\\n\\n<p>The story is about a twelve-year-old girl name Jade who is sent to spend the summer with her aunt in Wyoming by her parents. She meets a rebellious boy who called himself Roy Parker, after the legendary Butch Cassidy. Jade tries to be a good friend Roy, but worries about the trouble he might get her into while he tries to plan stunts worthy of Butch Cassidy himself.\\n</p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/44585/screenshots/2619340/skies-like-these-dribbble.png\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/44585/screenshots/2619340/skies-like-these-dribbble_1x.png\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/44585/screenshots/2619340/skies-like-these-dribbble_teaser.png\"\n    },\n    \"views_count\": 1548,\n    \"likes_count\": 177,\n    \"comments_count\": 5,\n    \"attachments_count\": 1,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 7,\n    \"created_at\": \"2016-03-29T16:50:48Z\",\n    \"updated_at\": \"2016-03-29T16:53:16Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619340-Skies-Like-These\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619340/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619340/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619340/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619340/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619340/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619340/rebounds\",\n    \"animated\": false,\n    \"tags\": [\n      \"book\",\n      \"book cover\",\n      \"cover artwork\",\n      \"cover design\",\n      \"cowboy hat\",\n      \"illustration\",\n      \"mountain\",\n      \"planets\",\n      \"sky\",\n      \"stars\"\n    ],\n    \"user\": {\n      \"id\": 44585,\n      \"name\": \"Brad Woodard\",\n      \"username\": \"bradwwoodard\",\n      \"html_url\": \"https://dribbble.com/bradwwoodard\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/44585/avatars/normal/593686b9b9c0d2b6a496d8404f24ce1f.png?1444862250\",\n      \"bio\": \"Designer • Illustrator • Braver of the Woods\",\n      \"location\": \"Austin, TX\",\n      \"links\": {\n        \"web\": \"http://www.bravethewoods.com/\",\n        \"twitter\": \"https://twitter.com/brave_the_woods\"\n      },\n      \"buckets_count\": 1,\n      \"comments_received_count\": 2598,\n      \"followers_count\": 8556,\n      \"followings_count\": 412,\n      \"likes_count\": 2285,\n      \"likes_received_count\": 45938,\n      \"projects_count\": 21,\n      \"rebounds_received_count\": 16,\n      \"shots_count\": 324,\n      \"teams_count\": 0,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/44585/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/44585/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/44585/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/44585/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/44585/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/44585/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/44585/teams\",\n      \"created_at\": \"2011-07-08T15:47:58Z\",\n      \"updated_at\": \"2016-03-29T16:53:16Z\"\n    },\n    \"team\": null\n  },\n  {\n    \"id\": 2619544,\n    \"title\": \"Robinhood\",\n    \"description\": \"<p>Robinhood integrations illustration. </p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/4598/screenshots/2619544/integrations_header_01.png\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/4598/screenshots/2619544/integrations_header_01_1x.png\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/4598/screenshots/2619544/integrations_header_01_teaser.png\"\n    },\n    \"views_count\": 1530,\n    \"likes_count\": 177,\n    \"comments_count\": 6,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 7,\n    \"created_at\": \"2016-03-29T18:24:59Z\",\n    \"updated_at\": \"2016-03-29T18:26:47Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619544-Robinhood\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619544/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619544/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619544/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619544/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619544/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619544/rebounds\",\n    \"animated\": false,\n    \"tags\": [\n      \"chart\",\n      \"finance\",\n      \"illustration\",\n      \"money\",\n      \"stock\"\n    ],\n    \"user\": {\n      \"id\": 4598,\n      \"name\": \"Ty Wilkins\",\n      \"username\": \"tywilkins\",\n      \"html_url\": \"https://dribbble.com/tywilkins\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/4598/avatars/normal/fox2.jpg?1391573055\",\n      \"bio\": \"hello@tywilkins.com\",\n      \"location\": \"San Francisco, CA\",\n      \"links\": {\n        \"web\": \"http://www.tywilkins.com\",\n        \"twitter\": \"https://twitter.com/tywilkins\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 1080,\n      \"followers_count\": 8222,\n      \"followings_count\": 527,\n      \"likes_count\": 0,\n      \"likes_received_count\": 21359,\n      \"projects_count\": 8,\n      \"rebounds_received_count\": 0,\n      \"shots_count\": 97,\n      \"teams_count\": 1,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/4598/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/4598/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/4598/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/4598/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/4598/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/4598/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/4598/teams\",\n      \"created_at\": \"2010-09-30T20:31:02Z\",\n      \"updated_at\": \"2016-03-29T18:27:54Z\"\n    },\n    \"team\": null\n  },\n  {\n    \"id\": 2619187,\n    \"title\": \"Confidential iPad App part #2\",\n    \"description\": \"<p>Over the holidays, Rally built an iPad app for a confidential client and conference. This is video directly from interacting with the native iOS app.</p>\\n\\n<p>Myself, <a href=\\\"https://dribbble.com/4777\\\">@Geof Crowl</a>, and Wes tackled the project in just 15 days. It was intense but fun. Geof and I did the design and helped with layout in Xcode using Nibs. Wes built the globe and the data visualizations from a json file using our own Open GL globe library we've been building on an off for the past year. </p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/3816/screenshots/2619187/confidential-ipad-app-rally.gif\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/3816/screenshots/2619187/confidential-ipad-app-rally_1x.gif\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/3816/screenshots/2619187/confidential-ipad-app-rally_teaser.gif\"\n    },\n    \"views_count\": 3205,\n    \"likes_count\": 183,\n    \"comments_count\": 9,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 20,\n    \"created_at\": \"2016-03-29T15:50:05Z\",\n    \"updated_at\": \"2016-03-29T15:51:33Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619187-Confidential-iPad-App-part-2\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619187/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619187/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619187/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619187/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619187/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619187/rebounds\",\n    \"animated\": true,\n    \"tags\": [\n\n    ],\n    \"user\": {\n      \"id\": 3816,\n      \"name\": \"Ben Cline\",\n      \"username\": \"letsgorally\",\n      \"html_url\": \"https://dribbble.com/letsgorally\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/3816/avatars/normal/bb00fd14001a8cdd5e0e354df52a7fa4.png?1450769044\",\n      \"bio\": \"<a href=\\\"https://dribbble.com/RALLY\\\">@RALLY</a> Co-Founder / Designer\",\n      \"location\": \"Salt Lake City\",\n      \"links\": {\n        \"web\": \"http://beta.rallyinteractive.com\",\n        \"twitter\": \"https://twitter.com/yocline\"\n      },\n      \"buckets_count\": 3,\n      \"comments_received_count\": 4525,\n      \"followers_count\": 30105,\n      \"followings_count\": 241,\n      \"likes_count\": 6878,\n      \"likes_received_count\": 87892,\n      \"projects_count\": 10,\n      \"rebounds_received_count\": 28,\n      \"shots_count\": 257,\n      \"teams_count\": 1,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/3816/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/3816/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/3816/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/3816/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/3816/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/3816/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/3816/teams\",\n      \"created_at\": \"2010-07-30T17:30:31Z\",\n      \"updated_at\": \"2016-03-29T15:51:33Z\"\n    },\n    \"team\": {\n      \"id\": 559317,\n      \"name\": \"RALLY\",\n      \"username\": \"rally\",\n      \"html_url\": \"https://dribbble.com/rally\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/559317/avatars/normal/rally_logo.png?1398641637\",\n      \"bio\": \"Interactive Studio. Design &amp; Development\",\n      \"location\": \"Salt Lake City\",\n      \"links\": {\n        \"web\": \"http://beta.rallyinteractive.com\",\n        \"twitter\": \"https://twitter.com/letsgorally\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 0,\n      \"followers_count\": 8281,\n      \"followings_count\": 6,\n      \"likes_count\": 73,\n      \"likes_received_count\": 0,\n      \"projects_count\": 14,\n      \"rebounds_received_count\": 0,\n      \"shots_count\": 273,\n      \"can_upload_shot\": true,\n      \"type\": \"Team\",\n      \"pro\": false,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/559317/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/559317/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/559317/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/559317/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/559317/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/559317/shots\",\n      \"created_at\": \"2014-04-27T23:31:42Z\",\n      \"updated_at\": \"2016-03-29T15:51:33Z\",\n      \"members_count\": 5,\n      \"members_url\": \"https://api.dribbble.com/v1/teams/559317/members\",\n      \"team_shots_url\": \"https://api.dribbble.com/v1/teams/559317/shots\"\n    }\n  },\n  {\n    \"id\": 2619200,\n    \"title\": \"Eilean Donan Castle\",\n    \"description\": \"<p>Day 209/365</p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/283823/screenshots/2619200/eilean_donan_castle-01.jpg\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/283823/screenshots/2619200/eilean_donan_castle-01_1x.jpg\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/283823/screenshots/2619200/eilean_donan_castle-01_teaser.jpg\"\n    },\n    \"views_count\": 1434,\n    \"likes_count\": 162,\n    \"comments_count\": 4,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 7,\n    \"created_at\": \"2016-03-29T15:54:42Z\",\n    \"updated_at\": \"2016-03-29T15:55:23Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619200-Eilean-Donan-Castle\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619200/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619200/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619200/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619200/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619200/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619200/rebounds\",\n    \"rebound_source_url\": \"https://api.dribbble.com/v1/shots/2614735\",\n    \"animated\": false,\n    \"tags\": [\n      \"icon\",\n      \"illustration\",\n      \"lake\",\n      \"scotland\",\n      \"vector\"\n    ],\n    \"user\": {\n      \"id\": 283823,\n      \"name\": \"Scott Tusk\",\n      \"username\": \"Tusk\",\n      \"html_url\": \"https://dribbble.com/Tusk\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/283823/avatars/normal/c71f583fd2f781e48da28697c6ec2211.jpg?1456193406\",\n      \"bio\": \"\",\n      \"location\": \"Chicago\",\n      \"links\": {\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 1118,\n      \"followers_count\": 5013,\n      \"followings_count\": 812,\n      \"likes_count\": 2295,\n      \"likes_received_count\": 45133,\n      \"projects_count\": 1,\n      \"rebounds_received_count\": 214,\n      \"shots_count\": 282,\n      \"teams_count\": 1,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/283823/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/283823/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/283823/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/283823/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/283823/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/283823/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/283823/teams\",\n      \"created_at\": \"2013-02-17T16:32:29Z\",\n      \"updated_at\": \"2016-03-29T15:55:23Z\"\n    },\n    \"team\": null\n  },\n  {\n    \"id\": 2619378,\n    \"title\": \"Infinite Coffee\",\n    \"description\": \"<p>It's Monday, I need coffee. Forever.</p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/60266/screenshots/2619378/coffee.jpg\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/60266/screenshots/2619378/coffee_1x.jpg\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/60266/screenshots/2619378/coffee_teaser.jpg\"\n    },\n    \"views_count\": 1301,\n    \"likes_count\": 146,\n    \"comments_count\": 6,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 2,\n    \"created_at\": \"2016-03-29T17:11:50Z\",\n    \"updated_at\": \"2016-03-29T17:18:17Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619378-Infinite-Coffee\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619378/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619378/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619378/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619378/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619378/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619378/rebounds\",\n    \"animated\": false,\n    \"tags\": [\n      \"8\",\n      \"coffee\",\n      \"cup\",\n      \"food\",\n      \"geometric\",\n      \"illustration\",\n      \"infinite\",\n      \"kite\",\n      \"liquid\",\n      \"mug\",\n      \"stroke\"\n    ],\n    \"user\": {\n      \"id\": 60266,\n      \"name\": \"Gustavo Zambelli\",\n      \"username\": \"zamax\",\n      \"html_url\": \"https://dribbble.com/zamax\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/60266/avatars/normal/83d4ac61d50bf5b2fedc9f9cc45a62d9.png?1453312126\",\n      \"bio\": \"Hi, I&#39;m Lead of illustration at <a href=\\\"https://dribbble.com/aerolab\\\">@aerolab</a> &amp; Superman at <a href=\\\"https://dribbble.com/RicosQuesos\\\">@RicosQuesos</a>\",\n      \"location\": \"Neuquén, Argentina.\",\n      \"links\": {\n        \"web\": \"http://zamax.tumblr.com\",\n        \"twitter\": \"https://twitter.com/zamax4\"\n      },\n      \"buckets_count\": 19,\n      \"comments_received_count\": 1645,\n      \"followers_count\": 4198,\n      \"followings_count\": 1253,\n      \"likes_count\": 8828,\n      \"likes_received_count\": 36018,\n      \"projects_count\": 4,\n      \"rebounds_received_count\": 133,\n      \"shots_count\": 305,\n      \"teams_count\": 4,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/60266/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/60266/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/60266/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/60266/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/60266/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/60266/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/60266/teams\",\n      \"created_at\": \"2011-09-07T19:27:31Z\",\n      \"updated_at\": \"2016-03-29T17:18:17Z\"\n    },\n    \"team\": {\n      \"id\": 171431,\n      \"name\": \"Aerolab\",\n      \"username\": \"aerolab\",\n      \"html_url\": \"https://dribbble.com/aerolab\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/171431/avatars/normal/1283d5fbcd21a809d0cdc2f96a560096.png?1458077891\",\n      \"bio\": \"We design and develop beautiful digital products for startups and leading brands.\",\n      \"location\": \"Buenos Aires - San Francisco\",\n      \"links\": {\n        \"web\": \"http://aerolab.co\",\n        \"twitter\": \"https://twitter.com/aerolab\"\n      },\n      \"buckets_count\": 5,\n      \"comments_received_count\": 157,\n      \"followers_count\": 3845,\n      \"followings_count\": 128,\n      \"likes_count\": 4228,\n      \"likes_received_count\": 2121,\n      \"projects_count\": 24,\n      \"rebounds_received_count\": 2,\n      \"shots_count\": 579,\n      \"can_upload_shot\": true,\n      \"type\": \"Team\",\n      \"pro\": false,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/171431/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/171431/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/171431/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/171431/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/171431/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/171431/shots\",\n      \"created_at\": \"2012-07-04T02:31:07Z\",\n      \"updated_at\": \"2016-03-29T17:18:17Z\",\n      \"members_count\": 21,\n      \"members_url\": \"https://api.dribbble.com/v1/teams/171431/members\",\n      \"team_shots_url\": \"https://api.dribbble.com/v1/teams/171431/shots\"\n    }\n  },\n  {\n    \"id\": 2619645,\n    \"title\": \"Hello, Is It Me You're Looking For?\",\n    \"description\": \"<p>I had the privilege of getting to collaborate with <a href=\\\"https://dribbble.com/72483\\\">@Jordan Wade</a> on a hero illustration for his SVG post. And let me tell you, watching your work come alive with CSS and JS is pretty much the jam.</p>\\n\\n<p><a href=\\\"https://dribbble.com/shots/2619653-Hello-from-the-other-side\\\" rel=\\\"nofollow noreferrer\\\">Check it out all alive n' stuff!</a></p>\\n\\n<p><a href=\\\"https://www.codeschool.com/blog/2016/03/29/benefits-of-learning-how-to-use-svg/\\\" rel=\\\"nofollow noreferrer\\\">Go read about why you should learn more about SVG for the web</a>.</p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/13774/screenshots/2619645/hello.png\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/13774/screenshots/2619645/hello_1x.png\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/13774/screenshots/2619645/hello_teaser.png\"\n    },\n    \"views_count\": 1771,\n    \"likes_count\": 146,\n    \"comments_count\": 2,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 1,\n    \"buckets_count\": 2,\n    \"created_at\": \"2016-03-29T19:12:57Z\",\n    \"updated_at\": \"2016-03-29T20:26:49Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619645-Hello-Is-It-Me-You-re-Looking-For\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619645/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619645/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619645/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619645/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619645/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619645/rebounds\",\n    \"animated\": false,\n    \"tags\": [\n      \"hello\"\n    ],\n    \"user\": {\n      \"id\": 13774,\n      \"name\": \"Justin Mezzell\",\n      \"username\": \"JustinMezzell\",\n      \"html_url\": \"https://dribbble.com/JustinMezzell\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/13774/avatars/normal/Me_Web.jpg?1380768479\",\n      \"bio\": \"Designer? Illustrator? Why not. Directing Art at <a href=\\\"https://dribbble.com/codeschool\\\">@codeschool</a>.\",\n      \"location\": \"Orlando, FL\",\n      \"links\": {\n        \"web\": \"http://justinmezzell.com/\",\n        \"twitter\": \"https://twitter.com/JustinMezzell\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 5736,\n      \"followers_count\": 31449,\n      \"followings_count\": 713,\n      \"likes_count\": 5548,\n      \"likes_received_count\": 113425,\n      \"projects_count\": 0,\n      \"rebounds_received_count\": 55,\n      \"shots_count\": 312,\n      \"teams_count\": 4,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/13774/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/13774/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/13774/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/13774/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/13774/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/13774/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/13774/teams\",\n      \"created_at\": \"2011-01-26T06:58:50Z\",\n      \"updated_at\": \"2016-03-29T20:26:49Z\"\n    },\n    \"team\": {\n      \"id\": 333539,\n      \"name\": \"Code School\",\n      \"username\": \"codeschool\",\n      \"html_url\": \"https://dribbble.com/codeschool\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/333539/avatars/normal/329ac818d30ca1a7b900c09b105ce277.jpg?1410890340\",\n      \"bio\": \"Code School teaches web technologies in the comfort of your browser with video lessons, coding challenges, and screencasts.\",\n      \"location\": \"Orlando, FL\",\n      \"links\": {\n        \"web\": \"http://codeschool.com\",\n        \"twitter\": \"https://twitter.com/codeschool\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 0,\n      \"followers_count\": 3057,\n      \"followings_count\": 13,\n      \"likes_count\": 1,\n      \"likes_received_count\": 0,\n      \"projects_count\": 0,\n      \"rebounds_received_count\": 0,\n      \"shots_count\": 154,\n      \"can_upload_shot\": true,\n      \"type\": \"Team\",\n      \"pro\": false,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/333539/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/333539/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/333539/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/333539/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/333539/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/333539/shots\",\n      \"created_at\": \"2013-05-15T21:37:44Z\",\n      \"updated_at\": \"2016-03-29T20:26:49Z\",\n      \"members_count\": 10,\n      \"members_url\": \"https://api.dribbble.com/v1/teams/333539/members\",\n      \"team_shots_url\": \"https://api.dribbble.com/v1/teams/333539/shots\"\n    }\n  },\n  {\n    \"id\": 2619181,\n    \"title\": \"Costa Rica\",\n    \"description\": \"<p>Shirt graphic for offsite meeting in Costa Rica. </p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/21030/screenshots/2619181/costa.png\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/21030/screenshots/2619181/costa_1x.png\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/21030/screenshots/2619181/costa_teaser.png\"\n    },\n    \"views_count\": 1261,\n    \"likes_count\": 136,\n    \"comments_count\": 7,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 7,\n    \"created_at\": \"2016-03-29T15:48:25Z\",\n    \"updated_at\": \"2016-03-29T15:49:13Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619181-Costa-Rica\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619181/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619181/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619181/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619181/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619181/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619181/rebounds\",\n    \"animated\": false,\n    \"tags\": [\n      \"bird\",\n      \"costa rica\",\n      \"design\",\n      \"illustration\",\n      \"leaf\",\n      \"toucan\",\n      \"tropical\"\n    ],\n    \"user\": {\n      \"id\": 21030,\n      \"name\": \"Trevor Basset\",\n      \"username\": \"trevorbasset\",\n      \"html_url\": \"https://dribbble.com/trevorbasset\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/21030/avatars/normal/e9907b8b54ea842b30c5787ef95acc3a.png?1426787498\",\n      \"bio\": \"Design, art direction, illustration, birds. \",\n      \"location\": \"Seattle, WA\",\n      \"links\": {\n        \"web\": \"http://www.trevorbasset.com\",\n        \"twitter\": \"https://twitter.com/trevorbasset\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 244,\n      \"followers_count\": 1169,\n      \"followings_count\": 367,\n      \"likes_count\": 1204,\n      \"likes_received_count\": 3660,\n      \"projects_count\": 0,\n      \"rebounds_received_count\": 4,\n      \"shots_count\": 85,\n      \"teams_count\": 0,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": false,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/21030/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/21030/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/21030/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/21030/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/21030/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/21030/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/21030/teams\",\n      \"created_at\": \"2011-03-03T20:05:14Z\",\n      \"updated_at\": \"2016-03-30T04:08:03Z\"\n    },\n    \"team\": null\n  },\n  {\n    \"id\": 2619381,\n    \"title\": \"Seaborn Oyster Co.\",\n    \"description\": null,\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher.jpg\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher_1x.jpg\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher_teaser.jpg\"\n    },\n    \"views_count\": 2166,\n    \"likes_count\": 235,\n    \"comments_count\": 2,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 11,\n    \"created_at\": \"2016-03-29T17:12:41Z\",\n    \"updated_at\": \"2016-03-29T17:12:53Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619381-Seaborn-Oyster-Co\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619381/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619381/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619381/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619381/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619381/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619381/rebounds\",\n    \"animated\": false,\n    \"tags\": [\n      \"charleston\",\n      \"company\",\n      \"ocean\",\n      \"oyster\",\n      \"sea\",\n      \"wave\"\n    ],\n    \"user\": {\n      \"id\": 52758,\n      \"name\": \"Jay Fletcher\",\n      \"username\": \"jfletcherdesign\",\n      \"html_url\": \"https://dribbble.com/jfletcherdesign\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/52758/avatars/normal/J_FLETCHER_DESIGN_LOGO-01.jpg?1401983283\",\n      \"bio\": \"\",\n      \"location\": \"Charleston, SC\",\n      \"links\": {\n        \"web\": \"http://www.jfletcherdesign.com\",\n        \"twitter\": \"https://twitter.com/jfletcherdesign\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 5239,\n      \"followers_count\": 13803,\n      \"followings_count\": 558,\n      \"likes_count\": 6531,\n      \"likes_received_count\": 104895,\n      \"projects_count\": 10,\n      \"rebounds_received_count\": 325,\n      \"shots_count\": 481,\n      \"teams_count\": 0,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/52758/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/52758/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/52758/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/52758/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/52758/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/52758/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/52758/teams\",\n      \"created_at\": \"2011-08-13T23:30:38Z\",\n      \"updated_at\": \"2016-03-29T17:12:53Z\"\n    },\n    \"team\": null\n  },\n  {\n    \"id\": 2619494,\n    \"title\": \"Mystery Project 72.1\",\n    \"description\": \"<p>We're excited to be onboard for a new year of Outside Lands festival branding! Stay tuned for weekly updates including Ranger Dave's new patch series, the 2016 lineup, and more!</p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/31348/screenshots/2619494/patches-30.jpg\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/31348/screenshots/2619494/patches-30_1x.jpg\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/31348/screenshots/2619494/patches-30_teaser.jpg\"\n    },\n    \"views_count\": 2304,\n    \"likes_count\": 252,\n    \"comments_count\": 4,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 11,\n    \"created_at\": \"2016-03-29T18:05:57Z\",\n    \"updated_at\": \"2016-03-29T18:07:21Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619494-Mystery-Project-72-1\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619494/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619494/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619494/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619494/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619494/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619494/rebounds\",\n    \"rebound_source_url\": \"https://api.dribbble.com/v1/shots/2454166\",\n    \"animated\": false,\n    \"tags\": [\n      \"badge\",\n      \"branding\",\n      \"bridge\",\n      \"city\",\n      \"dan kuhlken\",\n      \"dkng\",\n      \"logo\",\n      \"nathan goldman\",\n      \"patch\",\n      \"san francisco\",\n      \"vector\"\n    ],\n    \"user\": {\n      \"id\": 31348,\n      \"name\": \"DKNG\",\n      \"username\": \"DKNG\",\n      \"html_url\": \"https://dribbble.com/DKNG\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/31348/avatars/original/dkng_twitter.jpg?1305140827\",\n      \"bio\": \"Established in 2005, DKNG is a design studio based in Los Angeles, California with a focus on the music and entertainment industries.\",\n      \"location\": \"Los Angeles, CA\",\n      \"links\": {\n        \"web\": \"http://www.dkngstudios.com\",\n        \"twitter\": \"https://twitter.com/DKNGstudios\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 5274,\n      \"followers_count\": 24704,\n      \"followings_count\": 256,\n      \"likes_count\": 197,\n      \"likes_received_count\": 125646,\n      \"projects_count\": 47,\n      \"rebounds_received_count\": 324,\n      \"shots_count\": 479,\n      \"teams_count\": 0,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/31348/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/31348/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/31348/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/31348/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/31348/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/31348/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/31348/teams\",\n      \"created_at\": \"2011-04-28T20:48:48Z\",\n      \"updated_at\": \"2016-03-29T18:07:21Z\"\n    },\n    \"team\": null\n  },\n  {\n    \"id\": 2619183,\n    \"title\": \"Bonsai\",\n    \"description\": null,\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/44323/screenshots/2619183/bonsai.png\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/44323/screenshots/2619183/bonsai_1x.png\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/44323/screenshots/2619183/bonsai_teaser.png\"\n    },\n    \"views_count\": 2143,\n    \"likes_count\": 259,\n    \"comments_count\": 11,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 18,\n    \"created_at\": \"2016-03-29T15:48:38Z\",\n    \"updated_at\": \"2016-03-29T15:49:04Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619183-Bonsai\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619183/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619183/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619183/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619183/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619183/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619183/rebounds\",\n    \"animated\": false,\n    \"tags\": [\n      \"bonsai\",\n      \"illustration\",\n      \"nature\",\n      \"plant\",\n      \"pot\",\n      \"tree\",\n      \"zen\"\n    ],\n    \"user\": {\n      \"id\": 44323,\n      \"name\": \"Zach Roszczewski\",\n      \"username\": \"ZachRoszczewski\",\n      \"html_url\": \"https://dribbble.com/ZachRoszczewski\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/44323/avatars/normal/18f509c70a25627b40d5e3499b1cba2f.png?1419195740\",\n      \"bio\": \"Iconographer &amp; Illustrator. Creator of <a href=\\\"http://www.flaticons.co\\\" rel=\\\"nofollow noreferrer\\\">www.flaticons.co</a> &amp; <a href=\\\"http://www.mojiapp.net\\\" rel=\\\"nofollow noreferrer\\\">www.mojiapp.net</a>.\",\n      \"location\": \"Encinitas, California\",\n      \"links\": {\n        \"web\": \"http://zachroszczewski.com\",\n        \"twitter\": \"https://twitter.com/ZachRoszczewski\"\n      },\n      \"buckets_count\": 10,\n      \"comments_received_count\": 1682,\n      \"followers_count\": 9067,\n      \"followings_count\": 1541,\n      \"likes_count\": 14094,\n      \"likes_received_count\": 34409,\n      \"projects_count\": 7,\n      \"rebounds_received_count\": 14,\n      \"shots_count\": 113,\n      \"teams_count\": 2,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/44323/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/44323/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/44323/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/44323/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/44323/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/44323/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/44323/teams\",\n      \"created_at\": \"2011-07-07T14:49:07Z\",\n      \"updated_at\": \"2016-03-29T15:49:04Z\"\n    },\n    \"team\": null\n  },\n  {\n    \"id\": 2619255,\n    \"title\": \"Canvas—A new space for big ideas\",\n    \"description\": \"<p>A month ago the our team launched Canvas, a product for brands to tell their story and highlight products. It's been amazing to see your excitement for the creative possibilities and we can't wait to see how you use it. </p>\\n\\n<p>One of the best aspects of working on ads at Facebook is striving to find the sweet spot between the goals of our advertisers and those of people browsing their feed. Canvas allows businesses to create a more compelling experience for people, and in turn provides people with an ad they actually enjoy. Stay tuned for more :) </p>\\n\\n<p>If your interested in learning more about Canvas, or building one, you should check out <a href=\\\"https://canvas.facebook.com/\\\" target=\\\"_blank\\\" rel=\\\"noreferrer\\\">https://canvas.facebook.com/</a>\\n<br />To learn more about our process check out Jaime Rovira's medium post <a href=\\\"https://medium.com/facebook-design/canvas-how-we-crafted-facebook-s-new-immersive-ads-696870e66b3f#.jy9w9l51m\\\" target=\\\"_blank\\\" rel=\\\"noreferrer\\\">https://medium.com/facebook-design/canvas-how-we-crafted-facebook-s-new-immersive-ads-696870e66b3f#.jy9w9l51m</a></p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/476251/screenshots/2619255/startdribbble.gif\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/476251/screenshots/2619255/startdribbble_1x.gif\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/476251/screenshots/2619255/startdribbble_teaser.gif\"\n    },\n    \"views_count\": 3502,\n    \"likes_count\": 262,\n    \"comments_count\": 9,\n    \"attachments_count\": 2,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 12,\n    \"created_at\": \"2016-03-29T16:18:33Z\",\n    \"updated_at\": \"2016-03-29T16:19:50Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619255-Canvas-A-new-space-for-big-ideas\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619255/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619255/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619255/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619255/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619255/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619255/rebounds\",\n    \"animated\": true,\n    \"tags\": [\n      \"android\",\n      \"animation\",\n      \"creative\",\n      \"illustration\",\n      \"ios\",\n      \"mobile\",\n      \"tool\"\n    ],\n    \"user\": {\n      \"id\": 476251,\n      \"name\": \"ali griffin\",\n      \"username\": \"aligdanger\",\n      \"html_url\": \"https://dribbble.com/aligdanger\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/476251/avatars/normal/ali.png?1404762398\",\n      \"bio\": \"Designing product <a href=\\\"https://dribbble.com/Facebook\\\">@Facebook</a>\",\n      \"location\": \"San Francisco, CA\",\n      \"links\": {\n        \"twitter\": \"https://twitter.com/aligdanger\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 203,\n      \"followers_count\": 513,\n      \"followings_count\": 289,\n      \"likes_count\": 1302,\n      \"likes_received_count\": 2487,\n      \"projects_count\": 3,\n      \"rebounds_received_count\": 9,\n      \"shots_count\": 22,\n      \"teams_count\": 1,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/476251/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/476251/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/476251/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/476251/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/476251/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/476251/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/476251/teams\",\n      \"created_at\": \"2014-01-10T18:37:14Z\",\n      \"updated_at\": \"2016-03-30T04:07:49Z\"\n    },\n    \"team\": {\n      \"id\": 333588,\n      \"name\": \"Facebook\",\n      \"username\": \"Facebook\",\n      \"html_url\": \"https://dribbble.com/Facebook\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/333588/avatars/normal/9a9d5301e289975fa16abd070f1615c0.png?1440610176\",\n      \"bio\": \"\",\n      \"location\": \"1 Hacker Way, Menlo Park, CA\",\n      \"links\": {\n        \"web\": \"https://www.facebook.com/design\",\n        \"twitter\": \"https://twitter.com/facebookdesign\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 0,\n      \"followers_count\": 14039,\n      \"followings_count\": 0,\n      \"likes_count\": 2,\n      \"likes_received_count\": 0,\n      \"projects_count\": 0,\n      \"rebounds_received_count\": 0,\n      \"shots_count\": 121,\n      \"can_upload_shot\": true,\n      \"type\": \"Team\",\n      \"pro\": false,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/333588/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/333588/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/333588/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/333588/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/333588/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/333588/shots\",\n      \"created_at\": \"2013-05-15T23:13:37Z\",\n      \"updated_at\": \"2016-03-30T04:07:49Z\",\n      \"members_count\": 39,\n      \"members_url\": \"https://api.dribbble.com/v1/teams/333588/members\",\n      \"team_shots_url\": \"https://api.dribbble.com/v1/teams/333588/shots\"\n    }\n  },\n  {\n    \"id\": 2619346,\n    \"title\": \"Sunset\",\n    \"description\": \"<p>Baker Beach sunset from this weekend.</p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/3460/screenshots/2619346/sunset.png\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/3460/screenshots/2619346/sunset_1x.png\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/3460/screenshots/2619346/sunset_teaser.png\"\n    },\n    \"views_count\": 2897,\n    \"likes_count\": 231,\n    \"comments_count\": 3,\n    \"attachments_count\": 1,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 6,\n    \"created_at\": \"2016-03-29T16:55:27Z\",\n    \"updated_at\": \"2016-03-29T16:56:47Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619346-Sunset\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619346/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619346/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619346/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619346/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619346/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619346/rebounds\",\n    \"animated\": false,\n    \"tags\": [\n      \"beach\",\n      \"cartoon\",\n      \"comics\",\n      \"hand-darwn\",\n      \"illustration\",\n      \"nature\",\n      \"sketch\",\n      \"sunset\"\n    ],\n    \"user\": {\n      \"id\": 3460,\n      \"name\": \"Ryan Putnam\",\n      \"username\": \"RypeArts\",\n      \"html_url\": \"https://dribbble.com/RypeArts\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/3460/avatars/normal/4ed7a7a4737e971e3fa37f0705f5cc51.png?1457564367\",\n      \"bio\": \"designer, illustrator, potter, and father\",\n      \"location\": \"San Francisco, CA\",\n      \"links\": {\n        \"web\": \"http://ryanputn.am\",\n        \"twitter\": \"https://twitter.com/RypeArts\"\n      },\n      \"buckets_count\": 3,\n      \"comments_received_count\": 9722,\n      \"followers_count\": 46667,\n      \"followings_count\": 518,\n      \"likes_count\": 10207,\n      \"likes_received_count\": 211321,\n      \"projects_count\": 34,\n      \"rebounds_received_count\": 373,\n      \"shots_count\": 589,\n      \"teams_count\": 1,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/3460/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/3460/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/3460/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/3460/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/3460/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/3460/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/3460/teams\",\n      \"created_at\": \"2010-07-16T12:48:16Z\",\n      \"updated_at\": \"2016-03-29T16:56:47Z\"\n    },\n    \"team\": null\n  },\n  {\n    \"id\": 2619340,\n    \"title\": \"Skies Like These \",\n    \"description\": \"<p>In anticipation for their release of the paperback version of the book, Skies Like These, Macmillan commissioned us to redesign the cover artwork. </p>\\n\\n<p>The story is about a twelve-year-old girl name Jade who is sent to spend the summer with her aunt in Wyoming by her parents. She meets a rebellious boy who called himself Roy Parker, after the legendary Butch Cassidy. Jade tries to be a good friend Roy, but worries about the trouble he might get her into while he tries to plan stunts worthy of Butch Cassidy himself.\\n</p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/44585/screenshots/2619340/skies-like-these-dribbble.png\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/44585/screenshots/2619340/skies-like-these-dribbble_1x.png\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/44585/screenshots/2619340/skies-like-these-dribbble_teaser.png\"\n    },\n    \"views_count\": 1548,\n    \"likes_count\": 177,\n    \"comments_count\": 5,\n    \"attachments_count\": 1,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 7,\n    \"created_at\": \"2016-03-29T16:50:48Z\",\n    \"updated_at\": \"2016-03-29T16:53:16Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619340-Skies-Like-These\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619340/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619340/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619340/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619340/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619340/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619340/rebounds\",\n    \"animated\": false,\n    \"tags\": [\n      \"book\",\n      \"book cover\",\n      \"cover artwork\",\n      \"cover design\",\n      \"cowboy hat\",\n      \"illustration\",\n      \"mountain\",\n      \"planets\",\n      \"sky\",\n      \"stars\"\n    ],\n    \"user\": {\n      \"id\": 44585,\n      \"name\": \"Brad Woodard\",\n      \"username\": \"bradwwoodard\",\n      \"html_url\": \"https://dribbble.com/bradwwoodard\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/44585/avatars/normal/593686b9b9c0d2b6a496d8404f24ce1f.png?1444862250\",\n      \"bio\": \"Designer • Illustrator • Braver of the Woods\",\n      \"location\": \"Austin, TX\",\n      \"links\": {\n        \"web\": \"http://www.bravethewoods.com/\",\n        \"twitter\": \"https://twitter.com/brave_the_woods\"\n      },\n      \"buckets_count\": 1,\n      \"comments_received_count\": 2598,\n      \"followers_count\": 8556,\n      \"followings_count\": 412,\n      \"likes_count\": 2285,\n      \"likes_received_count\": 45938,\n      \"projects_count\": 21,\n      \"rebounds_received_count\": 16,\n      \"shots_count\": 324,\n      \"teams_count\": 0,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/44585/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/44585/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/44585/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/44585/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/44585/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/44585/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/44585/teams\",\n      \"created_at\": \"2011-07-08T15:47:58Z\",\n      \"updated_at\": \"2016-03-29T16:53:16Z\"\n    },\n    \"team\": null\n  },\n  {\n    \"id\": 2619544,\n    \"title\": \"Robinhood\",\n    \"description\": \"<p>Robinhood integrations illustration. </p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/4598/screenshots/2619544/integrations_header_01.png\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/4598/screenshots/2619544/integrations_header_01_1x.png\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/4598/screenshots/2619544/integrations_header_01_teaser.png\"\n    },\n    \"views_count\": 1530,\n    \"likes_count\": 177,\n    \"comments_count\": 6,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 7,\n    \"created_at\": \"2016-03-29T18:24:59Z\",\n    \"updated_at\": \"2016-03-29T18:26:47Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619544-Robinhood\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619544/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619544/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619544/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619544/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619544/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619544/rebounds\",\n    \"animated\": false,\n    \"tags\": [\n      \"chart\",\n      \"finance\",\n      \"illustration\",\n      \"money\",\n      \"stock\"\n    ],\n    \"user\": {\n      \"id\": 4598,\n      \"name\": \"Ty Wilkins\",\n      \"username\": \"tywilkins\",\n      \"html_url\": \"https://dribbble.com/tywilkins\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/4598/avatars/normal/fox2.jpg?1391573055\",\n      \"bio\": \"hello@tywilkins.com\",\n      \"location\": \"San Francisco, CA\",\n      \"links\": {\n        \"web\": \"http://www.tywilkins.com\",\n        \"twitter\": \"https://twitter.com/tywilkins\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 1080,\n      \"followers_count\": 8222,\n      \"followings_count\": 527,\n      \"likes_count\": 0,\n      \"likes_received_count\": 21359,\n      \"projects_count\": 8,\n      \"rebounds_received_count\": 0,\n      \"shots_count\": 97,\n      \"teams_count\": 1,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/4598/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/4598/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/4598/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/4598/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/4598/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/4598/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/4598/teams\",\n      \"created_at\": \"2010-09-30T20:31:02Z\",\n      \"updated_at\": \"2016-03-29T18:27:54Z\"\n    },\n    \"team\": null\n  },\n  {\n    \"id\": 2619187,\n    \"title\": \"Confidential iPad App part #2\",\n    \"description\": \"<p>Over the holidays, Rally built an iPad app for a confidential client and conference. This is video directly from interacting with the native iOS app.</p>\\n\\n<p>Myself, <a href=\\\"https://dribbble.com/4777\\\">@Geof Crowl</a>, and Wes tackled the project in just 15 days. It was intense but fun. Geof and I did the design and helped with layout in Xcode using Nibs. Wes built the globe and the data visualizations from a json file using our own Open GL globe library we've been building on an off for the past year. </p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/3816/screenshots/2619187/confidential-ipad-app-rally.gif\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/3816/screenshots/2619187/confidential-ipad-app-rally_1x.gif\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/3816/screenshots/2619187/confidential-ipad-app-rally_teaser.gif\"\n    },\n    \"views_count\": 3205,\n    \"likes_count\": 183,\n    \"comments_count\": 9,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 20,\n    \"created_at\": \"2016-03-29T15:50:05Z\",\n    \"updated_at\": \"2016-03-29T15:51:33Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619187-Confidential-iPad-App-part-2\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619187/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619187/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619187/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619187/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619187/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619187/rebounds\",\n    \"animated\": true,\n    \"tags\": [\n\n    ],\n    \"user\": {\n      \"id\": 3816,\n      \"name\": \"Ben Cline\",\n      \"username\": \"letsgorally\",\n      \"html_url\": \"https://dribbble.com/letsgorally\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/3816/avatars/normal/bb00fd14001a8cdd5e0e354df52a7fa4.png?1450769044\",\n      \"bio\": \"<a href=\\\"https://dribbble.com/RALLY\\\">@RALLY</a> Co-Founder / Designer\",\n      \"location\": \"Salt Lake City\",\n      \"links\": {\n        \"web\": \"http://beta.rallyinteractive.com\",\n        \"twitter\": \"https://twitter.com/yocline\"\n      },\n      \"buckets_count\": 3,\n      \"comments_received_count\": 4525,\n      \"followers_count\": 30105,\n      \"followings_count\": 241,\n      \"likes_count\": 6878,\n      \"likes_received_count\": 87892,\n      \"projects_count\": 10,\n      \"rebounds_received_count\": 28,\n      \"shots_count\": 257,\n      \"teams_count\": 1,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/3816/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/3816/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/3816/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/3816/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/3816/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/3816/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/3816/teams\",\n      \"created_at\": \"2010-07-30T17:30:31Z\",\n      \"updated_at\": \"2016-03-29T15:51:33Z\"\n    },\n    \"team\": {\n      \"id\": 559317,\n      \"name\": \"RALLY\",\n      \"username\": \"rally\",\n      \"html_url\": \"https://dribbble.com/rally\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/559317/avatars/normal/rally_logo.png?1398641637\",\n      \"bio\": \"Interactive Studio. Design &amp; Development\",\n      \"location\": \"Salt Lake City\",\n      \"links\": {\n        \"web\": \"http://beta.rallyinteractive.com\",\n        \"twitter\": \"https://twitter.com/letsgorally\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 0,\n      \"followers_count\": 8281,\n      \"followings_count\": 6,\n      \"likes_count\": 73,\n      \"likes_received_count\": 0,\n      \"projects_count\": 14,\n      \"rebounds_received_count\": 0,\n      \"shots_count\": 273,\n      \"can_upload_shot\": true,\n      \"type\": \"Team\",\n      \"pro\": false,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/559317/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/559317/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/559317/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/559317/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/559317/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/559317/shots\",\n      \"created_at\": \"2014-04-27T23:31:42Z\",\n      \"updated_at\": \"2016-03-29T15:51:33Z\",\n      \"members_count\": 5,\n      \"members_url\": \"https://api.dribbble.com/v1/teams/559317/members\",\n      \"team_shots_url\": \"https://api.dribbble.com/v1/teams/559317/shots\"\n    }\n  },\n  {\n    \"id\": 2619200,\n    \"title\": \"Eilean Donan Castle\",\n    \"description\": \"<p>Day 209/365</p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/283823/screenshots/2619200/eilean_donan_castle-01.jpg\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/283823/screenshots/2619200/eilean_donan_castle-01_1x.jpg\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/283823/screenshots/2619200/eilean_donan_castle-01_teaser.jpg\"\n    },\n    \"views_count\": 1434,\n    \"likes_count\": 162,\n    \"comments_count\": 4,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 7,\n    \"created_at\": \"2016-03-29T15:54:42Z\",\n    \"updated_at\": \"2016-03-29T15:55:23Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619200-Eilean-Donan-Castle\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619200/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619200/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619200/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619200/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619200/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619200/rebounds\",\n    \"rebound_source_url\": \"https://api.dribbble.com/v1/shots/2614735\",\n    \"animated\": false,\n    \"tags\": [\n      \"icon\",\n      \"illustration\",\n      \"lake\",\n      \"scotland\",\n      \"vector\"\n    ],\n    \"user\": {\n      \"id\": 283823,\n      \"name\": \"Scott Tusk\",\n      \"username\": \"Tusk\",\n      \"html_url\": \"https://dribbble.com/Tusk\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/283823/avatars/normal/c71f583fd2f781e48da28697c6ec2211.jpg?1456193406\",\n      \"bio\": \"\",\n      \"location\": \"Chicago\",\n      \"links\": {\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 1118,\n      \"followers_count\": 5013,\n      \"followings_count\": 812,\n      \"likes_count\": 2295,\n      \"likes_received_count\": 45133,\n      \"projects_count\": 1,\n      \"rebounds_received_count\": 214,\n      \"shots_count\": 282,\n      \"teams_count\": 1,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/283823/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/283823/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/283823/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/283823/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/283823/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/283823/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/283823/teams\",\n      \"created_at\": \"2013-02-17T16:32:29Z\",\n      \"updated_at\": \"2016-03-29T15:55:23Z\"\n    },\n    \"team\": null\n  },\n  {\n    \"id\": 2619378,\n    \"title\": \"Infinite Coffee\",\n    \"description\": \"<p>It's Monday, I need coffee. Forever.</p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/60266/screenshots/2619378/coffee.jpg\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/60266/screenshots/2619378/coffee_1x.jpg\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/60266/screenshots/2619378/coffee_teaser.jpg\"\n    },\n    \"views_count\": 1301,\n    \"likes_count\": 146,\n    \"comments_count\": 6,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 2,\n    \"created_at\": \"2016-03-29T17:11:50Z\",\n    \"updated_at\": \"2016-03-29T17:18:17Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619378-Infinite-Coffee\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619378/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619378/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619378/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619378/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619378/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619378/rebounds\",\n    \"animated\": false,\n    \"tags\": [\n      \"8\",\n      \"coffee\",\n      \"cup\",\n      \"food\",\n      \"geometric\",\n      \"illustration\",\n      \"infinite\",\n      \"kite\",\n      \"liquid\",\n      \"mug\",\n      \"stroke\"\n    ],\n    \"user\": {\n      \"id\": 60266,\n      \"name\": \"Gustavo Zambelli\",\n      \"username\": \"zamax\",\n      \"html_url\": \"https://dribbble.com/zamax\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/60266/avatars/normal/83d4ac61d50bf5b2fedc9f9cc45a62d9.png?1453312126\",\n      \"bio\": \"Hi, I&#39;m Lead of illustration at <a href=\\\"https://dribbble.com/aerolab\\\">@aerolab</a> &amp; Superman at <a href=\\\"https://dribbble.com/RicosQuesos\\\">@RicosQuesos</a>\",\n      \"location\": \"Neuquén, Argentina.\",\n      \"links\": {\n        \"web\": \"http://zamax.tumblr.com\",\n        \"twitter\": \"https://twitter.com/zamax4\"\n      },\n      \"buckets_count\": 19,\n      \"comments_received_count\": 1645,\n      \"followers_count\": 4198,\n      \"followings_count\": 1253,\n      \"likes_count\": 8828,\n      \"likes_received_count\": 36018,\n      \"projects_count\": 4,\n      \"rebounds_received_count\": 133,\n      \"shots_count\": 305,\n      \"teams_count\": 4,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/60266/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/60266/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/60266/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/60266/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/60266/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/60266/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/60266/teams\",\n      \"created_at\": \"2011-09-07T19:27:31Z\",\n      \"updated_at\": \"2016-03-29T17:18:17Z\"\n    },\n    \"team\": {\n      \"id\": 171431,\n      \"name\": \"Aerolab\",\n      \"username\": \"aerolab\",\n      \"html_url\": \"https://dribbble.com/aerolab\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/171431/avatars/normal/1283d5fbcd21a809d0cdc2f96a560096.png?1458077891\",\n      \"bio\": \"We design and develop beautiful digital products for startups and leading brands.\",\n      \"location\": \"Buenos Aires - San Francisco\",\n      \"links\": {\n        \"web\": \"http://aerolab.co\",\n        \"twitter\": \"https://twitter.com/aerolab\"\n      },\n      \"buckets_count\": 5,\n      \"comments_received_count\": 157,\n      \"followers_count\": 3845,\n      \"followings_count\": 128,\n      \"likes_count\": 4228,\n      \"likes_received_count\": 2121,\n      \"projects_count\": 24,\n      \"rebounds_received_count\": 2,\n      \"shots_count\": 579,\n      \"can_upload_shot\": true,\n      \"type\": \"Team\",\n      \"pro\": false,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/171431/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/171431/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/171431/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/171431/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/171431/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/171431/shots\",\n      \"created_at\": \"2012-07-04T02:31:07Z\",\n      \"updated_at\": \"2016-03-29T17:18:17Z\",\n      \"members_count\": 21,\n      \"members_url\": \"https://api.dribbble.com/v1/teams/171431/members\",\n      \"team_shots_url\": \"https://api.dribbble.com/v1/teams/171431/shots\"\n    }\n  },\n  {\n    \"id\": 2619645,\n    \"title\": \"Hello, Is It Me You're Looking For?\",\n    \"description\": \"<p>I had the privilege of getting to collaborate with <a href=\\\"https://dribbble.com/72483\\\">@Jordan Wade</a> on a hero illustration for his SVG post. And let me tell you, watching your work come alive with CSS and JS is pretty much the jam.</p>\\n\\n<p><a href=\\\"https://dribbble.com/shots/2619653-Hello-from-the-other-side\\\" rel=\\\"nofollow noreferrer\\\">Check it out all alive n' stuff!</a></p>\\n\\n<p><a href=\\\"https://www.codeschool.com/blog/2016/03/29/benefits-of-learning-how-to-use-svg/\\\" rel=\\\"nofollow noreferrer\\\">Go read about why you should learn more about SVG for the web</a>.</p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/13774/screenshots/2619645/hello.png\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/13774/screenshots/2619645/hello_1x.png\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/13774/screenshots/2619645/hello_teaser.png\"\n    },\n    \"views_count\": 1771,\n    \"likes_count\": 146,\n    \"comments_count\": 2,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 1,\n    \"buckets_count\": 2,\n    \"created_at\": \"2016-03-29T19:12:57Z\",\n    \"updated_at\": \"2016-03-29T20:26:49Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619645-Hello-Is-It-Me-You-re-Looking-For\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619645/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619645/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619645/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619645/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619645/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619645/rebounds\",\n    \"animated\": false,\n    \"tags\": [\n      \"hello\"\n    ],\n    \"user\": {\n      \"id\": 13774,\n      \"name\": \"Justin Mezzell\",\n      \"username\": \"JustinMezzell\",\n      \"html_url\": \"https://dribbble.com/JustinMezzell\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/13774/avatars/normal/Me_Web.jpg?1380768479\",\n      \"bio\": \"Designer? Illustrator? Why not. Directing Art at <a href=\\\"https://dribbble.com/codeschool\\\">@codeschool</a>.\",\n      \"location\": \"Orlando, FL\",\n      \"links\": {\n        \"web\": \"http://justinmezzell.com/\",\n        \"twitter\": \"https://twitter.com/JustinMezzell\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 5736,\n      \"followers_count\": 31449,\n      \"followings_count\": 713,\n      \"likes_count\": 5548,\n      \"likes_received_count\": 113425,\n      \"projects_count\": 0,\n      \"rebounds_received_count\": 55,\n      \"shots_count\": 312,\n      \"teams_count\": 4,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/13774/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/13774/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/13774/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/13774/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/13774/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/13774/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/13774/teams\",\n      \"created_at\": \"2011-01-26T06:58:50Z\",\n      \"updated_at\": \"2016-03-29T20:26:49Z\"\n    },\n    \"team\": {\n      \"id\": 333539,\n      \"name\": \"Code School\",\n      \"username\": \"codeschool\",\n      \"html_url\": \"https://dribbble.com/codeschool\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/333539/avatars/normal/329ac818d30ca1a7b900c09b105ce277.jpg?1410890340\",\n      \"bio\": \"Code School teaches web technologies in the comfort of your browser with video lessons, coding challenges, and screencasts.\",\n      \"location\": \"Orlando, FL\",\n      \"links\": {\n        \"web\": \"http://codeschool.com\",\n        \"twitter\": \"https://twitter.com/codeschool\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 0,\n      \"followers_count\": 3057,\n      \"followings_count\": 13,\n      \"likes_count\": 1,\n      \"likes_received_count\": 0,\n      \"projects_count\": 0,\n      \"rebounds_received_count\": 0,\n      \"shots_count\": 154,\n      \"can_upload_shot\": true,\n      \"type\": \"Team\",\n      \"pro\": false,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/333539/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/333539/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/333539/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/333539/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/333539/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/333539/shots\",\n      \"created_at\": \"2013-05-15T21:37:44Z\",\n      \"updated_at\": \"2016-03-29T20:26:49Z\",\n      \"members_count\": 10,\n      \"members_url\": \"https://api.dribbble.com/v1/teams/333539/members\",\n      \"team_shots_url\": \"https://api.dribbble.com/v1/teams/333539/shots\"\n    }\n  },\n  {\n    \"id\": 2619181,\n    \"title\": \"Costa Rica\",\n    \"description\": \"<p>Shirt graphic for offsite meeting in Costa Rica. </p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/21030/screenshots/2619181/costa.png\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/21030/screenshots/2619181/costa_1x.png\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/21030/screenshots/2619181/costa_teaser.png\"\n    },\n    \"views_count\": 1261,\n    \"likes_count\": 136,\n    \"comments_count\": 7,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 7,\n    \"created_at\": \"2016-03-29T15:48:25Z\",\n    \"updated_at\": \"2016-03-29T15:49:13Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619181-Costa-Rica\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619181/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619181/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619181/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619181/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619181/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619181/rebounds\",\n    \"animated\": false,\n    \"tags\": [\n      \"bird\",\n      \"costa rica\",\n      \"design\",\n      \"illustration\",\n      \"leaf\",\n      \"toucan\",\n      \"tropical\"\n    ],\n    \"user\": {\n      \"id\": 21030,\n      \"name\": \"Trevor Basset\",\n      \"username\": \"trevorbasset\",\n      \"html_url\": \"https://dribbble.com/trevorbasset\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/21030/avatars/normal/e9907b8b54ea842b30c5787ef95acc3a.png?1426787498\",\n      \"bio\": \"Design, art direction, illustration, birds. \",\n      \"location\": \"Seattle, WA\",\n      \"links\": {\n        \"web\": \"http://www.trevorbasset.com\",\n        \"twitter\": \"https://twitter.com/trevorbasset\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 244,\n      \"followers_count\": 1169,\n      \"followings_count\": 367,\n      \"likes_count\": 1204,\n      \"likes_received_count\": 3660,\n      \"projects_count\": 0,\n      \"rebounds_received_count\": 4,\n      \"shots_count\": 85,\n      \"teams_count\": 0,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": false,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/21030/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/21030/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/21030/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/21030/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/21030/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/21030/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/21030/teams\",\n      \"created_at\": \"2011-03-03T20:05:14Z\",\n      \"updated_at\": \"2016-03-30T04:08:03Z\"\n    },\n    \"team\": null\n  },\n  {\n    \"id\": 2619381,\n    \"title\": \"Seaborn Oyster Co.\",\n    \"description\": null,\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher.jpg\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher_1x.jpg\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher_teaser.jpg\"\n    },\n    \"views_count\": 2166,\n    \"likes_count\": 235,\n    \"comments_count\": 2,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 11,\n    \"created_at\": \"2016-03-29T17:12:41Z\",\n    \"updated_at\": \"2016-03-29T17:12:53Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619381-Seaborn-Oyster-Co\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619381/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619381/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619381/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619381/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619381/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619381/rebounds\",\n    \"animated\": false,\n    \"tags\": [\n      \"charleston\",\n      \"company\",\n      \"ocean\",\n      \"oyster\",\n      \"sea\",\n      \"wave\"\n    ],\n    \"user\": {\n      \"id\": 52758,\n      \"name\": \"Jay Fletcher\",\n      \"username\": \"jfletcherdesign\",\n      \"html_url\": \"https://dribbble.com/jfletcherdesign\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/52758/avatars/normal/J_FLETCHER_DESIGN_LOGO-01.jpg?1401983283\",\n      \"bio\": \"\",\n      \"location\": \"Charleston, SC\",\n      \"links\": {\n        \"web\": \"http://www.jfletcherdesign.com\",\n        \"twitter\": \"https://twitter.com/jfletcherdesign\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 5239,\n      \"followers_count\": 13803,\n      \"followings_count\": 558,\n      \"likes_count\": 6531,\n      \"likes_received_count\": 104895,\n      \"projects_count\": 10,\n      \"rebounds_received_count\": 325,\n      \"shots_count\": 481,\n      \"teams_count\": 0,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/52758/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/52758/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/52758/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/52758/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/52758/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/52758/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/52758/teams\",\n      \"created_at\": \"2011-08-13T23:30:38Z\",\n      \"updated_at\": \"2016-03-29T17:12:53Z\"\n    },\n    \"team\": null\n  },\n  {\n    \"id\": 2619494,\n    \"title\": \"Mystery Project 72.1\",\n    \"description\": \"<p>We're excited to be onboard for a new year of Outside Lands festival branding! Stay tuned for weekly updates including Ranger Dave's new patch series, the 2016 lineup, and more!</p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/31348/screenshots/2619494/patches-30.jpg\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/31348/screenshots/2619494/patches-30_1x.jpg\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/31348/screenshots/2619494/patches-30_teaser.jpg\"\n    },\n    \"views_count\": 2304,\n    \"likes_count\": 252,\n    \"comments_count\": 4,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 11,\n    \"created_at\": \"2016-03-29T18:05:57Z\",\n    \"updated_at\": \"2016-03-29T18:07:21Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619494-Mystery-Project-72-1\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619494/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619494/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619494/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619494/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619494/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619494/rebounds\",\n    \"rebound_source_url\": \"https://api.dribbble.com/v1/shots/2454166\",\n    \"animated\": false,\n    \"tags\": [\n      \"badge\",\n      \"branding\",\n      \"bridge\",\n      \"city\",\n      \"dan kuhlken\",\n      \"dkng\",\n      \"logo\",\n      \"nathan goldman\",\n      \"patch\",\n      \"san francisco\",\n      \"vector\"\n    ],\n    \"user\": {\n      \"id\": 31348,\n      \"name\": \"DKNG\",\n      \"username\": \"DKNG\",\n      \"html_url\": \"https://dribbble.com/DKNG\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/31348/avatars/original/dkng_twitter.jpg?1305140827\",\n      \"bio\": \"Established in 2005, DKNG is a design studio based in Los Angeles, California with a focus on the music and entertainment industries.\",\n      \"location\": \"Los Angeles, CA\",\n      \"links\": {\n        \"web\": \"http://www.dkngstudios.com\",\n        \"twitter\": \"https://twitter.com/DKNGstudios\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 5274,\n      \"followers_count\": 24704,\n      \"followings_count\": 256,\n      \"likes_count\": 197,\n      \"likes_received_count\": 125646,\n      \"projects_count\": 47,\n      \"rebounds_received_count\": 324,\n      \"shots_count\": 479,\n      \"teams_count\": 0,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/31348/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/31348/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/31348/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/31348/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/31348/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/31348/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/31348/teams\",\n      \"created_at\": \"2011-04-28T20:48:48Z\",\n      \"updated_at\": \"2016-03-29T18:07:21Z\"\n    },\n    \"team\": null\n  },\n  {\n    \"id\": 2619183,\n    \"title\": \"Bonsai\",\n    \"description\": null,\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/44323/screenshots/2619183/bonsai.png\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/44323/screenshots/2619183/bonsai_1x.png\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/44323/screenshots/2619183/bonsai_teaser.png\"\n    },\n    \"views_count\": 2143,\n    \"likes_count\": 259,\n    \"comments_count\": 11,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 18,\n    \"created_at\": \"2016-03-29T15:48:38Z\",\n    \"updated_at\": \"2016-03-29T15:49:04Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619183-Bonsai\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619183/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619183/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619183/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619183/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619183/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619183/rebounds\",\n    \"animated\": false,\n    \"tags\": [\n      \"bonsai\",\n      \"illustration\",\n      \"nature\",\n      \"plant\",\n      \"pot\",\n      \"tree\",\n      \"zen\"\n    ],\n    \"user\": {\n      \"id\": 44323,\n      \"name\": \"Zach Roszczewski\",\n      \"username\": \"ZachRoszczewski\",\n      \"html_url\": \"https://dribbble.com/ZachRoszczewski\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/44323/avatars/normal/18f509c70a25627b40d5e3499b1cba2f.png?1419195740\",\n      \"bio\": \"Iconographer &amp; Illustrator. Creator of <a href=\\\"http://www.flaticons.co\\\" rel=\\\"nofollow noreferrer\\\">www.flaticons.co</a> &amp; <a href=\\\"http://www.mojiapp.net\\\" rel=\\\"nofollow noreferrer\\\">www.mojiapp.net</a>.\",\n      \"location\": \"Encinitas, California\",\n      \"links\": {\n        \"web\": \"http://zachroszczewski.com\",\n        \"twitter\": \"https://twitter.com/ZachRoszczewski\"\n      },\n      \"buckets_count\": 10,\n      \"comments_received_count\": 1682,\n      \"followers_count\": 9067,\n      \"followings_count\": 1541,\n      \"likes_count\": 14094,\n      \"likes_received_count\": 34409,\n      \"projects_count\": 7,\n      \"rebounds_received_count\": 14,\n      \"shots_count\": 113,\n      \"teams_count\": 2,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/44323/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/44323/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/44323/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/44323/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/44323/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/44323/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/44323/teams\",\n      \"created_at\": \"2011-07-07T14:49:07Z\",\n      \"updated_at\": \"2016-03-29T15:49:04Z\"\n    },\n    \"team\": null\n  },\n  {\n    \"id\": 2619255,\n    \"title\": \"Canvas—A new space for big ideas\",\n    \"description\": \"<p>A month ago the our team launched Canvas, a product for brands to tell their story and highlight products. It's been amazing to see your excitement for the creative possibilities and we can't wait to see how you use it. </p>\\n\\n<p>One of the best aspects of working on ads at Facebook is striving to find the sweet spot between the goals of our advertisers and those of people browsing their feed. Canvas allows businesses to create a more compelling experience for people, and in turn provides people with an ad they actually enjoy. Stay tuned for more :) </p>\\n\\n<p>If your interested in learning more about Canvas, or building one, you should check out <a href=\\\"https://canvas.facebook.com/\\\" target=\\\"_blank\\\" rel=\\\"noreferrer\\\">https://canvas.facebook.com/</a>\\n<br />To learn more about our process check out Jaime Rovira's medium post <a href=\\\"https://medium.com/facebook-design/canvas-how-we-crafted-facebook-s-new-immersive-ads-696870e66b3f#.jy9w9l51m\\\" target=\\\"_blank\\\" rel=\\\"noreferrer\\\">https://medium.com/facebook-design/canvas-how-we-crafted-facebook-s-new-immersive-ads-696870e66b3f#.jy9w9l51m</a></p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/476251/screenshots/2619255/startdribbble.gif\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/476251/screenshots/2619255/startdribbble_1x.gif\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/476251/screenshots/2619255/startdribbble_teaser.gif\"\n    },\n    \"views_count\": 3502,\n    \"likes_count\": 262,\n    \"comments_count\": 9,\n    \"attachments_count\": 2,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 12,\n    \"created_at\": \"2016-03-29T16:18:33Z\",\n    \"updated_at\": \"2016-03-29T16:19:50Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619255-Canvas-A-new-space-for-big-ideas\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619255/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619255/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619255/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619255/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619255/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619255/rebounds\",\n    \"animated\": true,\n    \"tags\": [\n      \"android\",\n      \"animation\",\n      \"creative\",\n      \"illustration\",\n      \"ios\",\n      \"mobile\",\n      \"tool\"\n    ],\n    \"user\": {\n      \"id\": 476251,\n      \"name\": \"ali griffin\",\n      \"username\": \"aligdanger\",\n      \"html_url\": \"https://dribbble.com/aligdanger\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/476251/avatars/normal/ali.png?1404762398\",\n      \"bio\": \"Designing product <a href=\\\"https://dribbble.com/Facebook\\\">@Facebook</a>\",\n      \"location\": \"San Francisco, CA\",\n      \"links\": {\n        \"twitter\": \"https://twitter.com/aligdanger\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 203,\n      \"followers_count\": 513,\n      \"followings_count\": 289,\n      \"likes_count\": 1302,\n      \"likes_received_count\": 2487,\n      \"projects_count\": 3,\n      \"rebounds_received_count\": 9,\n      \"shots_count\": 22,\n      \"teams_count\": 1,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/476251/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/476251/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/476251/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/476251/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/476251/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/476251/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/476251/teams\",\n      \"created_at\": \"2014-01-10T18:37:14Z\",\n      \"updated_at\": \"2016-03-30T04:07:49Z\"\n    },\n    \"team\": {\n      \"id\": 333588,\n      \"name\": \"Facebook\",\n      \"username\": \"Facebook\",\n      \"html_url\": \"https://dribbble.com/Facebook\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/333588/avatars/normal/9a9d5301e289975fa16abd070f1615c0.png?1440610176\",\n      \"bio\": \"\",\n      \"location\": \"1 Hacker Way, Menlo Park, CA\",\n      \"links\": {\n        \"web\": \"https://www.facebook.com/design\",\n        \"twitter\": \"https://twitter.com/facebookdesign\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 0,\n      \"followers_count\": 14039,\n      \"followings_count\": 0,\n      \"likes_count\": 2,\n      \"likes_received_count\": 0,\n      \"projects_count\": 0,\n      \"rebounds_received_count\": 0,\n      \"shots_count\": 121,\n      \"can_upload_shot\": true,\n      \"type\": \"Team\",\n      \"pro\": false,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/333588/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/333588/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/333588/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/333588/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/333588/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/333588/shots\",\n      \"created_at\": \"2013-05-15T23:13:37Z\",\n      \"updated_at\": \"2016-03-30T04:07:49Z\",\n      \"members_count\": 39,\n      \"members_url\": \"https://api.dribbble.com/v1/teams/333588/members\",\n      \"team_shots_url\": \"https://api.dribbble.com/v1/teams/333588/shots\"\n    }\n  },\n  {\n    \"id\": 2619346,\n    \"title\": \"Sunset\",\n    \"description\": \"<p>Baker Beach sunset from this weekend.</p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/3460/screenshots/2619346/sunset.png\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/3460/screenshots/2619346/sunset_1x.png\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/3460/screenshots/2619346/sunset_teaser.png\"\n    },\n    \"views_count\": 2897,\n    \"likes_count\": 231,\n    \"comments_count\": 3,\n    \"attachments_count\": 1,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 6,\n    \"created_at\": \"2016-03-29T16:55:27Z\",\n    \"updated_at\": \"2016-03-29T16:56:47Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619346-Sunset\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619346/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619346/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619346/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619346/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619346/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619346/rebounds\",\n    \"animated\": false,\n    \"tags\": [\n      \"beach\",\n      \"cartoon\",\n      \"comics\",\n      \"hand-darwn\",\n      \"illustration\",\n      \"nature\",\n      \"sketch\",\n      \"sunset\"\n    ],\n    \"user\": {\n      \"id\": 3460,\n      \"name\": \"Ryan Putnam\",\n      \"username\": \"RypeArts\",\n      \"html_url\": \"https://dribbble.com/RypeArts\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/3460/avatars/normal/4ed7a7a4737e971e3fa37f0705f5cc51.png?1457564367\",\n      \"bio\": \"designer, illustrator, potter, and father\",\n      \"location\": \"San Francisco, CA\",\n      \"links\": {\n        \"web\": \"http://ryanputn.am\",\n        \"twitter\": \"https://twitter.com/RypeArts\"\n      },\n      \"buckets_count\": 3,\n      \"comments_received_count\": 9722,\n      \"followers_count\": 46667,\n      \"followings_count\": 518,\n      \"likes_count\": 10207,\n      \"likes_received_count\": 211321,\n      \"projects_count\": 34,\n      \"rebounds_received_count\": 373,\n      \"shots_count\": 589,\n      \"teams_count\": 1,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/3460/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/3460/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/3460/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/3460/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/3460/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/3460/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/3460/teams\",\n      \"created_at\": \"2010-07-16T12:48:16Z\",\n      \"updated_at\": \"2016-03-29T16:56:47Z\"\n    },\n    \"team\": null\n  },\n  {\n    \"id\": 2619340,\n    \"title\": \"Skies Like These \",\n    \"description\": \"<p>In anticipation for their release of the paperback version of the book, Skies Like These, Macmillan commissioned us to redesign the cover artwork. </p>\\n\\n<p>The story is about a twelve-year-old girl name Jade who is sent to spend the summer with her aunt in Wyoming by her parents. She meets a rebellious boy who called himself Roy Parker, after the legendary Butch Cassidy. Jade tries to be a good friend Roy, but worries about the trouble he might get her into while he tries to plan stunts worthy of Butch Cassidy himself.\\n</p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/44585/screenshots/2619340/skies-like-these-dribbble.png\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/44585/screenshots/2619340/skies-like-these-dribbble_1x.png\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/44585/screenshots/2619340/skies-like-these-dribbble_teaser.png\"\n    },\n    \"views_count\": 1548,\n    \"likes_count\": 177,\n    \"comments_count\": 5,\n    \"attachments_count\": 1,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 7,\n    \"created_at\": \"2016-03-29T16:50:48Z\",\n    \"updated_at\": \"2016-03-29T16:53:16Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619340-Skies-Like-These\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619340/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619340/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619340/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619340/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619340/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619340/rebounds\",\n    \"animated\": false,\n    \"tags\": [\n      \"book\",\n      \"book cover\",\n      \"cover artwork\",\n      \"cover design\",\n      \"cowboy hat\",\n      \"illustration\",\n      \"mountain\",\n      \"planets\",\n      \"sky\",\n      \"stars\"\n    ],\n    \"user\": {\n      \"id\": 44585,\n      \"name\": \"Brad Woodard\",\n      \"username\": \"bradwwoodard\",\n      \"html_url\": \"https://dribbble.com/bradwwoodard\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/44585/avatars/normal/593686b9b9c0d2b6a496d8404f24ce1f.png?1444862250\",\n      \"bio\": \"Designer • Illustrator • Braver of the Woods\",\n      \"location\": \"Austin, TX\",\n      \"links\": {\n        \"web\": \"http://www.bravethewoods.com/\",\n        \"twitter\": \"https://twitter.com/brave_the_woods\"\n      },\n      \"buckets_count\": 1,\n      \"comments_received_count\": 2598,\n      \"followers_count\": 8556,\n      \"followings_count\": 412,\n      \"likes_count\": 2285,\n      \"likes_received_count\": 45938,\n      \"projects_count\": 21,\n      \"rebounds_received_count\": 16,\n      \"shots_count\": 324,\n      \"teams_count\": 0,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/44585/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/44585/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/44585/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/44585/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/44585/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/44585/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/44585/teams\",\n      \"created_at\": \"2011-07-08T15:47:58Z\",\n      \"updated_at\": \"2016-03-29T16:53:16Z\"\n    },\n    \"team\": null\n  },\n  {\n    \"id\": 2619544,\n    \"title\": \"Robinhood\",\n    \"description\": \"<p>Robinhood integrations illustration. </p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/4598/screenshots/2619544/integrations_header_01.png\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/4598/screenshots/2619544/integrations_header_01_1x.png\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/4598/screenshots/2619544/integrations_header_01_teaser.png\"\n    },\n    \"views_count\": 1530,\n    \"likes_count\": 177,\n    \"comments_count\": 6,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 7,\n    \"created_at\": \"2016-03-29T18:24:59Z\",\n    \"updated_at\": \"2016-03-29T18:26:47Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619544-Robinhood\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619544/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619544/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619544/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619544/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619544/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619544/rebounds\",\n    \"animated\": false,\n    \"tags\": [\n      \"chart\",\n      \"finance\",\n      \"illustration\",\n      \"money\",\n      \"stock\"\n    ],\n    \"user\": {\n      \"id\": 4598,\n      \"name\": \"Ty Wilkins\",\n      \"username\": \"tywilkins\",\n      \"html_url\": \"https://dribbble.com/tywilkins\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/4598/avatars/normal/fox2.jpg?1391573055\",\n      \"bio\": \"hello@tywilkins.com\",\n      \"location\": \"San Francisco, CA\",\n      \"links\": {\n        \"web\": \"http://www.tywilkins.com\",\n        \"twitter\": \"https://twitter.com/tywilkins\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 1080,\n      \"followers_count\": 8222,\n      \"followings_count\": 527,\n      \"likes_count\": 0,\n      \"likes_received_count\": 21359,\n      \"projects_count\": 8,\n      \"rebounds_received_count\": 0,\n      \"shots_count\": 97,\n      \"teams_count\": 1,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/4598/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/4598/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/4598/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/4598/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/4598/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/4598/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/4598/teams\",\n      \"created_at\": \"2010-09-30T20:31:02Z\",\n      \"updated_at\": \"2016-03-29T18:27:54Z\"\n    },\n    \"team\": null\n  },\n  {\n    \"id\": 2619187,\n    \"title\": \"Confidential iPad App part #2\",\n    \"description\": \"<p>Over the holidays, Rally built an iPad app for a confidential client and conference. This is video directly from interacting with the native iOS app.</p>\\n\\n<p>Myself, <a href=\\\"https://dribbble.com/4777\\\">@Geof Crowl</a>, and Wes tackled the project in just 15 days. It was intense but fun. Geof and I did the design and helped with layout in Xcode using Nibs. Wes built the globe and the data visualizations from a json file using our own Open GL globe library we've been building on an off for the past year. </p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/3816/screenshots/2619187/confidential-ipad-app-rally.gif\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/3816/screenshots/2619187/confidential-ipad-app-rally_1x.gif\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/3816/screenshots/2619187/confidential-ipad-app-rally_teaser.gif\"\n    },\n    \"views_count\": 3205,\n    \"likes_count\": 183,\n    \"comments_count\": 9,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 20,\n    \"created_at\": \"2016-03-29T15:50:05Z\",\n    \"updated_at\": \"2016-03-29T15:51:33Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619187-Confidential-iPad-App-part-2\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619187/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619187/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619187/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619187/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619187/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619187/rebounds\",\n    \"animated\": true,\n    \"tags\": [\n\n    ],\n    \"user\": {\n      \"id\": 3816,\n      \"name\": \"Ben Cline\",\n      \"username\": \"letsgorally\",\n      \"html_url\": \"https://dribbble.com/letsgorally\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/3816/avatars/normal/bb00fd14001a8cdd5e0e354df52a7fa4.png?1450769044\",\n      \"bio\": \"<a href=\\\"https://dribbble.com/RALLY\\\">@RALLY</a> Co-Founder / Designer\",\n      \"location\": \"Salt Lake City\",\n      \"links\": {\n        \"web\": \"http://beta.rallyinteractive.com\",\n        \"twitter\": \"https://twitter.com/yocline\"\n      },\n      \"buckets_count\": 3,\n      \"comments_received_count\": 4525,\n      \"followers_count\": 30105,\n      \"followings_count\": 241,\n      \"likes_count\": 6878,\n      \"likes_received_count\": 87892,\n      \"projects_count\": 10,\n      \"rebounds_received_count\": 28,\n      \"shots_count\": 257,\n      \"teams_count\": 1,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/3816/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/3816/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/3816/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/3816/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/3816/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/3816/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/3816/teams\",\n      \"created_at\": \"2010-07-30T17:30:31Z\",\n      \"updated_at\": \"2016-03-29T15:51:33Z\"\n    },\n    \"team\": {\n      \"id\": 559317,\n      \"name\": \"RALLY\",\n      \"username\": \"rally\",\n      \"html_url\": \"https://dribbble.com/rally\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/559317/avatars/normal/rally_logo.png?1398641637\",\n      \"bio\": \"Interactive Studio. Design &amp; Development\",\n      \"location\": \"Salt Lake City\",\n      \"links\": {\n        \"web\": \"http://beta.rallyinteractive.com\",\n        \"twitter\": \"https://twitter.com/letsgorally\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 0,\n      \"followers_count\": 8281,\n      \"followings_count\": 6,\n      \"likes_count\": 73,\n      \"likes_received_count\": 0,\n      \"projects_count\": 14,\n      \"rebounds_received_count\": 0,\n      \"shots_count\": 273,\n      \"can_upload_shot\": true,\n      \"type\": \"Team\",\n      \"pro\": false,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/559317/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/559317/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/559317/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/559317/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/559317/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/559317/shots\",\n      \"created_at\": \"2014-04-27T23:31:42Z\",\n      \"updated_at\": \"2016-03-29T15:51:33Z\",\n      \"members_count\": 5,\n      \"members_url\": \"https://api.dribbble.com/v1/teams/559317/members\",\n      \"team_shots_url\": \"https://api.dribbble.com/v1/teams/559317/shots\"\n    }\n  },\n  {\n    \"id\": 2619200,\n    \"title\": \"Eilean Donan Castle\",\n    \"description\": \"<p>Day 209/365</p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/283823/screenshots/2619200/eilean_donan_castle-01.jpg\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/283823/screenshots/2619200/eilean_donan_castle-01_1x.jpg\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/283823/screenshots/2619200/eilean_donan_castle-01_teaser.jpg\"\n    },\n    \"views_count\": 1434,\n    \"likes_count\": 162,\n    \"comments_count\": 4,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 7,\n    \"created_at\": \"2016-03-29T15:54:42Z\",\n    \"updated_at\": \"2016-03-29T15:55:23Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619200-Eilean-Donan-Castle\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619200/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619200/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619200/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619200/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619200/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619200/rebounds\",\n    \"rebound_source_url\": \"https://api.dribbble.com/v1/shots/2614735\",\n    \"animated\": false,\n    \"tags\": [\n      \"icon\",\n      \"illustration\",\n      \"lake\",\n      \"scotland\",\n      \"vector\"\n    ],\n    \"user\": {\n      \"id\": 283823,\n      \"name\": \"Scott Tusk\",\n      \"username\": \"Tusk\",\n      \"html_url\": \"https://dribbble.com/Tusk\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/283823/avatars/normal/c71f583fd2f781e48da28697c6ec2211.jpg?1456193406\",\n      \"bio\": \"\",\n      \"location\": \"Chicago\",\n      \"links\": {\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 1118,\n      \"followers_count\": 5013,\n      \"followings_count\": 812,\n      \"likes_count\": 2295,\n      \"likes_received_count\": 45133,\n      \"projects_count\": 1,\n      \"rebounds_received_count\": 214,\n      \"shots_count\": 282,\n      \"teams_count\": 1,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/283823/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/283823/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/283823/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/283823/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/283823/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/283823/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/283823/teams\",\n      \"created_at\": \"2013-02-17T16:32:29Z\",\n      \"updated_at\": \"2016-03-29T15:55:23Z\"\n    },\n    \"team\": null\n  },\n  {\n    \"id\": 2619378,\n    \"title\": \"Infinite Coffee\",\n    \"description\": \"<p>It's Monday, I need coffee. Forever.</p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/60266/screenshots/2619378/coffee.jpg\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/60266/screenshots/2619378/coffee_1x.jpg\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/60266/screenshots/2619378/coffee_teaser.jpg\"\n    },\n    \"views_count\": 1301,\n    \"likes_count\": 146,\n    \"comments_count\": 6,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 2,\n    \"created_at\": \"2016-03-29T17:11:50Z\",\n    \"updated_at\": \"2016-03-29T17:18:17Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619378-Infinite-Coffee\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619378/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619378/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619378/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619378/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619378/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619378/rebounds\",\n    \"animated\": false,\n    \"tags\": [\n      \"8\",\n      \"coffee\",\n      \"cup\",\n      \"food\",\n      \"geometric\",\n      \"illustration\",\n      \"infinite\",\n      \"kite\",\n      \"liquid\",\n      \"mug\",\n      \"stroke\"\n    ],\n    \"user\": {\n      \"id\": 60266,\n      \"name\": \"Gustavo Zambelli\",\n      \"username\": \"zamax\",\n      \"html_url\": \"https://dribbble.com/zamax\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/60266/avatars/normal/83d4ac61d50bf5b2fedc9f9cc45a62d9.png?1453312126\",\n      \"bio\": \"Hi, I&#39;m Lead of illustration at <a href=\\\"https://dribbble.com/aerolab\\\">@aerolab</a> &amp; Superman at <a href=\\\"https://dribbble.com/RicosQuesos\\\">@RicosQuesos</a>\",\n      \"location\": \"Neuquén, Argentina.\",\n      \"links\": {\n        \"web\": \"http://zamax.tumblr.com\",\n        \"twitter\": \"https://twitter.com/zamax4\"\n      },\n      \"buckets_count\": 19,\n      \"comments_received_count\": 1645,\n      \"followers_count\": 4198,\n      \"followings_count\": 1253,\n      \"likes_count\": 8828,\n      \"likes_received_count\": 36018,\n      \"projects_count\": 4,\n      \"rebounds_received_count\": 133,\n      \"shots_count\": 305,\n      \"teams_count\": 4,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/60266/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/60266/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/60266/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/60266/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/60266/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/60266/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/60266/teams\",\n      \"created_at\": \"2011-09-07T19:27:31Z\",\n      \"updated_at\": \"2016-03-29T17:18:17Z\"\n    },\n    \"team\": {\n      \"id\": 171431,\n      \"name\": \"Aerolab\",\n      \"username\": \"aerolab\",\n      \"html_url\": \"https://dribbble.com/aerolab\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/171431/avatars/normal/1283d5fbcd21a809d0cdc2f96a560096.png?1458077891\",\n      \"bio\": \"We design and develop beautiful digital products for startups and leading brands.\",\n      \"location\": \"Buenos Aires - San Francisco\",\n      \"links\": {\n        \"web\": \"http://aerolab.co\",\n        \"twitter\": \"https://twitter.com/aerolab\"\n      },\n      \"buckets_count\": 5,\n      \"comments_received_count\": 157,\n      \"followers_count\": 3845,\n      \"followings_count\": 128,\n      \"likes_count\": 4228,\n      \"likes_received_count\": 2121,\n      \"projects_count\": 24,\n      \"rebounds_received_count\": 2,\n      \"shots_count\": 579,\n      \"can_upload_shot\": true,\n      \"type\": \"Team\",\n      \"pro\": false,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/171431/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/171431/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/171431/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/171431/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/171431/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/171431/shots\",\n      \"created_at\": \"2012-07-04T02:31:07Z\",\n      \"updated_at\": \"2016-03-29T17:18:17Z\",\n      \"members_count\": 21,\n      \"members_url\": \"https://api.dribbble.com/v1/teams/171431/members\",\n      \"team_shots_url\": \"https://api.dribbble.com/v1/teams/171431/shots\"\n    }\n  },\n  {\n    \"id\": 2619645,\n    \"title\": \"Hello, Is It Me You're Looking For?\",\n    \"description\": \"<p>I had the privilege of getting to collaborate with <a href=\\\"https://dribbble.com/72483\\\">@Jordan Wade</a> on a hero illustration for his SVG post. And let me tell you, watching your work come alive with CSS and JS is pretty much the jam.</p>\\n\\n<p><a href=\\\"https://dribbble.com/shots/2619653-Hello-from-the-other-side\\\" rel=\\\"nofollow noreferrer\\\">Check it out all alive n' stuff!</a></p>\\n\\n<p><a href=\\\"https://www.codeschool.com/blog/2016/03/29/benefits-of-learning-how-to-use-svg/\\\" rel=\\\"nofollow noreferrer\\\">Go read about why you should learn more about SVG for the web</a>.</p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/13774/screenshots/2619645/hello.png\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/13774/screenshots/2619645/hello_1x.png\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/13774/screenshots/2619645/hello_teaser.png\"\n    },\n    \"views_count\": 1771,\n    \"likes_count\": 146,\n    \"comments_count\": 2,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 1,\n    \"buckets_count\": 2,\n    \"created_at\": \"2016-03-29T19:12:57Z\",\n    \"updated_at\": \"2016-03-29T20:26:49Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619645-Hello-Is-It-Me-You-re-Looking-For\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619645/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619645/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619645/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619645/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619645/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619645/rebounds\",\n    \"animated\": false,\n    \"tags\": [\n      \"hello\"\n    ],\n    \"user\": {\n      \"id\": 13774,\n      \"name\": \"Justin Mezzell\",\n      \"username\": \"JustinMezzell\",\n      \"html_url\": \"https://dribbble.com/JustinMezzell\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/13774/avatars/normal/Me_Web.jpg?1380768479\",\n      \"bio\": \"Designer? Illustrator? Why not. Directing Art at <a href=\\\"https://dribbble.com/codeschool\\\">@codeschool</a>.\",\n      \"location\": \"Orlando, FL\",\n      \"links\": {\n        \"web\": \"http://justinmezzell.com/\",\n        \"twitter\": \"https://twitter.com/JustinMezzell\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 5736,\n      \"followers_count\": 31449,\n      \"followings_count\": 713,\n      \"likes_count\": 5548,\n      \"likes_received_count\": 113425,\n      \"projects_count\": 0,\n      \"rebounds_received_count\": 55,\n      \"shots_count\": 312,\n      \"teams_count\": 4,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": true,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/13774/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/13774/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/13774/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/13774/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/13774/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/13774/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/13774/teams\",\n      \"created_at\": \"2011-01-26T06:58:50Z\",\n      \"updated_at\": \"2016-03-29T20:26:49Z\"\n    },\n    \"team\": {\n      \"id\": 333539,\n      \"name\": \"Code School\",\n      \"username\": \"codeschool\",\n      \"html_url\": \"https://dribbble.com/codeschool\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/333539/avatars/normal/329ac818d30ca1a7b900c09b105ce277.jpg?1410890340\",\n      \"bio\": \"Code School teaches web technologies in the comfort of your browser with video lessons, coding challenges, and screencasts.\",\n      \"location\": \"Orlando, FL\",\n      \"links\": {\n        \"web\": \"http://codeschool.com\",\n        \"twitter\": \"https://twitter.com/codeschool\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 0,\n      \"followers_count\": 3057,\n      \"followings_count\": 13,\n      \"likes_count\": 1,\n      \"likes_received_count\": 0,\n      \"projects_count\": 0,\n      \"rebounds_received_count\": 0,\n      \"shots_count\": 154,\n      \"can_upload_shot\": true,\n      \"type\": \"Team\",\n      \"pro\": false,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/333539/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/333539/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/333539/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/333539/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/333539/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/333539/shots\",\n      \"created_at\": \"2013-05-15T21:37:44Z\",\n      \"updated_at\": \"2016-03-29T20:26:49Z\",\n      \"members_count\": 10,\n      \"members_url\": \"https://api.dribbble.com/v1/teams/333539/members\",\n      \"team_shots_url\": \"https://api.dribbble.com/v1/teams/333539/shots\"\n    }\n  },\n  {\n    \"id\": 2619181,\n    \"title\": \"Costa Rica\",\n    \"description\": \"<p>Shirt graphic for offsite meeting in Costa Rica. </p>\",\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n      \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/21030/screenshots/2619181/costa.png\",\n      \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/21030/screenshots/2619181/costa_1x.png\",\n      \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/21030/screenshots/2619181/costa_teaser.png\"\n    },\n    \"views_count\": 1261,\n    \"likes_count\": 136,\n    \"comments_count\": 7,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 7,\n    \"created_at\": \"2016-03-29T15:48:25Z\",\n    \"updated_at\": \"2016-03-29T15:49:13Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619181-Costa-Rica\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619181/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619181/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619181/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619181/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619181/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619181/rebounds\",\n    \"animated\": false,\n    \"tags\": [\n      \"bird\",\n      \"costa rica\",\n      \"design\",\n      \"illustration\",\n      \"leaf\",\n      \"toucan\",\n      \"tropical\"\n    ],\n    \"user\": {\n      \"id\": 21030,\n      \"name\": \"Trevor Basset\",\n      \"username\": \"trevorbasset\",\n      \"html_url\": \"https://dribbble.com/trevorbasset\",\n      \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/21030/avatars/normal/e9907b8b54ea842b30c5787ef95acc3a.png?1426787498\",\n      \"bio\": \"Design, art direction, illustration, birds. \",\n      \"location\": \"Seattle, WA\",\n      \"links\": {\n        \"web\": \"http://www.trevorbasset.com\",\n        \"twitter\": \"https://twitter.com/trevorbasset\"\n      },\n      \"buckets_count\": 0,\n      \"comments_received_count\": 244,\n      \"followers_count\": 1169,\n      \"followings_count\": 367,\n      \"likes_count\": 1204,\n      \"likes_received_count\": 3660,\n      \"projects_count\": 0,\n      \"rebounds_received_count\": 4,\n      \"shots_count\": 85,\n      \"teams_count\": 0,\n      \"can_upload_shot\": true,\n      \"type\": \"Player\",\n      \"pro\": false,\n      \"buckets_url\": \"https://api.dribbble.com/v1/users/21030/buckets\",\n      \"followers_url\": \"https://api.dribbble.com/v1/users/21030/followers\",\n      \"following_url\": \"https://api.dribbble.com/v1/users/21030/following\",\n      \"likes_url\": \"https://api.dribbble.com/v1/users/21030/likes\",\n      \"projects_url\": \"https://api.dribbble.com/v1/users/21030/projects\",\n      \"shots_url\": \"https://api.dribbble.com/v1/users/21030/shots\",\n      \"teams_url\": \"https://api.dribbble.com/v1/users/21030/teams\",\n      \"created_at\": \"2011-03-03T20:05:14Z\",\n      \"updated_at\": \"2016-03-30T04:08:03Z\"\n    },\n    \"team\": null\n  }\n];"
  },
  {
    "path": "Demo/DribbbleDemo/dribbbleDemo/main.m",
    "content": "    //\n//  main.m\n//  dribbbleDemo\n//\n//  Created by bang on 15/9/1.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n#import \"AppDelegate.h\"\n\nint main(int argc, char * argv[]) {\n    @autoreleasepool {\n        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));\n    }\n}\n"
  },
  {
    "path": "Demo/DribbbleDemo/dribbbleDemo.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t36091A1B1CAAA2830012490F /* JPEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 36091A191CAAA2830012490F /* JPEngine.m */; };\n\t\t36091A1C1CAAA2830012490F /* JSPatch.js in Resources */ = {isa = PBXBuildFile; fileRef = 36091A1A1CAAA2830012490F /* JSPatch.js */; };\n\t\t36091A771CAB91990012490F /* JPCleaner.m in Sources */ = {isa = PBXBuildFile; fileRef = 36091A5B1CAB91980012490F /* JPCleaner.m */; };\n\t\t36091A791CAB91990012490F /* JPLocker.m in Sources */ = {isa = PBXBuildFile; fileRef = 36091A5F1CAB91980012490F /* JPLocker.m */; };\n\t\t36091A7B1CAB91990012490F /* JPSpecialInit.m in Sources */ = {isa = PBXBuildFile; fileRef = 36091A631CAB91980012490F /* JPSpecialInit.m */; };\n\t\t36CE19221CB17D6A007D73AC /* dribbble in Resources */ = {isa = PBXBuildFile; fileRef = 36CE19211CB17D6A007D73AC /* dribbble */; };\n\t\tDEBA57DF1B95D5A200B4DC66 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DEBA57DE1B95D5A200B4DC66 /* main.m */; };\n\t\tDEBA57E21B95D5A300B4DC66 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DEBA57E11B95D5A300B4DC66 /* AppDelegate.m */; };\n\t\tDEBA57EA1B95D5A300B4DC66 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DEBA57E91B95D5A300B4DC66 /* Images.xcassets */; };\n\t\tDEBA57F91B95D5A300B4DC66 /* dribbbleDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DEBA57F81B95D5A300B4DC66 /* dribbbleDemoTests.m */; };\n\t\tDEBA58531B95DA6E00B4DC66 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DEBA58521B95DA6E00B4DC66 /* UIKit.framework */; };\n\t\tDEBA58551B95DA7C00B4DC66 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DEBA58541B95DA7C00B4DC66 /* Security.framework */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\tDEBA57F31B95D5A300B4DC66 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = DEBA57D11B95D5A200B4DC66 /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = DEBA57D81B95D5A200B4DC66;\n\t\t\tremoteInfo = dribbbleDemo;\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXFileReference section */\n\t\t0A8B1CDBA40FFAD086BA1A15 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = \"Pods/Target Support Files/Pods/Pods.release.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t15903DAE6B51ADB1AEC38472 /* libPods-dribbbleDemo.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = \"libPods-dribbbleDemo.a\"; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t36091A181CAAA2830012490F /* JPEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPEngine.h; sourceTree = \"<group>\"; };\n\t\t36091A191CAAA2830012490F /* JPEngine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPEngine.m; sourceTree = \"<group>\"; };\n\t\t36091A1A1CAAA2830012490F /* JSPatch.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = JSPatch.js; sourceTree = \"<group>\"; };\n\t\t36091A5A1CAB91980012490F /* JPCleaner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCleaner.h; sourceTree = \"<group>\"; };\n\t\t36091A5B1CAB91980012490F /* JPCleaner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCleaner.m; sourceTree = \"<group>\"; };\n\t\t36091A5E1CAB91980012490F /* JPLocker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPLocker.h; sourceTree = \"<group>\"; };\n\t\t36091A5F1CAB91980012490F /* JPLocker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPLocker.m; sourceTree = \"<group>\"; };\n\t\t36091A621CAB91980012490F /* JPSpecialInit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPSpecialInit.h; sourceTree = \"<group>\"; };\n\t\t36091A631CAB91980012490F /* JPSpecialInit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPSpecialInit.m; sourceTree = \"<group>\"; };\n\t\t36CE19211CB17D6A007D73AC /* dribbble */ = {isa = PBXFileReference; lastKnownFileType = folder; path = dribbble; sourceTree = \"<group>\"; };\n\t\t4E9FF79023501B4C7B8780E6 /* Pods-dribbbleDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-dribbbleDemo.debug.xcconfig\"; path = \"Pods/Target Support Files/Pods-dribbbleDemo/Pods-dribbbleDemo.debug.xcconfig\"; sourceTree = \"<group>\"; };\n\t\t5B21F30B82AD2BCFBD981366 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = \"Pods/Target Support Files/Pods/Pods.debug.xcconfig\"; sourceTree = \"<group>\"; };\n\t\tA354BF41D400455B098BBF0B /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tC74009A42925FAD86E7D36C0 /* Pods-dribbbleDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = \"Pods-dribbbleDemo.release.xcconfig\"; path = \"Pods/Target Support Files/Pods-dribbbleDemo/Pods-dribbbleDemo.release.xcconfig\"; sourceTree = \"<group>\"; };\n\t\tDEBA57D91B95D5A200B4DC66 /* dribbbleDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = dribbbleDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tDEBA57DD1B95D5A200B4DC66 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\tDEBA57DE1B95D5A200B4DC66 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = \"<group>\"; };\n\t\tDEBA57E01B95D5A300B4DC66 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = \"<group>\"; };\n\t\tDEBA57E11B95D5A300B4DC66 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = \"<group>\"; };\n\t\tDEBA57E91B95D5A300B4DC66 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = \"<group>\"; };\n\t\tDEBA57F21B95D5A300B4DC66 /* dribbbleDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = dribbbleDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tDEBA57F71B95D5A300B4DC66 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\tDEBA57F81B95D5A300B4DC66 /* dribbbleDemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = dribbbleDemoTests.m; sourceTree = \"<group>\"; };\n\t\tDEBA58521B95DA6E00B4DC66 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };\n\t\tDEBA58541B95DA7C00B4DC66 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\tDEBA57D61B95D5A200B4DC66 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tDEBA58551B95DA7C00B4DC66 /* Security.framework in Frameworks */,\n\t\t\t\tDEBA58531B95DA6E00B4DC66 /* UIKit.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tDEBA57EF1B95D5A300B4DC66 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t31AAE1067DD5D5B8CB52EAD4 /* Pods */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t5B21F30B82AD2BCFBD981366 /* Pods.debug.xcconfig */,\n\t\t\t\t0A8B1CDBA40FFAD086BA1A15 /* Pods.release.xcconfig */,\n\t\t\t\t4E9FF79023501B4C7B8780E6 /* Pods-dribbbleDemo.debug.xcconfig */,\n\t\t\t\tC74009A42925FAD86E7D36C0 /* Pods-dribbbleDemo.release.xcconfig */,\n\t\t\t);\n\t\t\tname = Pods;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t36091A171CAAA2830012490F /* JSPatch */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t36091A481CAB91980012490F /* Extensions */,\n\t\t\t\t36091A181CAAA2830012490F /* JPEngine.h */,\n\t\t\t\t36091A191CAAA2830012490F /* JPEngine.m */,\n\t\t\t\t36091A1A1CAAA2830012490F /* JSPatch.js */,\n\t\t\t);\n\t\t\tname = JSPatch;\n\t\t\tpath = ../../../JSPatch;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t36091A481CAB91980012490F /* Extensions */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t36091A5A1CAB91980012490F /* JPCleaner.h */,\n\t\t\t\t36091A5B1CAB91980012490F /* JPCleaner.m */,\n\t\t\t\t36091A5E1CAB91980012490F /* JPLocker.h */,\n\t\t\t\t36091A5F1CAB91980012490F /* JPLocker.m */,\n\t\t\t\t36091A621CAB91980012490F /* JPSpecialInit.h */,\n\t\t\t\t36091A631CAB91980012490F /* JPSpecialInit.m */,\n\t\t\t);\n\t\t\tname = Extensions;\n\t\t\tpath = ../Extensions;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDEBA57D01B95D5A200B4DC66 = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tDEBA58541B95DA7C00B4DC66 /* Security.framework */,\n\t\t\t\tDEBA58521B95DA6E00B4DC66 /* UIKit.framework */,\n\t\t\t\tDEBA57DB1B95D5A200B4DC66 /* dribbbleDemo */,\n\t\t\t\tDEBA57F51B95D5A300B4DC66 /* dribbbleDemoTests */,\n\t\t\t\tDEBA57DA1B95D5A200B4DC66 /* Products */,\n\t\t\t\t31AAE1067DD5D5B8CB52EAD4 /* Pods */,\n\t\t\t\tFF293541306D58FD4BDAA5CD /* Frameworks */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDEBA57DA1B95D5A200B4DC66 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tDEBA57D91B95D5A200B4DC66 /* dribbbleDemo.app */,\n\t\t\t\tDEBA57F21B95D5A300B4DC66 /* dribbbleDemoTests.xctest */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDEBA57DB1B95D5A200B4DC66 /* dribbbleDemo */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t36091A171CAAA2830012490F /* JSPatch */,\n\t\t\t\tDEBA57E01B95D5A300B4DC66 /* AppDelegate.h */,\n\t\t\t\tDEBA57E11B95D5A300B4DC66 /* AppDelegate.m */,\n\t\t\t\t36CE19211CB17D6A007D73AC /* dribbble */,\n\t\t\t\tDEBA57E91B95D5A300B4DC66 /* Images.xcassets */,\n\t\t\t\tDEBA57DC1B95D5A200B4DC66 /* Supporting Files */,\n\t\t\t);\n\t\t\tpath = dribbbleDemo;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDEBA57DC1B95D5A200B4DC66 /* Supporting Files */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tDEBA57DD1B95D5A200B4DC66 /* Info.plist */,\n\t\t\t\tDEBA57DE1B95D5A200B4DC66 /* main.m */,\n\t\t\t);\n\t\t\tname = \"Supporting Files\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDEBA57F51B95D5A300B4DC66 /* dribbbleDemoTests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tDEBA57F81B95D5A300B4DC66 /* dribbbleDemoTests.m */,\n\t\t\t\tDEBA57F61B95D5A300B4DC66 /* Supporting Files */,\n\t\t\t);\n\t\t\tpath = dribbbleDemoTests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDEBA57F61B95D5A300B4DC66 /* Supporting Files */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tDEBA57F71B95D5A300B4DC66 /* Info.plist */,\n\t\t\t);\n\t\t\tname = \"Supporting Files\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tFF293541306D58FD4BDAA5CD /* Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tA354BF41D400455B098BBF0B /* libPods.a */,\n\t\t\t\t15903DAE6B51ADB1AEC38472 /* libPods-dribbbleDemo.a */,\n\t\t\t);\n\t\t\tname = Frameworks;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\tDEBA57D81B95D5A200B4DC66 /* dribbbleDemo */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = DEBA57FC1B95D5A300B4DC66 /* Build configuration list for PBXNativeTarget \"dribbbleDemo\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t379F843EA00F8D428B9036AE /* 📦 Check Pods Manifest.lock */,\n\t\t\t\tDEBA57D51B95D5A200B4DC66 /* Sources */,\n\t\t\t\tDEBA57D61B95D5A200B4DC66 /* Frameworks */,\n\t\t\t\tDEBA57D71B95D5A200B4DC66 /* Resources */,\n\t\t\t\t5051F1B8E1BE3F57F4085EA8 /* 📦 Copy Pods Resources */,\n\t\t\t\t3E10562C003A078AFFFB76ED /* 📦 Embed Pods Frameworks */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = dribbbleDemo;\n\t\t\tproductName = dribbbleDemo;\n\t\t\tproductReference = DEBA57D91B95D5A200B4DC66 /* dribbbleDemo.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n\t\tDEBA57F11B95D5A300B4DC66 /* dribbbleDemoTests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = DEBA57FF1B95D5A300B4DC66 /* Build configuration list for PBXNativeTarget \"dribbbleDemoTests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tDEBA57EE1B95D5A300B4DC66 /* Sources */,\n\t\t\t\tDEBA57EF1B95D5A300B4DC66 /* Frameworks */,\n\t\t\t\tDEBA57F01B95D5A300B4DC66 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\tDEBA57F41B95D5A300B4DC66 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = dribbbleDemoTests;\n\t\t\tproductName = dribbbleDemoTests;\n\t\t\tproductReference = DEBA57F21B95D5A300B4DC66 /* dribbbleDemoTests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.unit-test\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\tDEBA57D11B95D5A200B4DC66 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 0640;\n\t\t\t\tORGANIZATIONNAME = bang;\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\tDEBA57D81B95D5A200B4DC66 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 6.4;\n\t\t\t\t\t};\n\t\t\t\t\tDEBA57F11B95D5A300B4DC66 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 6.4;\n\t\t\t\t\t\tTestTargetID = DEBA57D81B95D5A200B4DC66;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = DEBA57D41B95D5A200B4DC66 /* Build configuration list for PBXProject \"dribbbleDemo\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = DEBA57D01B95D5A200B4DC66;\n\t\t\tproductRefGroup = DEBA57DA1B95D5A200B4DC66 /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\tDEBA57D81B95D5A200B4DC66 /* dribbbleDemo */,\n\t\t\t\tDEBA57F11B95D5A300B4DC66 /* dribbbleDemoTests */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\tDEBA57D71B95D5A200B4DC66 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t36091A1C1CAAA2830012490F /* JSPatch.js in Resources */,\n\t\t\t\tDEBA57EA1B95D5A300B4DC66 /* Images.xcassets in Resources */,\n\t\t\t\t36CE19221CB17D6A007D73AC /* dribbble in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tDEBA57F01B95D5A300B4DC66 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXShellScriptBuildPhase section */\n\t\t379F843EA00F8D428B9036AE /* 📦 Check Pods Manifest.lock */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"📦 Check Pods Manifest.lock\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"diff \\\"${PODS_ROOT}/../Podfile.lock\\\" \\\"${PODS_ROOT}/Manifest.lock\\\" > /dev/null\\nif [[ $? != 0 ]] ; then\\n    cat << EOM\\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\\nEOM\\n    exit 1\\nfi\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\t3E10562C003A078AFFFB76ED /* 📦 Embed Pods Frameworks */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"📦 Embed Pods Frameworks\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"\\\"${SRCROOT}/Pods/Target Support Files/Pods-dribbbleDemo/Pods-dribbbleDemo-frameworks.sh\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n\t\t5051F1B8E1BE3F57F4085EA8 /* 📦 Copy Pods Resources */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"📦 Copy Pods Resources\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"\\\"${SRCROOT}/Pods/Target Support Files/Pods-dribbbleDemo/Pods-dribbbleDemo-resources.sh\\\"\\n\";\n\t\t\tshowEnvVarsInLog = 0;\n\t\t};\n/* End PBXShellScriptBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\tDEBA57D51B95D5A200B4DC66 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t36091A791CAB91990012490F /* JPLocker.m in Sources */,\n\t\t\t\t36091A771CAB91990012490F /* JPCleaner.m in Sources */,\n\t\t\t\t36091A1B1CAAA2830012490F /* JPEngine.m in Sources */,\n\t\t\t\t36091A7B1CAB91990012490F /* JPSpecialInit.m in Sources */,\n\t\t\t\tDEBA57E21B95D5A300B4DC66 /* AppDelegate.m in Sources */,\n\t\t\t\tDEBA57DF1B95D5A200B4DC66 /* main.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tDEBA57EE1B95D5A300B4DC66 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tDEBA57F91B95D5A300B4DC66 /* dribbbleDemoTests.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\tDEBA57F41B95D5A300B4DC66 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = DEBA57D81B95D5A200B4DC66 /* dribbbleDemo */;\n\t\t\ttargetProxy = DEBA57F31B95D5A300B4DC66 /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin XCBuildConfiguration section */\n\t\tDEBA57FA1B95D5A300B4DC66 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.4;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tDEBA57FB1B95D5A300B4DC66 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.4;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tDEBA57FD1B95D5A300B4DC66 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 4E9FF79023501B4C7B8780E6 /* Pods-dribbbleDemo.debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;\n\t\t\t\tINFOPLIST_FILE = dribbbleDemo/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 7.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tDEBA57FE1B95D5A300B4DC66 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = C74009A42925FAD86E7D36C0 /* Pods-dribbbleDemo.release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;\n\t\t\t\tINFOPLIST_FILE = dribbbleDemo/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 7.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tDEBA58001B95D5A300B4DC66 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(SDKROOT)/Developer/Library/Frameworks\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = dribbbleDemoTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/dribbbleDemo.app/dribbbleDemo\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tDEBA58011B95D5A300B4DC66 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(SDKROOT)/Developer/Library/Frameworks\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = dribbbleDemoTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/dribbbleDemo.app/dribbbleDemo\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\tDEBA57D41B95D5A200B4DC66 /* Build configuration list for PBXProject \"dribbbleDemo\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tDEBA57FA1B95D5A300B4DC66 /* Debug */,\n\t\t\t\tDEBA57FB1B95D5A300B4DC66 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tDEBA57FC1B95D5A300B4DC66 /* Build configuration list for PBXNativeTarget \"dribbbleDemo\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tDEBA57FD1B95D5A300B4DC66 /* Debug */,\n\t\t\t\tDEBA57FE1B95D5A300B4DC66 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tDEBA57FF1B95D5A300B4DC66 /* Build configuration list for PBXNativeTarget \"dribbbleDemoTests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tDEBA58001B95D5A300B4DC66 /* Debug */,\n\t\t\t\tDEBA58011B95D5A300B4DC66 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = DEBA57D11B95D5A200B4DC66 /* Project object */;\n}\n"
  },
  {
    "path": "Demo/DribbbleDemo/dribbbleDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:dribbbleDemo.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "Demo/DribbbleDemo/dribbbleDemoTests/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>com.jspatch..$(PRODUCT_NAME:rfc1034identifier)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Demo/DribbbleDemo/dribbbleDemoTests/dribbbleDemoTests.m",
    "content": "//\n//  dribbbleDemoTests.m\n//  dribbbleDemoTests\n//\n//  Created by bang on 15/9/1.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n#import <XCTest/XCTest.h>\n\n@interface dribbbleDemoTests : XCTestCase\n\n@end\n\n@implementation dribbbleDemoTests\n\n- (void)setUp {\n    [super setUp];\n    // Put setup code here. This method is called before the invocation of each test method in the class.\n}\n\n- (void)tearDown {\n    // Put teardown code here. This method is called after the invocation of each test method in the class.\n    [super tearDown];\n}\n\n- (void)testExample {\n    // This is an example of a functional test case.\n    XCTAssert(YES, @\"Pass\");\n}\n\n- (void)testPerformanceExample {\n    // This is an example of a performance test case.\n    [self measureBlock:^{\n        // Put the code you want to measure the time of here.\n    }];\n}\n\n@end\n"
  },
  {
    "path": "Demo/OSXDemo/JSPatchOSXDemo/AppDelegate.h",
    "content": "//\n//  AppDelegate.h\n//  JSPatchOSXDemo\n//\n//  Created by Felix Deimel on 26.05.15.\n//  Copyright (c) 2015 Lemon Mojo. All rights reserved.\n//\n\n#import <Cocoa/Cocoa.h>\n\n@interface AppDelegate : NSObject <NSApplicationDelegate, NSTableViewDataSource, NSTableViewDelegate>\n\n@property (nonatomic, readwrite) int clickCount;\n@property (weak) IBOutlet NSTableView *tableView;\n\n@end"
  },
  {
    "path": "Demo/OSXDemo/JSPatchOSXDemo/AppDelegate.m",
    "content": "//\n//  AppDelegate.m\n//  JSPatchOSXDemo\n//\n//  Created by Felix Deimel on 26.05.15.\n//  Copyright (c) 2015 Lemon Mojo. All rights reserved.\n//\n\n#import \"AppDelegate.h\"\n#import \"JPEngine.h\"\n\n@interface AppDelegate ()\n\n@property (weak) IBOutlet NSWindow *window;\n@end\n\n@implementation AppDelegate\n\n- (void)applicationDidFinishLaunching:(NSNotification *)aNotification\n{\n    [JPEngine startEngine];\n    \n    NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@\"demo\" ofType:@\"js\"];\n    NSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil];\n    \n    [JPEngine evaluateScript:script];\n}\n\n// Implemented in demo.js\n- (IBAction)buttonJavaScriptTestAction:(id)sender { }\n\n- (IBAction)buttonObjectiveCTestAction:(id)sender\n{\n    self.clickCount++;\n    \n    [(NSButton*)sender setTitle:[NSString stringWithFormat:@\"Clicked %i times\", self.clickCount]];\n    \n    [self.tableView reloadData];\n}\n\n// Implemented in demo.js\n- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { return 0; }\n\n// Implemented in demo.js\n- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row { return nil; }\n\n@end\n"
  },
  {
    "path": "Demo/OSXDemo/JSPatchOSXDemo/Base.lproj/MainMenu.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion=\"6221\" systemVersion=\"14A389\" targetRuntime=\"MacOSX.Cocoa\" propertyAccessControl=\"none\" useAutolayout=\"YES\" customObjectInstantitationMethod=\"direct\">\n    <dependencies>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.CocoaPlugin\" version=\"6221\"/>\n    </dependencies>\n    <objects>\n        <customObject id=\"-2\" userLabel=\"File's Owner\" customClass=\"NSApplication\">\n            <connections>\n                <outlet property=\"delegate\" destination=\"Voe-Tx-rLC\" id=\"GzC-gU-4Uq\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"-1\" userLabel=\"First Responder\" customClass=\"FirstResponder\"/>\n        <customObject id=\"-3\" userLabel=\"Application\" customClass=\"NSObject\"/>\n        <customObject id=\"Voe-Tx-rLC\" customClass=\"AppDelegate\">\n            <connections>\n                <outlet property=\"tableView\" destination=\"wuP-aK-Z80\" id=\"j5c-pP-57s\"/>\n                <outlet property=\"window\" destination=\"QvC-M9-y7g\" id=\"gIp-Ho-8D9\"/>\n            </connections>\n        </customObject>\n        <customObject id=\"YLy-65-1bz\" customClass=\"NSFontManager\"/>\n        <menu title=\"Main Menu\" systemMenu=\"main\" id=\"AYu-sK-qS6\">\n            <items>\n                <menuItem title=\"JSPatchOSXDemo\" id=\"1Xt-HY-uBw\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"JSPatchOSXDemo\" systemMenu=\"apple\" id=\"uQy-DD-JDr\">\n                        <items>\n                            <menuItem title=\"About JSPatchOSXDemo\" id=\"5kV-Vb-QxS\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"orderFrontStandardAboutPanel:\" target=\"-1\" id=\"Exp-CZ-Vem\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"VOq-y0-SEH\"/>\n                            <menuItem title=\"Preferences…\" keyEquivalent=\",\" id=\"BOF-NM-1cW\"/>\n                            <menuItem isSeparatorItem=\"YES\" id=\"wFC-TO-SCJ\"/>\n                            <menuItem title=\"Services\" id=\"NMo-om-nkz\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Services\" systemMenu=\"services\" id=\"hz9-B4-Xy5\"/>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"4je-JR-u6R\"/>\n                            <menuItem title=\"Hide JSPatchOSXDemo\" keyEquivalent=\"h\" id=\"Olw-nP-bQN\">\n                                <connections>\n                                    <action selector=\"hide:\" target=\"-1\" id=\"PnN-Uc-m68\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Hide Others\" keyEquivalent=\"h\" id=\"Vdr-fp-XzO\">\n                                <modifierMask key=\"keyEquivalentModifierMask\" option=\"YES\" command=\"YES\"/>\n                                <connections>\n                                    <action selector=\"hideOtherApplications:\" target=\"-1\" id=\"VT4-aY-XCT\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Show All\" id=\"Kd2-mp-pUS\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"unhideAllApplications:\" target=\"-1\" id=\"Dhg-Le-xox\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"kCx-OE-vgT\"/>\n                            <menuItem title=\"Quit JSPatchOSXDemo\" keyEquivalent=\"q\" id=\"4sb-4s-VLi\">\n                                <connections>\n                                    <action selector=\"terminate:\" target=\"-1\" id=\"Te7-pn-YzF\"/>\n                                </connections>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n                <menuItem title=\"File\" id=\"dMs-cI-mzQ\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"File\" id=\"bib-Uj-vzu\">\n                        <items>\n                            <menuItem title=\"New\" keyEquivalent=\"n\" id=\"Was-JA-tGl\">\n                                <connections>\n                                    <action selector=\"newDocument:\" target=\"-1\" id=\"4Si-XN-c54\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Open…\" keyEquivalent=\"o\" id=\"IAo-SY-fd9\">\n                                <connections>\n                                    <action selector=\"openDocument:\" target=\"-1\" id=\"bVn-NM-KNZ\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Open Recent\" id=\"tXI-mr-wws\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Open Recent\" systemMenu=\"recentDocuments\" id=\"oas-Oc-fiZ\">\n                                    <items>\n                                        <menuItem title=\"Clear Menu\" id=\"vNY-rz-j42\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"clearRecentDocuments:\" target=\"-1\" id=\"Daa-9d-B3U\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"m54-Is-iLE\"/>\n                            <menuItem title=\"Close\" keyEquivalent=\"w\" id=\"DVo-aG-piG\">\n                                <connections>\n                                    <action selector=\"performClose:\" target=\"-1\" id=\"HmO-Ls-i7Q\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Save…\" keyEquivalent=\"s\" id=\"pxx-59-PXV\">\n                                <connections>\n                                    <action selector=\"saveDocument:\" target=\"-1\" id=\"teZ-XB-qJY\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Save As…\" keyEquivalent=\"S\" id=\"Bw7-FT-i3A\">\n                                <connections>\n                                    <action selector=\"saveDocumentAs:\" target=\"-1\" id=\"mDf-zr-I0C\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Revert to Saved\" id=\"KaW-ft-85H\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"revertDocumentToSaved:\" target=\"-1\" id=\"iJ3-Pv-kwq\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"aJh-i4-bef\"/>\n                            <menuItem title=\"Page Setup…\" keyEquivalent=\"P\" id=\"qIS-W8-SiK\">\n                                <modifierMask key=\"keyEquivalentModifierMask\" shift=\"YES\" command=\"YES\"/>\n                                <connections>\n                                    <action selector=\"runPageLayout:\" target=\"-1\" id=\"Din-rz-gC5\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Print…\" keyEquivalent=\"p\" id=\"aTl-1u-JFS\">\n                                <connections>\n                                    <action selector=\"print:\" target=\"-1\" id=\"qaZ-4w-aoO\"/>\n                                </connections>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n                <menuItem title=\"Edit\" id=\"5QF-Oa-p0T\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"Edit\" id=\"W48-6f-4Dl\">\n                        <items>\n                            <menuItem title=\"Undo\" keyEquivalent=\"z\" id=\"dRJ-4n-Yzg\">\n                                <connections>\n                                    <action selector=\"undo:\" target=\"-1\" id=\"M6e-cu-g7V\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Redo\" keyEquivalent=\"Z\" id=\"6dh-zS-Vam\">\n                                <connections>\n                                    <action selector=\"redo:\" target=\"-1\" id=\"oIA-Rs-6OD\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"WRV-NI-Exz\"/>\n                            <menuItem title=\"Cut\" keyEquivalent=\"x\" id=\"uRl-iY-unG\">\n                                <connections>\n                                    <action selector=\"cut:\" target=\"-1\" id=\"YJe-68-I9s\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Copy\" keyEquivalent=\"c\" id=\"x3v-GG-iWU\">\n                                <connections>\n                                    <action selector=\"copy:\" target=\"-1\" id=\"G1f-GL-Joy\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Paste\" keyEquivalent=\"v\" id=\"gVA-U4-sdL\">\n                                <connections>\n                                    <action selector=\"paste:\" target=\"-1\" id=\"UvS-8e-Qdg\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Paste and Match Style\" keyEquivalent=\"V\" id=\"WeT-3V-zwk\">\n                                <modifierMask key=\"keyEquivalentModifierMask\" option=\"YES\" command=\"YES\"/>\n                                <connections>\n                                    <action selector=\"pasteAsPlainText:\" target=\"-1\" id=\"cEh-KX-wJQ\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Delete\" id=\"pa3-QI-u2k\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"delete:\" target=\"-1\" id=\"0Mk-Ml-PaM\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Select All\" keyEquivalent=\"a\" id=\"Ruw-6m-B2m\">\n                                <connections>\n                                    <action selector=\"selectAll:\" target=\"-1\" id=\"VNm-Mi-diN\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"uyl-h8-XO2\"/>\n                            <menuItem title=\"Find\" id=\"4EN-yA-p0u\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Find\" id=\"1b7-l0-nxx\">\n                                    <items>\n                                        <menuItem title=\"Find…\" tag=\"1\" keyEquivalent=\"f\" id=\"Xz5-n4-O0W\">\n                                            <connections>\n                                                <action selector=\"performFindPanelAction:\" target=\"-1\" id=\"cD7-Qs-BN4\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Find and Replace…\" tag=\"12\" keyEquivalent=\"f\" id=\"YEy-JH-Tfz\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\" option=\"YES\" command=\"YES\"/>\n                                            <connections>\n                                                <action selector=\"performFindPanelAction:\" target=\"-1\" id=\"WD3-Gg-5AJ\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Find Next\" tag=\"2\" keyEquivalent=\"g\" id=\"q09-fT-Sye\">\n                                            <connections>\n                                                <action selector=\"performFindPanelAction:\" target=\"-1\" id=\"NDo-RZ-v9R\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Find Previous\" tag=\"3\" keyEquivalent=\"G\" id=\"OwM-mh-QMV\">\n                                            <connections>\n                                                <action selector=\"performFindPanelAction:\" target=\"-1\" id=\"HOh-sY-3ay\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Use Selection for Find\" tag=\"7\" keyEquivalent=\"e\" id=\"buJ-ug-pKt\">\n                                            <connections>\n                                                <action selector=\"performFindPanelAction:\" target=\"-1\" id=\"U76-nv-p5D\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Jump to Selection\" keyEquivalent=\"j\" id=\"S0p-oC-mLd\">\n                                            <connections>\n                                                <action selector=\"centerSelectionInVisibleArea:\" target=\"-1\" id=\"IOG-6D-g5B\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                            <menuItem title=\"Spelling and Grammar\" id=\"Dv1-io-Yv7\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Spelling\" id=\"3IN-sU-3Bg\">\n                                    <items>\n                                        <menuItem title=\"Show Spelling and Grammar\" keyEquivalent=\":\" id=\"HFo-cy-zxI\">\n                                            <connections>\n                                                <action selector=\"showGuessPanel:\" target=\"-1\" id=\"vFj-Ks-hy3\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Check Document Now\" keyEquivalent=\";\" id=\"hz2-CU-CR7\">\n                                            <connections>\n                                                <action selector=\"checkSpelling:\" target=\"-1\" id=\"fz7-VC-reM\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"bNw-od-mp5\"/>\n                                        <menuItem title=\"Check Spelling While Typing\" id=\"rbD-Rh-wIN\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleContinuousSpellChecking:\" target=\"-1\" id=\"7w6-Qz-0kB\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Check Grammar With Spelling\" id=\"mK6-2p-4JG\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleGrammarChecking:\" target=\"-1\" id=\"muD-Qn-j4w\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Correct Spelling Automatically\" id=\"78Y-hA-62v\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticSpellingCorrection:\" target=\"-1\" id=\"2lM-Qi-WAP\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                            <menuItem title=\"Substitutions\" id=\"9ic-FL-obx\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Substitutions\" id=\"FeM-D8-WVr\">\n                                    <items>\n                                        <menuItem title=\"Show Substitutions\" id=\"z6F-FW-3nz\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"orderFrontSubstitutionsPanel:\" target=\"-1\" id=\"oku-mr-iSq\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"gPx-C9-uUO\"/>\n                                        <menuItem title=\"Smart Copy/Paste\" id=\"9yt-4B-nSM\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleSmartInsertDelete:\" target=\"-1\" id=\"3IJ-Se-DZD\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Smart Quotes\" id=\"hQb-2v-fYv\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticQuoteSubstitution:\" target=\"-1\" id=\"ptq-xd-QOA\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Smart Dashes\" id=\"rgM-f4-ycn\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticDashSubstitution:\" target=\"-1\" id=\"oCt-pO-9gS\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Smart Links\" id=\"cwL-P1-jid\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticLinkDetection:\" target=\"-1\" id=\"Gip-E3-Fov\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Data Detectors\" id=\"tRr-pd-1PS\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticDataDetection:\" target=\"-1\" id=\"R1I-Nq-Kbl\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Text Replacement\" id=\"HFQ-gK-NFA\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleAutomaticTextReplacement:\" target=\"-1\" id=\"DvP-Fe-Py6\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                            <menuItem title=\"Transformations\" id=\"2oI-Rn-ZJC\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Transformations\" id=\"c8a-y6-VQd\">\n                                    <items>\n                                        <menuItem title=\"Make Upper Case\" id=\"vmV-6d-7jI\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"uppercaseWord:\" target=\"-1\" id=\"sPh-Tk-edu\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Make Lower Case\" id=\"d9M-CD-aMd\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"lowercaseWord:\" target=\"-1\" id=\"iUZ-b5-hil\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Capitalize\" id=\"UEZ-Bs-lqG\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"capitalizeWord:\" target=\"-1\" id=\"26H-TL-nsh\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                            <menuItem title=\"Speech\" id=\"xrE-MZ-jX0\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Speech\" id=\"3rS-ZA-NoH\">\n                                    <items>\n                                        <menuItem title=\"Start Speaking\" id=\"Ynk-f8-cLZ\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"startSpeaking:\" target=\"-1\" id=\"654-Ng-kyl\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Stop Speaking\" id=\"Oyz-dy-DGm\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"stopSpeaking:\" target=\"-1\" id=\"dX8-6p-jy9\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n                <menuItem title=\"Format\" id=\"jxT-CU-nIS\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"Format\" id=\"GEO-Iw-cKr\">\n                        <items>\n                            <menuItem title=\"Font\" id=\"Gi5-1S-RQB\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Font\" systemMenu=\"font\" id=\"aXa-aM-Jaq\">\n                                    <items>\n                                        <menuItem title=\"Show Fonts\" keyEquivalent=\"t\" id=\"Q5e-8K-NDq\">\n                                            <connections>\n                                                <action selector=\"orderFrontFontPanel:\" target=\"YLy-65-1bz\" id=\"WHr-nq-2xA\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Bold\" tag=\"2\" keyEquivalent=\"b\" id=\"GB9-OM-e27\">\n                                            <connections>\n                                                <action selector=\"addFontTrait:\" target=\"YLy-65-1bz\" id=\"hqk-hr-sYV\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Italic\" tag=\"1\" keyEquivalent=\"i\" id=\"Vjx-xi-njq\">\n                                            <connections>\n                                                <action selector=\"addFontTrait:\" target=\"YLy-65-1bz\" id=\"IHV-OB-c03\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Underline\" keyEquivalent=\"u\" id=\"WRG-CD-K1S\">\n                                            <connections>\n                                                <action selector=\"underline:\" target=\"-1\" id=\"FYS-2b-JAY\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"5gT-KC-WSO\"/>\n                                        <menuItem title=\"Bigger\" tag=\"3\" keyEquivalent=\"+\" id=\"Ptp-SP-VEL\">\n                                            <connections>\n                                                <action selector=\"modifyFont:\" target=\"YLy-65-1bz\" id=\"Uc7-di-UnL\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Smaller\" tag=\"4\" keyEquivalent=\"-\" id=\"i1d-Er-qST\">\n                                            <connections>\n                                                <action selector=\"modifyFont:\" target=\"YLy-65-1bz\" id=\"HcX-Lf-eNd\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"kx3-Dk-x3B\"/>\n                                        <menuItem title=\"Kern\" id=\"jBQ-r6-VK2\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <menu key=\"submenu\" title=\"Kern\" id=\"tlD-Oa-oAM\">\n                                                <items>\n                                                    <menuItem title=\"Use Default\" id=\"GUa-eO-cwY\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"useStandardKerning:\" target=\"-1\" id=\"6dk-9l-Ckg\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem title=\"Use None\" id=\"cDB-IK-hbR\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"turnOffKerning:\" target=\"-1\" id=\"U8a-gz-Maa\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem title=\"Tighten\" id=\"46P-cB-AYj\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"tightenKerning:\" target=\"-1\" id=\"hr7-Nz-8ro\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem title=\"Loosen\" id=\"ogc-rX-tC1\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"loosenKerning:\" target=\"-1\" id=\"8i4-f9-FKE\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                </items>\n                                            </menu>\n                                        </menuItem>\n                                        <menuItem title=\"Ligatures\" id=\"o6e-r0-MWq\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <menu key=\"submenu\" title=\"Ligatures\" id=\"w0m-vy-SC9\">\n                                                <items>\n                                                    <menuItem title=\"Use Default\" id=\"agt-UL-0e3\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"useStandardLigatures:\" target=\"-1\" id=\"7uR-wd-Dx6\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem title=\"Use None\" id=\"J7y-lM-qPV\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"turnOffLigatures:\" target=\"-1\" id=\"iX2-gA-Ilz\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem title=\"Use All\" id=\"xQD-1f-W4t\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"useAllLigatures:\" target=\"-1\" id=\"KcB-kA-TuK\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                </items>\n                                            </menu>\n                                        </menuItem>\n                                        <menuItem title=\"Baseline\" id=\"OaQ-X3-Vso\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <menu key=\"submenu\" title=\"Baseline\" id=\"ijk-EB-dga\">\n                                                <items>\n                                                    <menuItem title=\"Use Default\" id=\"3Om-Ey-2VK\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"unscript:\" target=\"-1\" id=\"0vZ-95-Ywn\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem title=\"Superscript\" id=\"Rqc-34-cIF\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"superscript:\" target=\"-1\" id=\"3qV-fo-wpU\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem title=\"Subscript\" id=\"I0S-gh-46l\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"subscript:\" target=\"-1\" id=\"Q6W-4W-IGz\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem title=\"Raise\" id=\"2h7-ER-AoG\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"raiseBaseline:\" target=\"-1\" id=\"4sk-31-7Q9\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem title=\"Lower\" id=\"1tx-W0-xDw\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"lowerBaseline:\" target=\"-1\" id=\"OF1-bc-KW4\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                </items>\n                                            </menu>\n                                        </menuItem>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"Ndw-q3-faq\"/>\n                                        <menuItem title=\"Show Colors\" keyEquivalent=\"C\" id=\"bgn-CT-cEk\">\n                                            <connections>\n                                                <action selector=\"orderFrontColorPanel:\" target=\"-1\" id=\"mSX-Xz-DV3\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"iMs-zA-UFJ\"/>\n                                        <menuItem title=\"Copy Style\" keyEquivalent=\"c\" id=\"5Vv-lz-BsD\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\" option=\"YES\" command=\"YES\"/>\n                                            <connections>\n                                                <action selector=\"copyFont:\" target=\"-1\" id=\"GJO-xA-L4q\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Paste Style\" keyEquivalent=\"v\" id=\"vKC-jM-MkH\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\" option=\"YES\" command=\"YES\"/>\n                                            <connections>\n                                                <action selector=\"pasteFont:\" target=\"-1\" id=\"JfD-CL-leO\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                            <menuItem title=\"Text\" id=\"Fal-I4-PZk\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <menu key=\"submenu\" title=\"Text\" id=\"d9c-me-L2H\">\n                                    <items>\n                                        <menuItem title=\"Align Left\" keyEquivalent=\"{\" id=\"ZM1-6Q-yy1\">\n                                            <connections>\n                                                <action selector=\"alignLeft:\" target=\"-1\" id=\"zUv-R1-uAa\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Center\" keyEquivalent=\"|\" id=\"VIY-Ag-zcb\">\n                                            <connections>\n                                                <action selector=\"alignCenter:\" target=\"-1\" id=\"spX-mk-kcS\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Justify\" id=\"J5U-5w-g23\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"alignJustified:\" target=\"-1\" id=\"ljL-7U-jND\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Align Right\" keyEquivalent=\"}\" id=\"wb2-vD-lq4\">\n                                            <connections>\n                                                <action selector=\"alignRight:\" target=\"-1\" id=\"r48-bG-YeY\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"4s2-GY-VfK\"/>\n                                        <menuItem title=\"Writing Direction\" id=\"H1b-Si-o9J\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <menu key=\"submenu\" title=\"Writing Direction\" id=\"8mr-sm-Yjd\">\n                                                <items>\n                                                    <menuItem title=\"Paragraph\" enabled=\"NO\" id=\"ZvO-Gk-QUH\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                    </menuItem>\n                                                    <menuItem id=\"YGs-j5-SAR\">\n                                                        <string key=\"title\">\tDefault</string>\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"makeBaseWritingDirectionNatural:\" target=\"-1\" id=\"qtV-5e-UBP\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem id=\"Lbh-J2-qVU\">\n                                                        <string key=\"title\">\tLeft to Right</string>\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"makeBaseWritingDirectionLeftToRight:\" target=\"-1\" id=\"S0X-9S-QSf\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem id=\"jFq-tB-4Kx\">\n                                                        <string key=\"title\">\tRight to Left</string>\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"makeBaseWritingDirectionRightToLeft:\" target=\"-1\" id=\"5fk-qB-AqJ\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem isSeparatorItem=\"YES\" id=\"swp-gr-a21\"/>\n                                                    <menuItem title=\"Selection\" enabled=\"NO\" id=\"cqv-fj-IhA\">\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                    </menuItem>\n                                                    <menuItem id=\"Nop-cj-93Q\">\n                                                        <string key=\"title\">\tDefault</string>\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"makeTextWritingDirectionNatural:\" target=\"-1\" id=\"lPI-Se-ZHp\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem id=\"BgM-ve-c93\">\n                                                        <string key=\"title\">\tLeft to Right</string>\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"makeTextWritingDirectionLeftToRight:\" target=\"-1\" id=\"caW-Bv-w94\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                    <menuItem id=\"RB4-Sm-HuC\">\n                                                        <string key=\"title\">\tRight to Left</string>\n                                                        <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                                        <connections>\n                                                            <action selector=\"makeTextWritingDirectionRightToLeft:\" target=\"-1\" id=\"EXD-6r-ZUu\"/>\n                                                        </connections>\n                                                    </menuItem>\n                                                </items>\n                                            </menu>\n                                        </menuItem>\n                                        <menuItem isSeparatorItem=\"YES\" id=\"fKy-g9-1gm\"/>\n                                        <menuItem title=\"Show Ruler\" id=\"vLm-3I-IUL\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                            <connections>\n                                                <action selector=\"toggleRuler:\" target=\"-1\" id=\"FOx-HJ-KwY\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Copy Ruler\" keyEquivalent=\"c\" id=\"MkV-Pr-PK5\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\" control=\"YES\" command=\"YES\"/>\n                                            <connections>\n                                                <action selector=\"copyRuler:\" target=\"-1\" id=\"71i-fW-3W2\"/>\n                                            </connections>\n                                        </menuItem>\n                                        <menuItem title=\"Paste Ruler\" keyEquivalent=\"v\" id=\"LVM-kO-fVI\">\n                                            <modifierMask key=\"keyEquivalentModifierMask\" control=\"YES\" command=\"YES\"/>\n                                            <connections>\n                                                <action selector=\"pasteRuler:\" target=\"-1\" id=\"cSh-wd-qM2\"/>\n                                            </connections>\n                                        </menuItem>\n                                    </items>\n                                </menu>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n                <menuItem title=\"View\" id=\"H8h-7b-M4v\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"View\" id=\"HyV-fh-RgO\">\n                        <items>\n                            <menuItem title=\"Show Toolbar\" keyEquivalent=\"t\" id=\"snW-S8-Cw5\">\n                                <modifierMask key=\"keyEquivalentModifierMask\" option=\"YES\" command=\"YES\"/>\n                                <connections>\n                                    <action selector=\"toggleToolbarShown:\" target=\"-1\" id=\"BXY-wc-z0C\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Customize Toolbar…\" id=\"1UK-8n-QPP\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"runToolbarCustomizationPalette:\" target=\"-1\" id=\"pQI-g3-MTW\"/>\n                                </connections>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n                <menuItem title=\"Window\" id=\"aUF-d1-5bR\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"Window\" systemMenu=\"window\" id=\"Td7-aD-5lo\">\n                        <items>\n                            <menuItem title=\"Minimize\" keyEquivalent=\"m\" id=\"OY7-WF-poV\">\n                                <connections>\n                                    <action selector=\"performMiniaturize:\" target=\"-1\" id=\"VwT-WD-YPe\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem title=\"Zoom\" id=\"R4o-n2-Eq4\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"performZoom:\" target=\"-1\" id=\"DIl-cC-cCs\"/>\n                                </connections>\n                            </menuItem>\n                            <menuItem isSeparatorItem=\"YES\" id=\"eu3-7i-yIM\"/>\n                            <menuItem title=\"Bring All to Front\" id=\"LE2-aR-0XJ\">\n                                <modifierMask key=\"keyEquivalentModifierMask\"/>\n                                <connections>\n                                    <action selector=\"arrangeInFront:\" target=\"-1\" id=\"DRN-fu-gQh\"/>\n                                </connections>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n                <menuItem title=\"Help\" id=\"wpr-3q-Mcd\">\n                    <modifierMask key=\"keyEquivalentModifierMask\"/>\n                    <menu key=\"submenu\" title=\"Help\" systemMenu=\"help\" id=\"F2S-fz-NVQ\">\n                        <items>\n                            <menuItem title=\"JSPatchOSXDemo Help\" keyEquivalent=\"?\" id=\"FKE-Sm-Kum\">\n                                <connections>\n                                    <action selector=\"showHelp:\" target=\"-1\" id=\"y7X-2Q-9no\"/>\n                                </connections>\n                            </menuItem>\n                        </items>\n                    </menu>\n                </menuItem>\n            </items>\n        </menu>\n        <window title=\"JSPatch OSX Demo\" allowsToolTipsWhenApplicationIsInactive=\"NO\" autorecalculatesKeyViewLoop=\"NO\" releasedWhenClosed=\"NO\" animationBehavior=\"default\" id=\"QvC-M9-y7g\">\n            <windowStyleMask key=\"styleMask\" titled=\"YES\" closable=\"YES\" miniaturizable=\"YES\" resizable=\"YES\"/>\n            <windowPositionMask key=\"initialPositionMask\" leftStrut=\"YES\" rightStrut=\"YES\" topStrut=\"YES\" bottomStrut=\"YES\"/>\n            <rect key=\"contentRect\" x=\"335\" y=\"390\" width=\"350\" height=\"323\"/>\n            <rect key=\"screenRect\" x=\"0.0\" y=\"0.0\" width=\"2560\" height=\"1417\"/>\n            <view key=\"contentView\" id=\"EiT-Mj-1SZ\">\n                <rect key=\"frame\" x=\"0.0\" y=\"-1\" width=\"350\" height=\"323\"/>\n                <autoresizingMask key=\"autoresizingMask\"/>\n                <subviews>\n                    <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"zFR-9x-Mv0\">\n                        <rect key=\"frame\" x=\"14\" y=\"275\" width=\"322\" height=\"32\"/>\n                        <buttonCell key=\"cell\" type=\"push\" title=\"JavaScript Test\" bezelStyle=\"rounded\" alignment=\"center\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"pxZ-1F-hAD\">\n                            <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                            <font key=\"font\" metaFont=\"system\"/>\n                            <connections>\n                                <action selector=\"buttonJavaScriptTestAction:\" target=\"Voe-Tx-rLC\" id=\"SCa-1P-Jk4\"/>\n                            </connections>\n                        </buttonCell>\n                    </button>\n                    <button verticalHuggingPriority=\"750\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"dm7-og-VMf\">\n                        <rect key=\"frame\" x=\"14\" y=\"242\" width=\"322\" height=\"32\"/>\n                        <buttonCell key=\"cell\" type=\"push\" title=\"Objective-C Test\" bezelStyle=\"rounded\" alignment=\"center\" borderStyle=\"border\" imageScaling=\"proportionallyDown\" inset=\"2\" id=\"Nvv-70-ZWK\">\n                            <behavior key=\"behavior\" pushIn=\"YES\" lightByBackground=\"YES\" lightByGray=\"YES\"/>\n                            <font key=\"font\" metaFont=\"system\"/>\n                            <connections>\n                                <action selector=\"buttonObjectiveCTestAction:\" target=\"Voe-Tx-rLC\" id=\"D0f-VL-CQc\"/>\n                            </connections>\n                        </buttonCell>\n                    </button>\n                    <scrollView autohidesScrollers=\"YES\" horizontalLineScroll=\"19\" horizontalPageScroll=\"10\" verticalLineScroll=\"19\" verticalPageScroll=\"10\" usesPredominantAxisScrolling=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"rEf-Eu-fx1\">\n                        <rect key=\"frame\" x=\"-1\" y=\"-1\" width=\"352\" height=\"230\"/>\n                        <clipView key=\"contentView\" id=\"WKZ-k4-K5V\">\n                            <rect key=\"frame\" x=\"1\" y=\"17\" width=\"238\" height=\"117\"/>\n                            <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                            <subviews>\n                                <tableView verticalHuggingPriority=\"750\" allowsExpansionToolTips=\"YES\" alternatingRowBackgroundColors=\"YES\" columnReordering=\"NO\" columnSelection=\"YES\" columnResizing=\"NO\" multipleSelection=\"NO\" autosaveColumns=\"NO\" rowSizeStyle=\"automatic\" viewBased=\"YES\" id=\"wuP-aK-Z80\">\n                                    <autoresizingMask key=\"autoresizingMask\"/>\n                                    <size key=\"intercellSpacing\" width=\"3\" height=\"2\"/>\n                                    <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <color key=\"gridColor\" name=\"gridColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                    <tableColumns>\n                                        <tableColumn width=\"347\" minWidth=\"40\" maxWidth=\"1000\" id=\"1nF-Wq-PwI\">\n                                            <tableHeaderCell key=\"headerCell\" lineBreakMode=\"truncatingTail\" borderStyle=\"border\" alignment=\"left\">\n                                                <font key=\"font\" metaFont=\"smallSystem\"/>\n                                                <color key=\"textColor\" name=\"headerTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                <color key=\"backgroundColor\" name=\"headerColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            </tableHeaderCell>\n                                            <textFieldCell key=\"dataCell\" lineBreakMode=\"truncatingTail\" selectable=\"YES\" editable=\"YES\" alignment=\"left\" title=\"Text Cell\" id=\"ziq-1n-P1b\">\n                                                <font key=\"font\" metaFont=\"system\"/>\n                                                <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                            </textFieldCell>\n                                            <tableColumnResizingMask key=\"resizingMask\" resizeWithTable=\"YES\" userResizable=\"YES\"/>\n                                            <prototypeCellViews>\n                                                <tableCellView identifier=\"TABLEVIEW_CELL\" id=\"BZH-WC-1Uh\">\n                                                    <rect key=\"frame\" x=\"1\" y=\"1\" width=\"347\" height=\"17\"/>\n                                                    <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                                                    <subviews>\n                                                        <textField verticalHuggingPriority=\"750\" horizontalCompressionResistancePriority=\"250\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"wqv-Be-v2q\">\n                                                            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"346\" height=\"17\"/>\n                                                            <textFieldCell key=\"cell\" lineBreakMode=\"truncatingTail\" sendsActionOnEndEditing=\"YES\" title=\"Table View Cell\" id=\"EJV-SP-U7s\">\n                                                                <font key=\"font\" metaFont=\"system\"/>\n                                                                <color key=\"textColor\" name=\"controlTextColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                                <color key=\"backgroundColor\" name=\"controlColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                                                            </textFieldCell>\n                                                        </textField>\n                                                    </subviews>\n                                                    <constraints>\n                                                        <constraint firstAttribute=\"centerY\" secondItem=\"wqv-Be-v2q\" secondAttribute=\"centerY\" id=\"SCd-PT-zkz\"/>\n                                                        <constraint firstAttribute=\"trailing\" secondItem=\"wqv-Be-v2q\" secondAttribute=\"trailing\" constant=\"3\" id=\"Tmd-0d-hDe\"/>\n                                                        <constraint firstItem=\"wqv-Be-v2q\" firstAttribute=\"leading\" secondItem=\"BZH-WC-1Uh\" secondAttribute=\"leading\" constant=\"2\" id=\"lPQ-C6-fSe\"/>\n                                                    </constraints>\n                                                    <connections>\n                                                        <outlet property=\"textField\" destination=\"wqv-Be-v2q\" id=\"7g7-we-gt4\"/>\n                                                    </connections>\n                                                </tableCellView>\n                                            </prototypeCellViews>\n                                        </tableColumn>\n                                    </tableColumns>\n                                    <connections>\n                                        <outlet property=\"dataSource\" destination=\"Voe-Tx-rLC\" id=\"4TC-Do-hvs\"/>\n                                        <outlet property=\"delegate\" destination=\"Voe-Tx-rLC\" id=\"V9v-Bk-6Gk\"/>\n                                    </connections>\n                                </tableView>\n                            </subviews>\n                            <color key=\"backgroundColor\" name=\"controlBackgroundColor\" catalog=\"System\" colorSpace=\"catalog\"/>\n                        </clipView>\n                        <scroller key=\"horizontalScroller\" hidden=\"YES\" verticalHuggingPriority=\"750\" horizontal=\"YES\" id=\"SQU-72-St1\">\n                            <rect key=\"frame\" x=\"1\" y=\"119\" width=\"223\" height=\"15\"/>\n                            <autoresizingMask key=\"autoresizingMask\"/>\n                        </scroller>\n                        <scroller key=\"verticalScroller\" hidden=\"YES\" verticalHuggingPriority=\"750\" horizontal=\"NO\" id=\"4e4-Fk-C8s\">\n                            <rect key=\"frame\" x=\"224\" y=\"17\" width=\"15\" height=\"102\"/>\n                            <autoresizingMask key=\"autoresizingMask\"/>\n                        </scroller>\n                    </scrollView>\n                </subviews>\n                <constraints>\n                    <constraint firstAttribute=\"trailing\" secondItem=\"rEf-Eu-fx1\" secondAttribute=\"trailing\" constant=\"-1\" id=\"0ii-j0-OMo\"/>\n                    <constraint firstItem=\"dm7-og-VMf\" firstAttribute=\"top\" secondItem=\"zFR-9x-Mv0\" secondAttribute=\"bottom\" constant=\"12\" id=\"1kY-mu-4bW\"/>\n                    <constraint firstItem=\"rEf-Eu-fx1\" firstAttribute=\"top\" secondItem=\"dm7-og-VMf\" secondAttribute=\"bottom\" constant=\"20\" id=\"GFf-vS-YDx\"/>\n                    <constraint firstAttribute=\"trailing\" secondItem=\"zFR-9x-Mv0\" secondAttribute=\"trailing\" constant=\"20\" id=\"Vid-Tz-wag\"/>\n                    <constraint firstItem=\"zFR-9x-Mv0\" firstAttribute=\"leading\" secondItem=\"EiT-Mj-1SZ\" secondAttribute=\"leading\" constant=\"20\" id=\"W2B-Ih-eDQ\"/>\n                    <constraint firstAttribute=\"bottom\" secondItem=\"rEf-Eu-fx1\" secondAttribute=\"bottom\" constant=\"-1\" id=\"jLG-SL-y3W\"/>\n                    <constraint firstItem=\"rEf-Eu-fx1\" firstAttribute=\"leading\" secondItem=\"EiT-Mj-1SZ\" secondAttribute=\"leading\" constant=\"-1\" id=\"njU-vu-x1n\"/>\n                    <constraint firstItem=\"zFR-9x-Mv0\" firstAttribute=\"centerX\" secondItem=\"dm7-og-VMf\" secondAttribute=\"centerX\" id=\"typ-gR-VSE\"/>\n                    <constraint firstItem=\"zFR-9x-Mv0\" firstAttribute=\"width\" secondItem=\"dm7-og-VMf\" secondAttribute=\"width\" id=\"vLl-as-Xzn\"/>\n                    <constraint firstItem=\"zFR-9x-Mv0\" firstAttribute=\"top\" secondItem=\"EiT-Mj-1SZ\" secondAttribute=\"top\" constant=\"20\" id=\"xLD-6S-q0W\"/>\n                </constraints>\n            </view>\n            <point key=\"canvasLocation\" x=\"335\" y=\"639.5\"/>\n        </window>\n    </objects>\n</document>\n"
  },
  {
    "path": "Demo/OSXDemo/JSPatchOSXDemo/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIconFile</key>\n\t<string></string>\n\t<key>CFBundleIdentifier</key>\n\t<string>com.lemonmojo.$(PRODUCT_NAME:rfc1034identifier)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n\t<key>LSMinimumSystemVersion</key>\n\t<string>$(MACOSX_DEPLOYMENT_TARGET)</string>\n\t<key>NSHumanReadableCopyright</key>\n\t<string>Copyright © 2015 Lemon Mojo. All rights reserved.</string>\n\t<key>NSMainNibFile</key>\n\t<string>MainMenu</string>\n\t<key>NSPrincipalClass</key>\n\t<string>NSApplication</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Demo/OSXDemo/JSPatchOSXDemo/demo.js",
    "content": "defineClass('AppDelegate', {\n    buttonJavaScriptTestAction: function(sender) {\n        self.setClickCount(self.clickCount() + 1);\n        \n        sender.setTitle(\"Clicked \" + self.clickCount() + \" times\");\n        \n        self.tableView().reloadData();\n    },\n            \n    numberOfRowsInTableView: function(tableView) {\n        return self.clickCount();\n    },\n            \n    tableView_viewForTableColumn_row: function(tableView, tableColumn, row) {\n        var view = tableView.makeViewWithIdentifier_owner(\"TABLEVIEW_CELL\", self);\n        \n        view.textField().setStringValue(\"Clicked \" + (row + 1) + \" times\");\n        \n        return view;\n    }\n});"
  },
  {
    "path": "Demo/OSXDemo/JSPatchOSXDemo/main.m",
    "content": "//\n//  main.m\n//  JSPatchOSXDemo\n//\n//  Created by Felix Deimel on 26.05.15.\n//  Copyright (c) 2015 Lemon Mojo. All rights reserved.\n//\n\n#import <Cocoa/Cocoa.h>\n\nint main(int argc, const char * argv[]) {\n    return NSApplicationMain(argc, argv);\n}\n"
  },
  {
    "path": "Demo/OSXDemo/JSPatchOSXDemo.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t3613C3941C632A3E00E915CB /* JPEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3921C632A3E00E915CB /* JPEngine.m */; };\n\t\t3613C3951C632A3E00E915CB /* JSPatch.js in Resources */ = {isa = PBXBuildFile; fileRef = 3613C3931C632A3E00E915CB /* JSPatch.js */; };\n\t\tE7E413DB1B14853E008E10DC /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E7E413DA1B14853E008E10DC /* AppDelegate.m */; };\n\t\tE7E413DD1B14853E008E10DC /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E7E413DC1B14853E008E10DC /* main.m */; };\n\t\tE7E413E21B14853E008E10DC /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = E7E413E01B14853E008E10DC /* MainMenu.xib */; };\n\t\tE7E413FE1B1486AD008E10DC /* demo.js in Resources */ = {isa = PBXBuildFile; fileRef = E7E413FD1B1486AD008E10DC /* demo.js */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXFileReference section */\n\t\t3613C3911C632A3E00E915CB /* JPEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPEngine.h; sourceTree = \"<group>\"; };\n\t\t3613C3921C632A3E00E915CB /* JPEngine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPEngine.m; sourceTree = \"<group>\"; };\n\t\t3613C3931C632A3E00E915CB /* JSPatch.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = JSPatch.js; sourceTree = \"<group>\"; };\n\t\tE7E413D41B14853E008E10DC /* JSPatchOSXDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JSPatchOSXDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tE7E413D81B14853E008E10DC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\tE7E413D91B14853E008E10DC /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = \"<group>\"; };\n\t\tE7E413DA1B14853E008E10DC /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = \"<group>\"; };\n\t\tE7E413DC1B14853E008E10DC /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = \"<group>\"; };\n\t\tE7E413E11B14853E008E10DC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = \"<group>\"; };\n\t\tE7E413FD1B1486AD008E10DC /* demo.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = demo.js; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\tE7E413D11B14853E008E10DC /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t3613C3901C632A3E00E915CB /* JSPatch */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3613C3911C632A3E00E915CB /* JPEngine.h */,\n\t\t\t\t3613C3921C632A3E00E915CB /* JPEngine.m */,\n\t\t\t\t3613C3931C632A3E00E915CB /* JSPatch.js */,\n\t\t\t);\n\t\t\tname = JSPatch;\n\t\t\tpath = ../../../JSPatch;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tE7E413CB1B14853E008E10DC = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tE7E413D61B14853E008E10DC /* JSPatchOSXDemo */,\n\t\t\t\tE7E413D51B14853E008E10DC /* Products */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tE7E413D51B14853E008E10DC /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tE7E413D41B14853E008E10DC /* JSPatchOSXDemo.app */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tE7E413D61B14853E008E10DC /* JSPatchOSXDemo */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3613C3901C632A3E00E915CB /* JSPatch */,\n\t\t\t\tE7E413D91B14853E008E10DC /* AppDelegate.h */,\n\t\t\t\tE7E413DA1B14853E008E10DC /* AppDelegate.m */,\n\t\t\t\tE7E413FD1B1486AD008E10DC /* demo.js */,\n\t\t\t\tE7E413E01B14853E008E10DC /* MainMenu.xib */,\n\t\t\t\tE7E413D71B14853E008E10DC /* Supporting Files */,\n\t\t\t);\n\t\t\tpath = JSPatchOSXDemo;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tE7E413D71B14853E008E10DC /* Supporting Files */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tE7E413D81B14853E008E10DC /* Info.plist */,\n\t\t\t\tE7E413DC1B14853E008E10DC /* main.m */,\n\t\t\t);\n\t\t\tname = \"Supporting Files\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\tE7E413D31B14853E008E10DC /* JSPatchOSXDemo */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = E7E413F11B14853E008E10DC /* Build configuration list for PBXNativeTarget \"JSPatchOSXDemo\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tE7E413D01B14853E008E10DC /* Sources */,\n\t\t\t\tE7E413D11B14853E008E10DC /* Frameworks */,\n\t\t\t\tE7E413D21B14853E008E10DC /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = JSPatchOSXDemo;\n\t\t\tproductName = JSPatchOSXDemo;\n\t\t\tproductReference = E7E413D41B14853E008E10DC /* JSPatchOSXDemo.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\tE7E413CC1B14853E008E10DC /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 0630;\n\t\t\t\tORGANIZATIONNAME = \"Lemon Mojo\";\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\tE7E413D31B14853E008E10DC = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 6.3.2;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = E7E413CF1B14853E008E10DC /* Build configuration list for PBXProject \"JSPatchOSXDemo\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = E7E413CB1B14853E008E10DC;\n\t\t\tproductRefGroup = E7E413D51B14853E008E10DC /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\tE7E413D31B14853E008E10DC /* JSPatchOSXDemo */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\tE7E413D21B14853E008E10DC /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t3613C3951C632A3E00E915CB /* JSPatch.js in Resources */,\n\t\t\t\tE7E413E21B14853E008E10DC /* MainMenu.xib in Resources */,\n\t\t\t\tE7E413FE1B1486AD008E10DC /* demo.js in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\tE7E413D01B14853E008E10DC /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t3613C3941C632A3E00E915CB /* JPEngine.m in Sources */,\n\t\t\t\tE7E413DD1B14853E008E10DC /* main.m in Sources */,\n\t\t\t\tE7E413DB1B14853E008E10DC /* AppDelegate.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXVariantGroup section */\n\t\tE7E413E01B14853E008E10DC /* MainMenu.xib */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\tE7E413E11B14853E008E10DC /* Base */,\n\t\t\t);\n\t\t\tname = MainMenu.xib;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\tE7E413EF1B14853E008E10DC /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"-\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.10;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = macosx;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tE7E413F01B14853E008E10DC /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCODE_SIGN_IDENTITY = \"-\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tMACOSX_DEPLOYMENT_TARGET = 10.10;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = macosx;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tE7E413F21B14853E008E10DC /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tINFOPLIST_FILE = JSPatchOSXDemo/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/../Frameworks\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tE7E413F31B14853E008E10DC /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;\n\t\t\t\tINFOPLIST_FILE = JSPatchOSXDemo/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/../Frameworks\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\tE7E413CF1B14853E008E10DC /* Build configuration list for PBXProject \"JSPatchOSXDemo\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tE7E413EF1B14853E008E10DC /* Debug */,\n\t\t\t\tE7E413F01B14853E008E10DC /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tE7E413F11B14853E008E10DC /* Build configuration list for PBXNativeTarget \"JSPatchOSXDemo\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tE7E413F21B14853E008E10DC /* Debug */,\n\t\t\t\tE7E413F31B14853E008E10DC /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = E7E413CC1B14853E008E10DC /* Project object */;\n}\n"
  },
  {
    "path": "Demo/OSXDemo/JSPatchOSXDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:JSPatchOSXDemo.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "Demo/SwiftDemo/SwiftDemo/AppDelegate.swift",
    "content": "//\n//  AppDelegate.swift\n//  SwiftDemo\n//\n//  Created by jspatch on 16/2/3.\n//  Copyright © 2016年 Arlen. All rights reserved.\n//\n\nimport UIKit\n\n@UIApplicationMain\nclass AppDelegate: UIResponder, UIApplicationDelegate {\n\n    var window: UIWindow?\n\n\n    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {\n        // Override point for customization after application launch.\n        \n        let aClass: AnyClass? = NSClassFromString(\"SwiftDemo.ViewController\")\n        if (aClass != nil) {\n            let clsName = NSStringFromClass(aClass!)\n            print(clsName)\n        } else {\n            print(\"error ViewController not found\")\n        }\n        \n        let bClass: AnyClass? = NSClassFromString(\"SwiftDemo.TestObject\")\n        if (bClass != nil) {\n            let clsName = NSStringFromClass(bClass!)\n            print(clsName)\n        } else {\n            print(\"error TestObject not found\")\n        }\n        \n        let path = Bundle.main.path(forResource: \"demo\", ofType: \"js\")\n        do {\n            let patch = try String(contentsOfFile: path!)\n            \n            JPEngine.start()\n            JPEngine.evaluateScript(patch)\n            \n        } catch {}\n        \n        \n        return true\n    }\n\n    func applicationWillResignActive(_ application: UIApplication) {\n        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.\n        // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.\n    }\n\n    func applicationDidEnterBackground(_ application: UIApplication) {\n        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.\n        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.\n    }\n\n    func applicationWillEnterForeground(_ application: UIApplication) {\n        // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.\n    }\n\n    func applicationDidBecomeActive(_ application: UIApplication) {\n        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.\n    }\n\n    func applicationWillTerminate(_ application: UIApplication) {\n        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.\n    }\n\n\n}\n\n"
  },
  {
    "path": "Demo/SwiftDemo/SwiftDemo/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"60x60\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"60x60\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"76x76\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"76x76\",\n      \"scale\" : \"2x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Demo/SwiftDemo/SwiftDemo/Base.lproj/LaunchScreen.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"9532\" systemVersion=\"15D21\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" launchScreen=\"YES\" useTraitCollections=\"YES\" initialViewController=\"01J-lp-oVM\">\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"9530\"/>\n    </dependencies>\n    <scenes>\n        <!--View Controller-->\n        <scene sceneID=\"EHf-IW-A2E\">\n            <objects>\n                <viewController id=\"01J-lp-oVM\" sceneMemberID=\"viewController\">\n                    <layoutGuides>\n                        <viewControllerLayoutGuide type=\"top\" id=\"Llm-lL-Icb\"/>\n                        <viewControllerLayoutGuide type=\"bottom\" id=\"xb3-aO-Qok\"/>\n                    </layoutGuides>\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"Ze5-6b-2t3\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"600\" height=\"600\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"calibratedWhite\"/>\n                    </view>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"iYj-Kq-Ea1\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"53\" y=\"375\"/>\n        </scene>\n    </scenes>\n</document>\n"
  },
  {
    "path": "Demo/SwiftDemo/SwiftDemo/Base.lproj/Main.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"9059\" systemVersion=\"14F27\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" useTraitCollections=\"YES\" initialViewController=\"BYZ-38-t0r\">\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"9049\"/>\n    </dependencies>\n    <scenes>\n        <!--View Controller-->\n        <scene sceneID=\"tne-QT-ifu\">\n            <objects>\n                <viewController id=\"BYZ-38-t0r\" customClass=\"ViewController\" customModule=\"SwiftDemo\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">\n                    <layoutGuides>\n                        <viewControllerLayoutGuide type=\"top\" id=\"y3c-jy-aDJ\"/>\n                        <viewControllerLayoutGuide type=\"bottom\" id=\"wfy-db-euE\"/>\n                    </layoutGuides>\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"8bC-Xf-vdC\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"600\" height=\"600\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <tableView clipsSubviews=\"YES\" contentMode=\"scaleToFill\" alwaysBounceVertical=\"YES\" dataMode=\"prototypes\" style=\"plain\" separatorStyle=\"default\" rowHeight=\"44\" sectionHeaderHeight=\"28\" sectionFooterHeight=\"28\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"U8v-lx-Nu4\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"600\" height=\"600\"/>\n                                <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n                                <prototypes>\n                                    <tableViewCell clipsSubviews=\"YES\" contentMode=\"scaleToFill\" selectionStyle=\"default\" indentationWidth=\"10\" reuseIdentifier=\"TableviewCell\" id=\"gSU-lE-IN7\">\n                                        <rect key=\"frame\" x=\"0.0\" y=\"28\" width=\"600\" height=\"44\"/>\n                                        <autoresizingMask key=\"autoresizingMask\"/>\n                                        <tableViewCellContentView key=\"contentView\" opaque=\"NO\" clipsSubviews=\"YES\" multipleTouchEnabled=\"YES\" contentMode=\"center\" tableViewCell=\"gSU-lE-IN7\" id=\"f7g-Yh-eAF\">\n                                            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"600\" height=\"43.5\"/>\n                                            <autoresizingMask key=\"autoresizingMask\"/>\n                                        </tableViewCellContentView>\n                                    </tableViewCell>\n                                </prototypes>\n                                <connections>\n                                    <outlet property=\"dataSource\" destination=\"BYZ-38-t0r\" id=\"O2z-at-DvO\"/>\n                                    <outlet property=\"delegate\" destination=\"BYZ-38-t0r\" id=\"rmL-D8-BHa\"/>\n                                </connections>\n                            </tableView>\n                        </subviews>\n                        <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"calibratedWhite\"/>\n                        <constraints>\n                            <constraint firstItem=\"U8v-lx-Nu4\" firstAttribute=\"top\" secondItem=\"8bC-Xf-vdC\" secondAttribute=\"top\" id=\"60r-mk-k3y\"/>\n                            <constraint firstItem=\"U8v-lx-Nu4\" firstAttribute=\"bottom\" secondItem=\"wfy-db-euE\" secondAttribute=\"top\" id=\"JY3-jd-PVM\"/>\n                            <constraint firstAttribute=\"trailing\" secondItem=\"U8v-lx-Nu4\" secondAttribute=\"trailing\" id=\"N8A-ap-EfG\"/>\n                            <constraint firstItem=\"U8v-lx-Nu4\" firstAttribute=\"leading\" secondItem=\"8bC-Xf-vdC\" secondAttribute=\"leading\" id=\"i47-uN-Gcr\"/>\n                        </constraints>\n                    </view>\n                    <connections>\n                        <outlet property=\"tableView\" destination=\"U8v-lx-Nu4\" id=\"fAg-39-ZHC\"/>\n                    </connections>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"dkx-z0-nzr\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n        </scene>\n    </scenes>\n</document>\n"
  },
  {
    "path": "Demo/SwiftDemo/SwiftDemo/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n\t<key>LSRequiresIPhoneOS</key>\n\t<true/>\n\t<key>UILaunchStoryboardName</key>\n\t<string>LaunchScreen</string>\n\t<key>UIMainStoryboardFile</key>\n\t<string>Main</string>\n\t<key>UIRequiredDeviceCapabilities</key>\n\t<array>\n\t\t<string>armv7</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations~ipad</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationPortraitUpsideDown</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "Demo/SwiftDemo/SwiftDemo/SwiftDemo-Bridging-Header.h",
    "content": "//\n//  SwiftDemo-Bridging-Header.h\n//  SwiftDemo\n//\n//  Created by bang on 2/4/16.\n//  Copyright © 2016 Arlen. All rights reserved.\n//\n\n#ifndef SwiftDemo_Bridging_Header_h\n#define SwiftDemo_Bridging_Header_h\n\n#import \"JPEngine.h\"\n\n#endif /* SwiftDemo_Bridging_Header_h */"
  },
  {
    "path": "Demo/SwiftDemo/SwiftDemo/TestObject.swift",
    "content": "//\n//  TestObject.swift\n//  SwiftDemo\n//\n//  Created by jspatch on 16/2/3.\n//  Copyright © 2016年 Arlen. All rights reserved.\n//\n\nimport Foundation\n\n/**\n After XCode 7.0(could be Swift 2.2), the Swift Class can not be marked using @objc,\n and it can't be use in objc rumtime directly. \n So if you want to use JSPatch in your project,\n you should declare all your Swift Classes inherited from NSObject\n \n https://forums.developer.apple.com/thread/11867\n */\n\nopen class TestObject: NSObject {\n    \n    /**\n     if your patch doesn't take effect, you should consider adding the dynamic attribute to the function\n     \n     http://stackoverflow.com/questions/25651081/method-swizzling-in-swift\n     \n     In production environment, I advise you to add the dynamic attribute to all your Custom Functions.\n     But you must know, this operation will reduce efficiency.\n     */\n    \n    dynamic func testLog() {\n        print(\"TestObject orig testLog\")\n    }\n}\n"
  },
  {
    "path": "Demo/SwiftDemo/SwiftDemo/ViewController.swift",
    "content": "//\n//  ViewController.swift\n//  SwiftDemo\n//\n//  Created by jspatch on 16/2/3.\n//  Copyright © 2016年 Arlen. All rights reserved.\n//\n\nimport UIKit\n\n//@objc(ViewController)\nclass ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {\n\n    @IBOutlet weak var tableView: UITableView!\n    \n    override func viewDidLoad() {\n        super.viewDidLoad()\n        // Do any additional setup after loading the view, typically from a nib.\n        \n        tableView.register(UITableViewCell.self, forCellReuseIdentifier: \"TableViewCell\")\n        \n        let testObject = TestObject()\n        testObject.testLog()\n        \n        self.testLog()\n    }\n    \n    /**\n     if your patch doesn't take effect, you should consider adding the dynamic attribute to the function\n     \n     http://stackoverflow.com/questions/25651081/method-swizzling-in-swift\n     \n     In production environment, I advise you to add the dynamic attribute to all your Custom Functions.\n     But you must know, this operation will reduce efficiency.\n     */\n    dynamic func testLog() {\n        print(\"ViewController orig testLog\")\n    }\n\n    override func didReceiveMemoryWarning() {\n        super.didReceiveMemoryWarning()\n        // Dispose of any resources that can be recreated.\n    }\n    \n    \n    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {\n        return 5\n    }\n    \n    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {\n        return 60\n    }\n    \n    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {\n        let cell = tableView.dequeueReusableCell(withIdentifier: \"TableViewCell\", for: indexPath)\n        cell.textLabel?.text = NSString(format: \"cell%d\", indexPath.row) as String;\n        return cell\n    }\n}\n\n"
  },
  {
    "path": "Demo/SwiftDemo/SwiftDemo/demo.js",
    "content": "defineClass('SwiftDemo.ViewController', {\n\tviewDidLoad: function() {\n\t\tconsole.log('js viewDidLoad begin')\n\t\tself.ORIGviewDidLoad()\n\t\tconsole.log('js viewDidLoad end')\n\t},\n\t\n\ttestLog: function() {\n\t\tconsole.log('js ViewController testlog')\n\t},\n\t\n\ttableView_numberOfRowsInSection: function(tableView, section) {\n\t\treturn 10\n\t}\n})\n\ndefineClass('SwiftDemo.TestObject', {\n\ttestLog: function() {\n\t\tconsole.log('js TestObject testlog')\n\t}\n})"
  },
  {
    "path": "Demo/SwiftDemo/SwiftDemo.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t3613C39A1C632AB400E915CB /* JPEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3981C632AB400E915CB /* JPEngine.m */; };\n\t\t3613C39B1C632AB400E915CB /* JSPatch.js in Resources */ = {isa = PBXBuildFile; fileRef = 3613C3991C632AB400E915CB /* JSPatch.js */; };\n\t\t3613C39E1C63387900E915CB /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3613C39D1C63387900E915CB /* JavaScriptCore.framework */; };\n\t\tDC5FA8C31C61F242007F1AA0 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC5FA8C21C61F242007F1AA0 /* AppDelegate.swift */; };\n\t\tDC5FA8C51C61F242007F1AA0 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC5FA8C41C61F242007F1AA0 /* ViewController.swift */; };\n\t\tDC5FA8C81C61F242007F1AA0 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DC5FA8C61C61F242007F1AA0 /* Main.storyboard */; };\n\t\tDC5FA8CA1C61F242007F1AA0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DC5FA8C91C61F242007F1AA0 /* Assets.xcassets */; };\n\t\tDC5FA8CD1C61F242007F1AA0 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DC5FA8CB1C61F242007F1AA0 /* LaunchScreen.storyboard */; };\n\t\tDC5FA8D51C61F732007F1AA0 /* demo.js in Resources */ = {isa = PBXBuildFile; fileRef = DC5FA8D41C61F732007F1AA0 /* demo.js */; };\n\t\tDC5FA8D71C61FD74007F1AA0 /* TestObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC5FA8D61C61FD74007F1AA0 /* TestObject.swift */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXFileReference section */\n\t\t3613C3971C632AB400E915CB /* JPEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPEngine.h; sourceTree = \"<group>\"; };\n\t\t3613C3981C632AB400E915CB /* JPEngine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPEngine.m; sourceTree = \"<group>\"; };\n\t\t3613C3991C632AB400E915CB /* JSPatch.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = JSPatch.js; sourceTree = \"<group>\"; };\n\t\t3613C39C1C63344D00E915CB /* SwiftDemo-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = \"SwiftDemo-Bridging-Header.h\"; sourceTree = \"<group>\"; };\n\t\t3613C39D1C63387900E915CB /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };\n\t\tDC5FA8BF1C61F242007F1AA0 /* SwiftDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tDC5FA8C21C61F242007F1AA0 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = \"<group>\"; };\n\t\tDC5FA8C41C61F242007F1AA0 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = \"<group>\"; };\n\t\tDC5FA8C71C61F242007F1AA0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = \"<group>\"; };\n\t\tDC5FA8C91C61F242007F1AA0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = \"<group>\"; };\n\t\tDC5FA8CC1C61F242007F1AA0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = \"<group>\"; };\n\t\tDC5FA8CE1C61F242007F1AA0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\tDC5FA8D41C61F732007F1AA0 /* demo.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = demo.js; sourceTree = \"<group>\"; };\n\t\tDC5FA8D61C61FD74007F1AA0 /* TestObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestObject.swift; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\tDC5FA8BC1C61F242007F1AA0 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t3613C39E1C63387900E915CB /* JavaScriptCore.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t1559087F26CA089030BE8522 /* Frameworks */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3613C39D1C63387900E915CB /* JavaScriptCore.framework */,\n\t\t\t);\n\t\t\tname = Frameworks;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t3613C3961C632AB400E915CB /* JSPatch */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3613C3971C632AB400E915CB /* JPEngine.h */,\n\t\t\t\t3613C3981C632AB400E915CB /* JPEngine.m */,\n\t\t\t\t3613C3991C632AB400E915CB /* JSPatch.js */,\n\t\t\t);\n\t\t\tname = JSPatch;\n\t\t\tpath = ../../../JSPatch;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDC5FA8B61C61F242007F1AA0 = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tDC5FA8C11C61F242007F1AA0 /* SwiftDemo */,\n\t\t\t\tDC5FA8C01C61F242007F1AA0 /* Products */,\n\t\t\t\t1559087F26CA089030BE8522 /* Frameworks */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDC5FA8C01C61F242007F1AA0 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tDC5FA8BF1C61F242007F1AA0 /* SwiftDemo.app */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDC5FA8C11C61F242007F1AA0 /* SwiftDemo */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3613C3961C632AB400E915CB /* JSPatch */,\n\t\t\t\tDC5FA8C21C61F242007F1AA0 /* AppDelegate.swift */,\n\t\t\t\tDC5FA8C41C61F242007F1AA0 /* ViewController.swift */,\n\t\t\t\tDC5FA8C61C61F242007F1AA0 /* Main.storyboard */,\n\t\t\t\tDC5FA8C91C61F242007F1AA0 /* Assets.xcassets */,\n\t\t\t\tDC5FA8CB1C61F242007F1AA0 /* LaunchScreen.storyboard */,\n\t\t\t\tDC5FA8CE1C61F242007F1AA0 /* Info.plist */,\n\t\t\t\tDC5FA8D41C61F732007F1AA0 /* demo.js */,\n\t\t\t\tDC5FA8D61C61FD74007F1AA0 /* TestObject.swift */,\n\t\t\t\t3613C39C1C63344D00E915CB /* SwiftDemo-Bridging-Header.h */,\n\t\t\t);\n\t\t\tpath = SwiftDemo;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\tDC5FA8BE1C61F242007F1AA0 /* SwiftDemo */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = DC5FA8D11C61F242007F1AA0 /* Build configuration list for PBXNativeTarget \"SwiftDemo\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tDC5FA8BB1C61F242007F1AA0 /* Sources */,\n\t\t\t\tDC5FA8BC1C61F242007F1AA0 /* Frameworks */,\n\t\t\t\tDC5FA8BD1C61F242007F1AA0 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = SwiftDemo;\n\t\t\tproductName = SwiftDemo;\n\t\t\tproductReference = DC5FA8BF1C61F242007F1AA0 /* SwiftDemo.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\tDC5FA8B71C61F242007F1AA0 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastSwiftUpdateCheck = 0720;\n\t\t\t\tLastUpgradeCheck = 0720;\n\t\t\t\tORGANIZATIONNAME = Arlen;\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\tDC5FA8BE1C61F242007F1AA0 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.2.1;\n\t\t\t\t\t\tLastSwiftMigration = 0820;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = DC5FA8BA1C61F242007F1AA0 /* Build configuration list for PBXProject \"SwiftDemo\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = DC5FA8B61C61F242007F1AA0;\n\t\t\tproductRefGroup = DC5FA8C01C61F242007F1AA0 /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\tDC5FA8BE1C61F242007F1AA0 /* SwiftDemo */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\tDC5FA8BD1C61F242007F1AA0 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tDC5FA8CD1C61F242007F1AA0 /* LaunchScreen.storyboard in Resources */,\n\t\t\t\t3613C39B1C632AB400E915CB /* JSPatch.js in Resources */,\n\t\t\t\tDC5FA8CA1C61F242007F1AA0 /* Assets.xcassets in Resources */,\n\t\t\t\tDC5FA8C81C61F242007F1AA0 /* Main.storyboard in Resources */,\n\t\t\t\tDC5FA8D51C61F732007F1AA0 /* demo.js in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\tDC5FA8BB1C61F242007F1AA0 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tDC5FA8D71C61FD74007F1AA0 /* TestObject.swift in Sources */,\n\t\t\t\t3613C39A1C632AB400E915CB /* JPEngine.m in Sources */,\n\t\t\t\tDC5FA8C51C61F242007F1AA0 /* ViewController.swift in Sources */,\n\t\t\t\tDC5FA8C31C61F242007F1AA0 /* AppDelegate.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXVariantGroup section */\n\t\tDC5FA8C61C61F242007F1AA0 /* Main.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\tDC5FA8C71C61F242007F1AA0 /* Base */,\n\t\t\t);\n\t\t\tname = Main.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDC5FA8CB1C61F242007F1AA0 /* LaunchScreen.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\tDC5FA8CC1C61F242007F1AA0 /* Base */,\n\t\t\t);\n\t\t\tname = LaunchScreen.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\tDC5FA8CF1C61F242007F1AA0 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 9.2;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tDC5FA8D01C61F242007F1AA0 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 9.2;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tDC5FA8D21C61F242007F1AA0 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tINFOPLIST_FILE = SwiftDemo/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.jspatch.SwiftDemo;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"SwiftDemo/SwiftDemo-Bridging-Header.h\";\n\t\t\t\tSWIFT_VERSION = 3.0;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tDC5FA8D31C61F242007F1AA0 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tINFOPLIST_FILE = SwiftDemo/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.jspatch.SwiftDemo;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_OBJC_BRIDGING_HEADER = \"SwiftDemo/SwiftDemo-Bridging-Header.h\";\n\t\t\t\tSWIFT_VERSION = 3.0;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\tDC5FA8BA1C61F242007F1AA0 /* Build configuration list for PBXProject \"SwiftDemo\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tDC5FA8CF1C61F242007F1AA0 /* Debug */,\n\t\t\t\tDC5FA8D01C61F242007F1AA0 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tDC5FA8D11C61F242007F1AA0 /* Build configuration list for PBXNativeTarget \"SwiftDemo\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tDC5FA8D21C61F242007F1AA0 /* Debug */,\n\t\t\t\tDC5FA8D31C61F242007F1AA0 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = DC5FA8B71C61F242007F1AA0 /* Project object */;\n}\n"
  },
  {
    "path": "Demo/SwiftDemo/SwiftDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:SwiftDemo.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchDemo/AppDelegate.h",
    "content": "//\n//  AppDelegate.h\n//  JSPatch\n//\n//  Created by bang on 15/4/30.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface AppDelegate : UIResponder <UIApplicationDelegate>\n\n@property (strong, nonatomic) UIWindow *window;\n\n@end\n\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchDemo/AppDelegate.m",
    "content": "//\n//  AppDelegate.m\n//  JSPatch\n//\n//  Created by bang on 15/4/30.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import \"AppDelegate.h\"\n#import \"JPEngine.h\"\n#import \"JPViewController.h\"\n\n@implementation AppDelegate\n\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {\n    \n    [JPEngine startEngine];\n    NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@\"demo\" ofType:@\"js\"];\n    NSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil];\n    [JPEngine evaluateScript:script];\n    \n    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];\n    JPViewController *rootViewController = [[JPViewController alloc] init];\n    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];\n    self.window.rootViewController = navigationController;\n    [self.window makeKeyAndVisible];\n    \n    [[UINavigationBar appearance] setBackgroundImage:nil forBarMetrics:UIBarMetricsCompact];\n    return YES;\n}\n@end\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchDemo/JPViewController.h",
    "content": "//\n//  JPViewController.h\n//  JSPatch\n//\n//  Created by bang on 15/5/2.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface JPViewController : UIViewController\n@end\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchDemo/JPViewController.m",
    "content": "//\n//  JPViewController.m\n//  JSPatch\n//\n//  Created by bang on 15/5/2.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import \"JPViewController.h\"\n\n@implementation JPViewController\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 100, [UIScreen mainScreen].bounds.size.width, 50)];\n    [btn setTitle:@\"Push JPTableViewController\" forState:UIControlStateNormal];\n    [btn addTarget:self action:@selector(handleBtn:) forControlEvents:UIControlEventTouchUpInside];\n    [btn setBackgroundColor:[UIColor grayColor]];\n    [self.view addSubview:btn];\n}\n\n- (void)handleBtn:(id)sender\n{\n}\n\n@end\n\n\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchDemo/Supporting Files/Images.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"60x60\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"60x60\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"76x76\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"76x76\",\n      \"scale\" : \"2x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Demo/iOSDemo/JSPatchDemo/Supporting Files/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>net.cnbang.$(PRODUCT_NAME:rfc1034identifier)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n\t<key>LSRequiresIPhoneOS</key>\n\t<true/>\n\t<key>NSAppTransportSecurity</key>\n\t<dict>\n\t\t<key>NSAllowsArbitraryLoads</key>\n\t\t<true/>\n\t</dict>\n\t<key>UIRequiredDeviceCapabilities</key>\n\t<array>\n\t\t<string>armv7</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations~ipad</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationPortraitUpsideDown</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchDemo/Supporting Files/main.m",
    "content": "//\n//  main.m\n//  JSPatch\n//\n//  Created by bang on 15/4/30.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n#import \"AppDelegate.h\"\n\nint main(int argc, char * argv[]) {\n    @autoreleasepool {\n        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));\n    }\n}\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchDemo/demo.js",
    "content": "defineClass('JPViewController', {\n  handleBtn: function(sender) {\n    var tableViewCtrl = JPTableViewController.alloc().init()\n    self.navigationController().pushViewController_animated(tableViewCtrl, YES)\n  }\n})\n\ndefineClass('JPTableViewController : UITableViewController <UIAlertViewDelegate>', ['data'], {\n  dataSource: function() {\n    var data = self.data();\n    if (data) return data;\n    var data = [];\n    for (var i = 0; i < 20; i ++) {\n      data.push(\"cell from js \" + i);\n    }\n    self.setData(data)\n    return data;\n  },\n  numberOfSectionsInTableView: function(tableView) {\n    return 1;\n  },\n  tableView_numberOfRowsInSection: function(tableView, section) {\n    return self.dataSource().length;\n  },\n  tableView_cellForRowAtIndexPath: function(tableView, indexPath) {\n    var cell = tableView.dequeueReusableCellWithIdentifier(\"cell\") \n    if (!cell) {\n      cell = require('UITableViewCell').alloc().initWithStyle_reuseIdentifier(0, \"cell\")\n    }\n    cell.textLabel().setText(self.dataSource()[indexPath.row()])\n    return cell\n  },\n  tableView_heightForRowAtIndexPath: function(tableView, indexPath) {\n    return 60\n  },\n  tableView_didSelectRowAtIndexPath: function(tableView, indexPath) {\n     var alertView = require('UIAlertView').alloc().initWithTitle_message_delegate_cancelButtonTitle_otherButtonTitles(\"Alert\",self.dataSource()[indexPath.row()], self, \"OK\",  null);\n     alertView.show()\n  },\n  alertView_willDismissWithButtonIndex: function(alertView, idx) {\n    console.log('click btn ' + alertView.buttonTitleAtIndex(idx).toJS())\n  }\n})"
  },
  {
    "path": "Demo/iOSDemo/JSPatchDemo.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t2D0DF7071B22F75C005695DA /* inheritTest.js in Resources */ = {isa = PBXBuildFile; fileRef = 2D0DF7061B22F75C005695DA /* inheritTest.js */; };\n\t\t2D5D89211B0B8BFF009382EC /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D5D89181B0B8BFF009382EC /* AppDelegate.m */; };\n\t\t2D5D89251B0B8BFF009382EC /* JPViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D5D891E1B0B8BFF009382EC /* JPViewController.m */; };\n\t\t2D6D12FD1B0B8CF20095A435 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2D6D12FA1B0B8CF20095A435 /* Images.xcassets */; };\n\t\t2D6D12FF1B0B8CF20095A435 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D6D12FC1B0B8CF20095A435 /* main.m */; };\n\t\t2D6D13011B0B8CFF0095A435 /* demo.js in Resources */ = {isa = PBXBuildFile; fileRef = 2D6D13001B0B8CFF0095A435 /* demo.js */; };\n\t\t2DA3C42B206A1892005877CB /* newBlockTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 2DA3C42A206A1892005877CB /* newBlockTest.m */; };\n\t\t2DA3C434206B5569005877CB /* newBlockTest.js in Resources */ = {isa = PBXBuildFile; fileRef = 2DA3C433206B5569005877CB /* newBlockTest.js */; };\n\t\t360BCF4E1D82DCFC00202977 /* JPDispatch.m in Sources */ = {isa = PBXBuildFile; fileRef = 360BCF4D1D82DCFC00202977 /* JPDispatch.m */; };\n\t\t360BCF541D82EFCD00202977 /* JPProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 360BCF531D82EFCD00202977 /* JPProtocol.m */; };\n\t\t3613C3861C6329F300E915CB /* JPEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3611C6329F300E915CB /* JPEngine.m */; };\n\t\t3613C3871C6329F300E915CB /* JSPatch.js in Resources */ = {isa = PBXBuildFile; fileRef = 3613C3621C6329F300E915CB /* JSPatch.js */; };\n\t\t3613C3881C6329F300E915CB /* JPLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3651C6329F300E915CB /* JPLoader.m */; };\n\t\t3613C3891C6329F300E915CB /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3691C6329F300E915CB /* ioapi.c */; };\n\t\t3613C38A1C6329F300E915CB /* mztools.c in Sources */ = {isa = PBXBuildFile; fileRef = 3613C36B1C6329F300E915CB /* mztools.c */; };\n\t\t3613C38B1C6329F300E915CB /* unzip.c in Sources */ = {isa = PBXBuildFile; fileRef = 3613C36D1C6329F300E915CB /* unzip.c */; };\n\t\t3613C38C1C6329F300E915CB /* zip.c in Sources */ = {isa = PBXBuildFile; fileRef = 3613C36F1C6329F300E915CB /* zip.c */; };\n\t\t3613C38D1C6329F300E915CB /* RSA.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3721C6329F300E915CB /* RSA.m */; };\n\t\t3613C38E1C6329F300E915CB /* ZipArchive.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3741C6329F300E915CB /* ZipArchive.m */; };\n\t\t3613C38F1C6329F300E915CB /* packer.php in Resources */ = {isa = PBXBuildFile; fileRef = 3613C3761C6329F300E915CB /* packer.php */; };\n\t\t3613C3AF1C6346F500E915CB /* JPCleaner.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3AE1C6346F500E915CB /* JPCleaner.m */; };\n\t\t3646F8B41CA0F89C00E10774 /* JPLocker.m in Sources */ = {isa = PBXBuildFile; fileRef = 3646F8B31CA0F89C00E10774 /* JPLocker.m */; };\n\t\t3660BC2D1E2634C900DB3765 /* JPBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 3660BC2C1E2634C900DB3765 /* JPBlock.m */; };\n\t\t367650481E2CC3BD00828E12 /* JPBlockWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 367650471E2CC3BD00828E12 /* JPBlockWrapper.m */; };\n\t\t3694925F1CFEFE42003F44CA /* JPCFunctionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 3694925D1CFEFE42003F44CA /* JPCFunctionTest.m */; };\n\t\t369492601CFEFE42003F44CA /* jsCFunctionTest.js in Resources */ = {isa = PBXBuildFile; fileRef = 3694925E1CFEFE42003F44CA /* jsCFunctionTest.js */; };\n\t\t369EC2971C9925A400334A64 /* JPSpecialInit.m in Sources */ = {isa = PBXBuildFile; fileRef = 369EC2961C9925A400334A64 /* JPSpecialInit.m */; };\n\t\t36B3252D1E290D0C006945DF /* JPMethodSignature.m in Sources */ = {isa = PBXBuildFile; fileRef = 36B3252C1E290D0C006945DF /* JPMethodSignature.m */; };\n\t\t36C59D611E4B517B00A40835 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 36C59D601E4B517B00A40835 /* libffi.a */; };\n\t\t36CC3A4B1CFEE6A80001465B /* JPCFunction.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A151CFEE6A80001465B /* JPCFunction.m */; };\n\t\t36CC3A4C1CFEE6A80001465B /* JPMemory.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A171CFEE6A80001465B /* JPMemory.m */; };\n\t\t36CC3A4D1CFEE6A80001465B /* JPStructPointer.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A191CFEE6A80001465B /* JPStructPointer.m */; };\n\t\t36CC3A4F1CFEE6A80001465B /* JPCGBitmapContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A331CFEE6A80001465B /* JPCGBitmapContext.m */; };\n\t\t36CC3A501CFEE6A80001465B /* JPCGColor.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A351CFEE6A80001465B /* JPCGColor.m */; };\n\t\t36CC3A511CFEE6A80001465B /* JPCGContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A371CFEE6A80001465B /* JPCGContext.m */; };\n\t\t36CC3A521CFEE6A80001465B /* JPCGGeometry.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A391CFEE6A80001465B /* JPCGGeometry.m */; };\n\t\t36CC3A531CFEE6A80001465B /* JPCGImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A3B1CFEE6A80001465B /* JPCGImage.m */; };\n\t\t36CC3A541CFEE6A80001465B /* JPCGPath.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A3D1CFEE6A80001465B /* JPCGPath.m */; };\n\t\t36CC3A551CFEE6A80001465B /* JPCGTransform.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A3F1CFEE6A80001465B /* JPCGTransform.m */; };\n\t\t36CC3A561CFEE6A80001465B /* JPCoreGraphics.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A411CFEE6A80001465B /* JPCoreGraphics.m */; };\n\t\t36CC3A571CFEE6A80001465B /* JPUIGeometry.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A441CFEE6A80001465B /* JPUIGeometry.m */; };\n\t\t36CC3A581CFEE6A80001465B /* JPUIGraphics.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A461CFEE6A80001465B /* JPUIGraphics.m */; };\n\t\t36CC3A591CFEE6A80001465B /* JPUIImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A481CFEE6A80001465B /* JPUIImage.m */; };\n\t\t36CC3A5A1CFEE6A80001465B /* JPUIKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CC3A4A1CFEE6A80001465B /* JPUIKit.m */; };\n\t\t36CE191B1CAEA179007D73AC /* jsClassTest.js in Resources */ = {isa = PBXBuildFile; fileRef = 36CE191A1CAEA179007D73AC /* jsClassTest.js */; };\n\t\t36CE191E1CAEA1DE007D73AC /* JPJSClassTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CE191D1CAEA1DE007D73AC /* JPJSClassTest.m */; };\n\t\t36CE19251CB3E709007D73AC /* JPPerformanceTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 36CE19241CB3E709007D73AC /* JPPerformanceTest.m */; };\n\t\t36CE19271CB3E72B007D73AC /* performanceTest.js in Resources */ = {isa = PBXBuildFile; fileRef = 36CE19261CB3E72B007D73AC /* performanceTest.js */; };\n\t\t36F0DCC61BFAF41C0090EA4A /* libz.1.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 36F0DCC51BFAF41C0090EA4A /* libz.1.dylib */; };\n\t\t4F9EBFC51D50745200EC72C1 /* JPNumber.m in Sources */ = {isa = PBXBuildFile; fileRef = 4F9EBFC41D50745200EC72C1 /* JPNumber.m */; };\n\t\t4F9EBFC91D50749200EC72C1 /* JPNumberTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 4F9EBFC71D50749200EC72C1 /* JPNumberTest.m */; };\n\t\t4F9EBFCA1D50749200EC72C1 /* jsNumberTest.js in Resources */ = {isa = PBXBuildFile; fileRef = 4F9EBFC81D50749200EC72C1 /* jsNumberTest.js */; };\n\t\t6C6CAC741C5F0BCA00444348 /* superTest.js in Resources */ = {isa = PBXBuildFile; fileRef = 6C6CAC721C5F0BCA00444348 /* superTest.js */; };\n\t\t6C6CAC751C5F0BCA00444348 /* JPSuperTestObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C6CAC731C5F0BCA00444348 /* JPSuperTestObject.m */; };\n\t\t6C72B7961C352BA80086C98D /* newProtocolTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C72B7951C352BA80086C98D /* newProtocolTest.m */; };\n\t\t6C9C0EE41C25A7C700FCAAC5 /* newProtocolTest.js in Resources */ = {isa = PBXBuildFile; fileRef = 6C9C0EE31C25A7C700FCAAC5 /* newProtocolTest.js */; };\n\t\t6C9C0EE51C25A7DA00FCAAC5 /* newProtocolTest.js in Resources */ = {isa = PBXBuildFile; fileRef = 6C9C0EE31C25A7C700FCAAC5 /* newProtocolTest.js */; };\n\t\tDE58B6481B7C312800F64C63 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DE58B6471B7C312800F64C63 /* JavaScriptCore.framework */; settings = {ATTRIBUTES = (Weak, ); }; };\n\t\tDE6FFF031B42B01C0005EE83 /* protocolTest.js in Resources */ = {isa = PBXBuildFile; fileRef = DE6FFF021B42B01C0005EE83 /* protocolTest.js */; };\n\t\tDE6FFF051B42C25D0005EE83 /* protocolTest.js in Resources */ = {isa = PBXBuildFile; fileRef = DE6FFF021B42B01C0005EE83 /* protocolTest.js */; };\n\t\tDE94AE2B1AF246C000E461D4 /* JSPatchTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DE94AE2A1AF246C000E461D4 /* JSPatchTests.m */; };\n\t\tDE94AE461AF2480000E461D4 /* JPTestObject.m in Sources */ = {isa = PBXBuildFile; fileRef = DE94AE441AF2480000E461D4 /* JPTestObject.m */; };\n\t\tDE94AE471AF2480000E461D4 /* test.js in Resources */ = {isa = PBXBuildFile; fileRef = DE94AE451AF2480000E461D4 /* test.js */; };\n\t\tE1B89EA01B203482000645C2 /* JPMultithreadTestObject.m in Sources */ = {isa = PBXBuildFile; fileRef = E1B89E9F1B203482000645C2 /* JPMultithreadTestObject.m */; };\n\t\tE1B89EA31B218986000645C2 /* JPInheritanceTestObjects.m in Sources */ = {isa = PBXBuildFile; fileRef = E1B89EA21B218986000645C2 /* JPInheritanceTestObjects.m */; };\n\t\tE1B89EAE1B228818000645C2 /* multithreadTest.js in Resources */ = {isa = PBXBuildFile; fileRef = E1B89EAD1B228818000645C2 /* multithreadTest.js */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\tDE94AE251AF246C000E461D4 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = DE94AE031AF246BF00E461D4 /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = DE94AE0A1AF246BF00E461D4;\n\t\t\tremoteInfo = JSPatch;\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXFileReference section */\n\t\t2D0DF7061B22F75C005695DA /* inheritTest.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = inheritTest.js; sourceTree = \"<group>\"; };\n\t\t2D5D89171B0B8BFF009382EC /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = \"<group>\"; };\n\t\t2D5D89181B0B8BFF009382EC /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = \"<group>\"; };\n\t\t2D5D891D1B0B8BFF009382EC /* JPViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPViewController.h; sourceTree = \"<group>\"; };\n\t\t2D5D891E1B0B8BFF009382EC /* JPViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPViewController.m; sourceTree = \"<group>\"; };\n\t\t2D6D12FA1B0B8CF20095A435 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = \"<group>\"; };\n\t\t2D6D12FB1B0B8CF20095A435 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t2D6D12FC1B0B8CF20095A435 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = \"<group>\"; };\n\t\t2D6D13001B0B8CFF0095A435 /* demo.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = demo.js; sourceTree = \"<group>\"; };\n\t\t2DA3C429206A1892005877CB /* newBlockTest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = newBlockTest.h; sourceTree = \"<group>\"; };\n\t\t2DA3C42A206A1892005877CB /* newBlockTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = newBlockTest.m; sourceTree = \"<group>\"; };\n\t\t2DA3C433206B5569005877CB /* newBlockTest.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = newBlockTest.js; sourceTree = \"<group>\"; };\n\t\t360BCF4C1D82DCFC00202977 /* JPDispatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPDispatch.h; sourceTree = \"<group>\"; };\n\t\t360BCF4D1D82DCFC00202977 /* JPDispatch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPDispatch.m; sourceTree = \"<group>\"; };\n\t\t360BCF521D82EFCD00202977 /* JPProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPProtocol.h; sourceTree = \"<group>\"; };\n\t\t360BCF531D82EFCD00202977 /* JPProtocol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPProtocol.m; sourceTree = \"<group>\"; };\n\t\t3613C3601C6329F300E915CB /* JPEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPEngine.h; sourceTree = \"<group>\"; };\n\t\t3613C3611C6329F300E915CB /* JPEngine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPEngine.m; sourceTree = \"<group>\"; };\n\t\t3613C3621C6329F300E915CB /* JSPatch.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = JSPatch.js; sourceTree = \"<group>\"; };\n\t\t3613C3641C6329F300E915CB /* JPLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPLoader.h; sourceTree = \"<group>\"; };\n\t\t3613C3651C6329F300E915CB /* JPLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPLoader.m; sourceTree = \"<group>\"; };\n\t\t3613C3681C6329F300E915CB /* crypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypt.h; sourceTree = \"<group>\"; };\n\t\t3613C3691C6329F300E915CB /* ioapi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioapi.c; sourceTree = \"<group>\"; };\n\t\t3613C36A1C6329F300E915CB /* ioapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ioapi.h; sourceTree = \"<group>\"; };\n\t\t3613C36B1C6329F300E915CB /* mztools.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mztools.c; sourceTree = \"<group>\"; };\n\t\t3613C36C1C6329F300E915CB /* mztools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mztools.h; sourceTree = \"<group>\"; };\n\t\t3613C36D1C6329F300E915CB /* unzip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = unzip.c; sourceTree = \"<group>\"; };\n\t\t3613C36E1C6329F300E915CB /* unzip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unzip.h; sourceTree = \"<group>\"; };\n\t\t3613C36F1C6329F300E915CB /* zip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip.c; sourceTree = \"<group>\"; };\n\t\t3613C3701C6329F300E915CB /* zip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zip.h; sourceTree = \"<group>\"; };\n\t\t3613C3711C6329F300E915CB /* RSA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RSA.h; sourceTree = \"<group>\"; };\n\t\t3613C3721C6329F300E915CB /* RSA.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RSA.m; sourceTree = \"<group>\"; };\n\t\t3613C3731C6329F300E915CB /* ZipArchive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZipArchive.h; sourceTree = \"<group>\"; };\n\t\t3613C3741C6329F300E915CB /* ZipArchive.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZipArchive.m; sourceTree = \"<group>\"; };\n\t\t3613C3761C6329F300E915CB /* packer.php */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.php; path = packer.php; sourceTree = \"<group>\"; };\n\t\t3613C3AD1C6346F500E915CB /* JPCleaner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCleaner.h; sourceTree = \"<group>\"; };\n\t\t3613C3AE1C6346F500E915CB /* JPCleaner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCleaner.m; sourceTree = \"<group>\"; };\n\t\t3646F8B21CA0F89C00E10774 /* JPLocker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPLocker.h; sourceTree = \"<group>\"; };\n\t\t3646F8B31CA0F89C00E10774 /* JPLocker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPLocker.m; sourceTree = \"<group>\"; };\n\t\t3660BC2B1E2634C900DB3765 /* JPBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPBlock.h; sourceTree = \"<group>\"; };\n\t\t3660BC2C1E2634C900DB3765 /* JPBlock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPBlock.m; sourceTree = \"<group>\"; };\n\t\t367650461E2CC3BD00828E12 /* JPBlockWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPBlockWrapper.h; sourceTree = \"<group>\"; };\n\t\t367650471E2CC3BD00828E12 /* JPBlockWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPBlockWrapper.m; sourceTree = \"<group>\"; };\n\t\t3694925C1CFEFE42003F44CA /* JPCFunctionTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCFunctionTest.h; sourceTree = \"<group>\"; };\n\t\t3694925D1CFEFE42003F44CA /* JPCFunctionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCFunctionTest.m; sourceTree = \"<group>\"; };\n\t\t3694925E1CFEFE42003F44CA /* jsCFunctionTest.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = jsCFunctionTest.js; sourceTree = \"<group>\"; };\n\t\t369EC2951C9925A400334A64 /* JPSpecialInit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPSpecialInit.h; sourceTree = \"<group>\"; };\n\t\t369EC2961C9925A400334A64 /* JPSpecialInit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPSpecialInit.m; sourceTree = \"<group>\"; };\n\t\t36B3252B1E290D0C006945DF /* JPMethodSignature.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPMethodSignature.h; sourceTree = \"<group>\"; };\n\t\t36B3252C1E290D0C006945DF /* JPMethodSignature.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPMethodSignature.m; sourceTree = \"<group>\"; };\n\t\t36C59D561E4B517B00A40835 /* ffi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi.h; sourceTree = \"<group>\"; };\n\t\t36C59D571E4B517B00A40835 /* ffi_arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_arm.h; sourceTree = \"<group>\"; };\n\t\t36C59D581E4B517B00A40835 /* ffi_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_arm64.h; sourceTree = \"<group>\"; };\n\t\t36C59D591E4B517B00A40835 /* ffi_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_i386.h; sourceTree = \"<group>\"; };\n\t\t36C59D5A1E4B517B00A40835 /* ffi_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_x86_64.h; sourceTree = \"<group>\"; };\n\t\t36C59D5B1E4B517B00A40835 /* ffitarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget.h; sourceTree = \"<group>\"; };\n\t\t36C59D5C1E4B517B00A40835 /* ffitarget_arm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_arm.h; sourceTree = \"<group>\"; };\n\t\t36C59D5D1E4B517B00A40835 /* ffitarget_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_arm64.h; sourceTree = \"<group>\"; };\n\t\t36C59D5E1E4B517B00A40835 /* ffitarget_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_i386.h; sourceTree = \"<group>\"; };\n\t\t36C59D5F1E4B517B00A40835 /* ffitarget_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_x86_64.h; sourceTree = \"<group>\"; };\n\t\t36C59D601E4B517B00A40835 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = \"<group>\"; };\n\t\t36CC3A141CFEE6A80001465B /* JPCFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCFunction.h; sourceTree = \"<group>\"; };\n\t\t36CC3A151CFEE6A80001465B /* JPCFunction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCFunction.m; sourceTree = \"<group>\"; };\n\t\t36CC3A161CFEE6A80001465B /* JPMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPMemory.h; sourceTree = \"<group>\"; };\n\t\t36CC3A171CFEE6A80001465B /* JPMemory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPMemory.m; sourceTree = \"<group>\"; };\n\t\t36CC3A181CFEE6A80001465B /* JPStructPointer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPStructPointer.h; sourceTree = \"<group>\"; };\n\t\t36CC3A191CFEE6A80001465B /* JPStructPointer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPStructPointer.m; sourceTree = \"<group>\"; };\n\t\t36CC3A321CFEE6A80001465B /* JPCGBitmapContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGBitmapContext.h; sourceTree = \"<group>\"; };\n\t\t36CC3A331CFEE6A80001465B /* JPCGBitmapContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGBitmapContext.m; sourceTree = \"<group>\"; };\n\t\t36CC3A341CFEE6A80001465B /* JPCGColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGColor.h; sourceTree = \"<group>\"; };\n\t\t36CC3A351CFEE6A80001465B /* JPCGColor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGColor.m; sourceTree = \"<group>\"; };\n\t\t36CC3A361CFEE6A80001465B /* JPCGContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGContext.h; sourceTree = \"<group>\"; };\n\t\t36CC3A371CFEE6A80001465B /* JPCGContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGContext.m; sourceTree = \"<group>\"; };\n\t\t36CC3A381CFEE6A80001465B /* JPCGGeometry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGGeometry.h; sourceTree = \"<group>\"; };\n\t\t36CC3A391CFEE6A80001465B /* JPCGGeometry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGGeometry.m; sourceTree = \"<group>\"; };\n\t\t36CC3A3A1CFEE6A80001465B /* JPCGImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGImage.h; sourceTree = \"<group>\"; };\n\t\t36CC3A3B1CFEE6A80001465B /* JPCGImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGImage.m; sourceTree = \"<group>\"; };\n\t\t36CC3A3C1CFEE6A80001465B /* JPCGPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGPath.h; sourceTree = \"<group>\"; };\n\t\t36CC3A3D1CFEE6A80001465B /* JPCGPath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGPath.m; sourceTree = \"<group>\"; };\n\t\t36CC3A3E1CFEE6A80001465B /* JPCGTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGTransform.h; sourceTree = \"<group>\"; };\n\t\t36CC3A3F1CFEE6A80001465B /* JPCGTransform.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGTransform.m; sourceTree = \"<group>\"; };\n\t\t36CC3A401CFEE6A80001465B /* JPCoreGraphics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCoreGraphics.h; sourceTree = \"<group>\"; };\n\t\t36CC3A411CFEE6A80001465B /* JPCoreGraphics.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCoreGraphics.m; sourceTree = \"<group>\"; };\n\t\t36CC3A431CFEE6A80001465B /* JPUIGeometry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPUIGeometry.h; sourceTree = \"<group>\"; };\n\t\t36CC3A441CFEE6A80001465B /* JPUIGeometry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPUIGeometry.m; sourceTree = \"<group>\"; };\n\t\t36CC3A451CFEE6A80001465B /* JPUIGraphics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPUIGraphics.h; sourceTree = \"<group>\"; };\n\t\t36CC3A461CFEE6A80001465B /* JPUIGraphics.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPUIGraphics.m; sourceTree = \"<group>\"; };\n\t\t36CC3A471CFEE6A80001465B /* JPUIImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPUIImage.h; sourceTree = \"<group>\"; };\n\t\t36CC3A481CFEE6A80001465B /* JPUIImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPUIImage.m; sourceTree = \"<group>\"; };\n\t\t36CC3A491CFEE6A80001465B /* JPUIKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPUIKit.h; sourceTree = \"<group>\"; };\n\t\t36CC3A4A1CFEE6A80001465B /* JPUIKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPUIKit.m; sourceTree = \"<group>\"; };\n\t\t36CE191A1CAEA179007D73AC /* jsClassTest.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = jsClassTest.js; sourceTree = \"<group>\"; };\n\t\t36CE191C1CAEA1DE007D73AC /* JPJSClassTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPJSClassTest.h; sourceTree = \"<group>\"; };\n\t\t36CE191D1CAEA1DE007D73AC /* JPJSClassTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPJSClassTest.m; sourceTree = \"<group>\"; };\n\t\t36CE19231CB3E709007D73AC /* JPPerformanceTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPPerformanceTest.h; sourceTree = \"<group>\"; };\n\t\t36CE19241CB3E709007D73AC /* JPPerformanceTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPPerformanceTest.m; sourceTree = \"<group>\"; };\n\t\t36CE19261CB3E72B007D73AC /* performanceTest.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = performanceTest.js; sourceTree = \"<group>\"; };\n\t\t36F0DCC51BFAF41C0090EA4A /* libz.1.dylib */ = {isa = PBXFileReference; lastKnownFileType = \"compiled.mach-o.dylib\"; name = libz.1.dylib; path = ../../../../../../usr/lib/libz.1.dylib; sourceTree = \"<group>\"; };\n\t\t4F9EBFC31D50745200EC72C1 /* JPNumber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPNumber.h; sourceTree = \"<group>\"; };\n\t\t4F9EBFC41D50745200EC72C1 /* JPNumber.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPNumber.m; sourceTree = \"<group>\"; };\n\t\t4F9EBFC61D50749200EC72C1 /* JPNumberTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPNumberTest.h; sourceTree = \"<group>\"; };\n\t\t4F9EBFC71D50749200EC72C1 /* JPNumberTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPNumberTest.m; sourceTree = \"<group>\"; };\n\t\t4F9EBFC81D50749200EC72C1 /* jsNumberTest.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = jsNumberTest.js; sourceTree = \"<group>\"; };\n\t\t6C6CAC711C5F0BCA00444348 /* JPSuperTestObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPSuperTestObject.h; sourceTree = \"<group>\"; };\n\t\t6C6CAC721C5F0BCA00444348 /* superTest.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = superTest.js; sourceTree = \"<group>\"; };\n\t\t6C6CAC731C5F0BCA00444348 /* JPSuperTestObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPSuperTestObject.m; sourceTree = \"<group>\"; };\n\t\t6C72B7941C352BA80086C98D /* newProtocolTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = newProtocolTest.h; sourceTree = \"<group>\"; };\n\t\t6C72B7951C352BA80086C98D /* newProtocolTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = newProtocolTest.m; sourceTree = \"<group>\"; };\n\t\t6C9C0EE31C25A7C700FCAAC5 /* newProtocolTest.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = newProtocolTest.js; sourceTree = \"<group>\"; };\n\t\tDE58B6471B7C312800F64C63 /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };\n\t\tDE6FFF021B42B01C0005EE83 /* protocolTest.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = protocolTest.js; sourceTree = \"<group>\"; };\n\t\tDE94AE0B1AF246BF00E461D4 /* JSPatchDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JSPatchDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tDE94AE241AF246C000E461D4 /* JSPatchDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = JSPatchDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\tDE94AE291AF246C000E461D4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\tDE94AE2A1AF246C000E461D4 /* JSPatchTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JSPatchTests.m; sourceTree = \"<group>\"; };\n\t\tDE94AE431AF2480000E461D4 /* JPTestObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPTestObject.h; sourceTree = \"<group>\"; };\n\t\tDE94AE441AF2480000E461D4 /* JPTestObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPTestObject.m; sourceTree = \"<group>\"; };\n\t\tDE94AE451AF2480000E461D4 /* test.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = test.js; sourceTree = \"<group>\"; };\n\t\tE1B89E9E1B203482000645C2 /* JPMultithreadTestObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPMultithreadTestObject.h; sourceTree = \"<group>\"; };\n\t\tE1B89E9F1B203482000645C2 /* JPMultithreadTestObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPMultithreadTestObject.m; sourceTree = \"<group>\"; };\n\t\tE1B89EA11B218986000645C2 /* JPInheritanceTestObjects.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPInheritanceTestObjects.h; sourceTree = \"<group>\"; };\n\t\tE1B89EA21B218986000645C2 /* JPInheritanceTestObjects.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPInheritanceTestObjects.m; sourceTree = \"<group>\"; };\n\t\tE1B89EAD1B228818000645C2 /* multithreadTest.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = multithreadTest.js; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\tDE94AE081AF246BF00E461D4 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t36F0DCC61BFAF41C0090EA4A /* libz.1.dylib in Frameworks */,\n\t\t\t\t36C59D611E4B517B00A40835 /* libffi.a in Frameworks */,\n\t\t\t\tDE58B6481B7C312800F64C63 /* JavaScriptCore.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tDE94AE211AF246C000E461D4 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t2D5D89161B0B8BFF009382EC /* JSPatchDemo */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3613C33E1C6329F300E915CB /* Extensions */,\n\t\t\t\t3613C35F1C6329F300E915CB /* JSPatch */,\n\t\t\t\t3613C3631C6329F300E915CB /* Loader */,\n\t\t\t\t2D6D12F91B0B8CF20095A435 /* Supporting Files */,\n\t\t\t\t2D5D89171B0B8BFF009382EC /* AppDelegate.h */,\n\t\t\t\t2D5D89181B0B8BFF009382EC /* AppDelegate.m */,\n\t\t\t\t2D5D891D1B0B8BFF009382EC /* JPViewController.h */,\n\t\t\t\t2D5D891E1B0B8BFF009382EC /* JPViewController.m */,\n\t\t\t\t2D6D13001B0B8CFF0095A435 /* demo.js */,\n\t\t\t);\n\t\t\tpath = JSPatchDemo;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t2D6D12F91B0B8CF20095A435 /* Supporting Files */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t2D6D12FA1B0B8CF20095A435 /* Images.xcassets */,\n\t\t\t\t2D6D12FB1B0B8CF20095A435 /* Info.plist */,\n\t\t\t\t2D6D12FC1B0B8CF20095A435 /* main.m */,\n\t\t\t);\n\t\t\tpath = \"Supporting Files\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t3613C33E1C6329F300E915CB /* Extensions */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t36B324F51E290CF3006945DF /* JPLibffi */,\n\t\t\t\t3660BC171E26327800DB3765 /* JPBlock */,\n\t\t\t\t36CC3A131CFEE6A80001465B /* JPCFunction */,\n\t\t\t\t36CC3A301CFEE6A80001465B /* JPCFunctionBinder */,\n\t\t\t\t369EC2951C9925A400334A64 /* JPSpecialInit.h */,\n\t\t\t\t369EC2961C9925A400334A64 /* JPSpecialInit.m */,\n\t\t\t\t3613C3AD1C6346F500E915CB /* JPCleaner.h */,\n\t\t\t\t3613C3AE1C6346F500E915CB /* JPCleaner.m */,\n\t\t\t\t3646F8B21CA0F89C00E10774 /* JPLocker.h */,\n\t\t\t\t3646F8B31CA0F89C00E10774 /* JPLocker.m */,\n\t\t\t\t4F9EBFC31D50745200EC72C1 /* JPNumber.h */,\n\t\t\t\t4F9EBFC41D50745200EC72C1 /* JPNumber.m */,\n\t\t\t\t360BCF4C1D82DCFC00202977 /* JPDispatch.h */,\n\t\t\t\t360BCF4D1D82DCFC00202977 /* JPDispatch.m */,\n\t\t\t\t360BCF521D82EFCD00202977 /* JPProtocol.h */,\n\t\t\t\t360BCF531D82EFCD00202977 /* JPProtocol.m */,\n\t\t\t);\n\t\t\tname = Extensions;\n\t\t\tpath = ../../../Extensions;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t3613C35F1C6329F300E915CB /* JSPatch */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3613C3601C6329F300E915CB /* JPEngine.h */,\n\t\t\t\t3613C3611C6329F300E915CB /* JPEngine.m */,\n\t\t\t\t3613C3621C6329F300E915CB /* JSPatch.js */,\n\t\t\t);\n\t\t\tname = JSPatch;\n\t\t\tpath = ../../../JSPatch;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t3613C3631C6329F300E915CB /* Loader */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3613C3641C6329F300E915CB /* JPLoader.h */,\n\t\t\t\t3613C3651C6329F300E915CB /* JPLoader.m */,\n\t\t\t\t3613C3661C6329F300E915CB /* libs */,\n\t\t\t\t3613C3751C6329F300E915CB /* tools */,\n\t\t\t);\n\t\t\tname = Loader;\n\t\t\tpath = ../../../Loader;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t3613C3661C6329F300E915CB /* libs */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3613C3671C6329F300E915CB /* minizip */,\n\t\t\t\t3613C3711C6329F300E915CB /* RSA.h */,\n\t\t\t\t3613C3721C6329F300E915CB /* RSA.m */,\n\t\t\t\t3613C3731C6329F300E915CB /* ZipArchive.h */,\n\t\t\t\t3613C3741C6329F300E915CB /* ZipArchive.m */,\n\t\t\t);\n\t\t\tpath = libs;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t3613C3671C6329F300E915CB /* minizip */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3613C3681C6329F300E915CB /* crypt.h */,\n\t\t\t\t3613C3691C6329F300E915CB /* ioapi.c */,\n\t\t\t\t3613C36A1C6329F300E915CB /* ioapi.h */,\n\t\t\t\t3613C36B1C6329F300E915CB /* mztools.c */,\n\t\t\t\t3613C36C1C6329F300E915CB /* mztools.h */,\n\t\t\t\t3613C36D1C6329F300E915CB /* unzip.c */,\n\t\t\t\t3613C36E1C6329F300E915CB /* unzip.h */,\n\t\t\t\t3613C36F1C6329F300E915CB /* zip.c */,\n\t\t\t\t3613C3701C6329F300E915CB /* zip.h */,\n\t\t\t);\n\t\t\tpath = minizip;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t3613C3751C6329F300E915CB /* tools */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3613C3761C6329F300E915CB /* packer.php */,\n\t\t\t);\n\t\t\tpath = tools;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t3660BC171E26327800DB3765 /* JPBlock */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3660BC2B1E2634C900DB3765 /* JPBlock.h */,\n\t\t\t\t3660BC2C1E2634C900DB3765 /* JPBlock.m */,\n\t\t\t\t367650461E2CC3BD00828E12 /* JPBlockWrapper.h */,\n\t\t\t\t367650471E2CC3BD00828E12 /* JPBlockWrapper.m */,\n\t\t\t);\n\t\t\tpath = JPBlock;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t36B324F51E290CF3006945DF /* JPLibffi */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t36C59D551E4B517B00A40835 /* libffi */,\n\t\t\t\t36B3252B1E290D0C006945DF /* JPMethodSignature.h */,\n\t\t\t\t36B3252C1E290D0C006945DF /* JPMethodSignature.m */,\n\t\t\t);\n\t\t\tpath = JPLibffi;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t36C59D551E4B517B00A40835 /* libffi */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t36C59D561E4B517B00A40835 /* ffi.h */,\n\t\t\t\t36C59D571E4B517B00A40835 /* ffi_arm.h */,\n\t\t\t\t36C59D581E4B517B00A40835 /* ffi_arm64.h */,\n\t\t\t\t36C59D591E4B517B00A40835 /* ffi_i386.h */,\n\t\t\t\t36C59D5A1E4B517B00A40835 /* ffi_x86_64.h */,\n\t\t\t\t36C59D5B1E4B517B00A40835 /* ffitarget.h */,\n\t\t\t\t36C59D5C1E4B517B00A40835 /* ffitarget_arm.h */,\n\t\t\t\t36C59D5D1E4B517B00A40835 /* ffitarget_arm64.h */,\n\t\t\t\t36C59D5E1E4B517B00A40835 /* ffitarget_i386.h */,\n\t\t\t\t36C59D5F1E4B517B00A40835 /* ffitarget_x86_64.h */,\n\t\t\t\t36C59D601E4B517B00A40835 /* libffi.a */,\n\t\t\t);\n\t\t\tpath = libffi;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t36CC3A131CFEE6A80001465B /* JPCFunction */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t36CC3A141CFEE6A80001465B /* JPCFunction.h */,\n\t\t\t\t36CC3A151CFEE6A80001465B /* JPCFunction.m */,\n\t\t\t\t36CC3A161CFEE6A80001465B /* JPMemory.h */,\n\t\t\t\t36CC3A171CFEE6A80001465B /* JPMemory.m */,\n\t\t\t\t36CC3A181CFEE6A80001465B /* JPStructPointer.h */,\n\t\t\t\t36CC3A191CFEE6A80001465B /* JPStructPointer.m */,\n\t\t\t);\n\t\t\tpath = JPCFunction;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t36CC3A301CFEE6A80001465B /* JPCFunctionBinder */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t36CC3A311CFEE6A80001465B /* CoreGraphics */,\n\t\t\t\t36CC3A421CFEE6A80001465B /* UIKit */,\n\t\t\t);\n\t\t\tpath = JPCFunctionBinder;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t36CC3A311CFEE6A80001465B /* CoreGraphics */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t36CC3A321CFEE6A80001465B /* JPCGBitmapContext.h */,\n\t\t\t\t36CC3A331CFEE6A80001465B /* JPCGBitmapContext.m */,\n\t\t\t\t36CC3A341CFEE6A80001465B /* JPCGColor.h */,\n\t\t\t\t36CC3A351CFEE6A80001465B /* JPCGColor.m */,\n\t\t\t\t36CC3A361CFEE6A80001465B /* JPCGContext.h */,\n\t\t\t\t36CC3A371CFEE6A80001465B /* JPCGContext.m */,\n\t\t\t\t36CC3A381CFEE6A80001465B /* JPCGGeometry.h */,\n\t\t\t\t36CC3A391CFEE6A80001465B /* JPCGGeometry.m */,\n\t\t\t\t36CC3A3A1CFEE6A80001465B /* JPCGImage.h */,\n\t\t\t\t36CC3A3B1CFEE6A80001465B /* JPCGImage.m */,\n\t\t\t\t36CC3A3C1CFEE6A80001465B /* JPCGPath.h */,\n\t\t\t\t36CC3A3D1CFEE6A80001465B /* JPCGPath.m */,\n\t\t\t\t36CC3A3E1CFEE6A80001465B /* JPCGTransform.h */,\n\t\t\t\t36CC3A3F1CFEE6A80001465B /* JPCGTransform.m */,\n\t\t\t\t36CC3A401CFEE6A80001465B /* JPCoreGraphics.h */,\n\t\t\t\t36CC3A411CFEE6A80001465B /* JPCoreGraphics.m */,\n\t\t\t);\n\t\t\tpath = CoreGraphics;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t36CC3A421CFEE6A80001465B /* UIKit */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t36CC3A431CFEE6A80001465B /* JPUIGeometry.h */,\n\t\t\t\t36CC3A441CFEE6A80001465B /* JPUIGeometry.m */,\n\t\t\t\t36CC3A451CFEE6A80001465B /* JPUIGraphics.h */,\n\t\t\t\t36CC3A461CFEE6A80001465B /* JPUIGraphics.m */,\n\t\t\t\t36CC3A471CFEE6A80001465B /* JPUIImage.h */,\n\t\t\t\t36CC3A481CFEE6A80001465B /* JPUIImage.m */,\n\t\t\t\t36CC3A491CFEE6A80001465B /* JPUIKit.h */,\n\t\t\t\t36CC3A4A1CFEE6A80001465B /* JPUIKit.m */,\n\t\t\t);\n\t\t\tpath = UIKit;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDE94AE021AF246BE00E461D4 = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t36F0DCC51BFAF41C0090EA4A /* libz.1.dylib */,\n\t\t\t\tDE58B6471B7C312800F64C63 /* JavaScriptCore.framework */,\n\t\t\t\t2D5D89161B0B8BFF009382EC /* JSPatchDemo */,\n\t\t\t\tDE94AE271AF246C000E461D4 /* JSPatchTests */,\n\t\t\t\tDE94AE0C1AF246BF00E461D4 /* Products */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDE94AE0C1AF246BF00E461D4 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tDE94AE0B1AF246BF00E461D4 /* JSPatchDemo.app */,\n\t\t\t\tDE94AE241AF246C000E461D4 /* JSPatchDemoTests.xctest */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDE94AE271AF246C000E461D4 /* JSPatchTests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t4F9EBFC61D50749200EC72C1 /* JPNumberTest.h */,\n\t\t\t\t4F9EBFC71D50749200EC72C1 /* JPNumberTest.m */,\n\t\t\t\t4F9EBFC81D50749200EC72C1 /* jsNumberTest.js */,\n\t\t\t\t3694925C1CFEFE42003F44CA /* JPCFunctionTest.h */,\n\t\t\t\t3694925D1CFEFE42003F44CA /* JPCFunctionTest.m */,\n\t\t\t\t3694925E1CFEFE42003F44CA /* jsCFunctionTest.js */,\n\t\t\t\t36CE191C1CAEA1DE007D73AC /* JPJSClassTest.h */,\n\t\t\t\t36CE191D1CAEA1DE007D73AC /* JPJSClassTest.m */,\n\t\t\t\t36CE191A1CAEA179007D73AC /* jsClassTest.js */,\n\t\t\t\t6C6CAC711C5F0BCA00444348 /* JPSuperTestObject.h */,\n\t\t\t\t6C6CAC731C5F0BCA00444348 /* JPSuperTestObject.m */,\n\t\t\t\t6C6CAC721C5F0BCA00444348 /* superTest.js */,\n\t\t\t\t36CE19231CB3E709007D73AC /* JPPerformanceTest.h */,\n\t\t\t\t36CE19241CB3E709007D73AC /* JPPerformanceTest.m */,\n\t\t\t\t36CE19261CB3E72B007D73AC /* performanceTest.js */,\n\t\t\t\t2DA3C429206A1892005877CB /* newBlockTest.h */,\n\t\t\t\t2DA3C42A206A1892005877CB /* newBlockTest.m */,\n\t\t\t\t2DA3C433206B5569005877CB /* newBlockTest.js */,\n\t\t\t\t6C72B7941C352BA80086C98D /* newProtocolTest.h */,\n\t\t\t\t6C72B7951C352BA80086C98D /* newProtocolTest.m */,\n\t\t\t\t6C9C0EE31C25A7C700FCAAC5 /* newProtocolTest.js */,\n\t\t\t\tE1B89E9E1B203482000645C2 /* JPMultithreadTestObject.h */,\n\t\t\t\tE1B89E9F1B203482000645C2 /* JPMultithreadTestObject.m */,\n\t\t\t\tDE94AE431AF2480000E461D4 /* JPTestObject.h */,\n\t\t\t\tDE94AE441AF2480000E461D4 /* JPTestObject.m */,\n\t\t\t\tE1B89EA11B218986000645C2 /* JPInheritanceTestObjects.h */,\n\t\t\t\tE1B89EA21B218986000645C2 /* JPInheritanceTestObjects.m */,\n\t\t\t\tDE6FFF021B42B01C0005EE83 /* protocolTest.js */,\n\t\t\t\t2D0DF7061B22F75C005695DA /* inheritTest.js */,\n\t\t\t\tDE94AE451AF2480000E461D4 /* test.js */,\n\t\t\t\tE1B89EAD1B228818000645C2 /* multithreadTest.js */,\n\t\t\t\tDE94AE2A1AF246C000E461D4 /* JSPatchTests.m */,\n\t\t\t\tDE94AE281AF246C000E461D4 /* Supporting Files */,\n\t\t\t);\n\t\t\tpath = JSPatchTests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDE94AE281AF246C000E461D4 /* Supporting Files */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\tDE94AE291AF246C000E461D4 /* Info.plist */,\n\t\t\t);\n\t\t\tname = \"Supporting Files\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\tDE94AE0A1AF246BF00E461D4 /* JSPatchDemo */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = DE94AE2E1AF246C000E461D4 /* Build configuration list for PBXNativeTarget \"JSPatchDemo\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tDE94AE071AF246BF00E461D4 /* Sources */,\n\t\t\t\tDE94AE081AF246BF00E461D4 /* Frameworks */,\n\t\t\t\tDE94AE091AF246BF00E461D4 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = JSPatchDemo;\n\t\t\tproductName = JSPatch;\n\t\t\tproductReference = DE94AE0B1AF246BF00E461D4 /* JSPatchDemo.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n\t\tDE94AE231AF246C000E461D4 /* JSPatchTests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = DE94AE311AF246C000E461D4 /* Build configuration list for PBXNativeTarget \"JSPatchTests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\tDE94AE201AF246C000E461D4 /* Sources */,\n\t\t\t\tDE94AE211AF246C000E461D4 /* Frameworks */,\n\t\t\t\tDE94AE221AF246C000E461D4 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\tDE94AE261AF246C000E461D4 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = JSPatchTests;\n\t\t\tproductName = JSPatchTests;\n\t\t\tproductReference = DE94AE241AF246C000E461D4 /* JSPatchDemoTests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.unit-test\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\tDE94AE031AF246BF00E461D4 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 0620;\n\t\t\t\tORGANIZATIONNAME = bang;\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\tDE94AE0A1AF246BF00E461D4 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 6.2;\n\t\t\t\t\t};\n\t\t\t\t\tDE94AE231AF246C000E461D4 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 6.2;\n\t\t\t\t\t\tTestTargetID = DE94AE0A1AF246BF00E461D4;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = DE94AE061AF246BF00E461D4 /* Build configuration list for PBXProject \"JSPatchDemo\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = DE94AE021AF246BE00E461D4;\n\t\t\tproductRefGroup = DE94AE0C1AF246BF00E461D4 /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\tDE94AE0A1AF246BF00E461D4 /* JSPatchDemo */,\n\t\t\t\tDE94AE231AF246C000E461D4 /* JSPatchTests */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\tDE94AE091AF246BF00E461D4 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t6C9C0EE51C25A7DA00FCAAC5 /* newProtocolTest.js in Resources */,\n\t\t\t\t3613C3871C6329F300E915CB /* JSPatch.js in Resources */,\n\t\t\t\t3613C38F1C6329F300E915CB /* packer.php in Resources */,\n\t\t\t\tDE6FFF051B42C25D0005EE83 /* protocolTest.js in Resources */,\n\t\t\t\t2D6D12FD1B0B8CF20095A435 /* Images.xcassets in Resources */,\n\t\t\t\t2D6D13011B0B8CFF0095A435 /* demo.js in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tDE94AE221AF246C000E461D4 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tDE6FFF031B42B01C0005EE83 /* protocolTest.js in Resources */,\n\t\t\t\t2D0DF7071B22F75C005695DA /* inheritTest.js in Resources */,\n\t\t\t\t6C6CAC741C5F0BCA00444348 /* superTest.js in Resources */,\n\t\t\t\tDE94AE471AF2480000E461D4 /* test.js in Resources */,\n\t\t\t\t36CE191B1CAEA179007D73AC /* jsClassTest.js in Resources */,\n\t\t\t\t6C9C0EE41C25A7C700FCAAC5 /* newProtocolTest.js in Resources */,\n\t\t\t\t4F9EBFCA1D50749200EC72C1 /* jsNumberTest.js in Resources */,\n\t\t\t\tE1B89EAE1B228818000645C2 /* multithreadTest.js in Resources */,\n\t\t\t\t369492601CFEFE42003F44CA /* jsCFunctionTest.js in Resources */,\n\t\t\t\t36CE19271CB3E72B007D73AC /* performanceTest.js in Resources */,\n\t\t\t\t2DA3C434206B5569005877CB /* newBlockTest.js in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\tDE94AE071AF246BF00E461D4 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t36CC3A591CFEE6A80001465B /* JPUIImage.m in Sources */,\n\t\t\t\t360BCF4E1D82DCFC00202977 /* JPDispatch.m in Sources */,\n\t\t\t\t3613C3AF1C6346F500E915CB /* JPCleaner.m in Sources */,\n\t\t\t\t2D5D89211B0B8BFF009382EC /* AppDelegate.m in Sources */,\n\t\t\t\t36CC3A511CFEE6A80001465B /* JPCGContext.m in Sources */,\n\t\t\t\t3613C38E1C6329F300E915CB /* ZipArchive.m in Sources */,\n\t\t\t\t3613C3861C6329F300E915CB /* JPEngine.m in Sources */,\n\t\t\t\t36CC3A531CFEE6A80001465B /* JPCGImage.m in Sources */,\n\t\t\t\t36CC3A541CFEE6A80001465B /* JPCGPath.m in Sources */,\n\t\t\t\t3613C3881C6329F300E915CB /* JPLoader.m in Sources */,\n\t\t\t\t36CC3A501CFEE6A80001465B /* JPCGColor.m in Sources */,\n\t\t\t\t4F9EBFC51D50745200EC72C1 /* JPNumber.m in Sources */,\n\t\t\t\t36CC3A521CFEE6A80001465B /* JPCGGeometry.m in Sources */,\n\t\t\t\t360BCF541D82EFCD00202977 /* JPProtocol.m in Sources */,\n\t\t\t\tE1B89EA01B203482000645C2 /* JPMultithreadTestObject.m in Sources */,\n\t\t\t\t3660BC2D1E2634C900DB3765 /* JPBlock.m in Sources */,\n\t\t\t\t3613C38B1C6329F300E915CB /* unzip.c in Sources */,\n\t\t\t\t36CC3A4C1CFEE6A80001465B /* JPMemory.m in Sources */,\n\t\t\t\t36CC3A5A1CFEE6A80001465B /* JPUIKit.m in Sources */,\n\t\t\t\t36CC3A4D1CFEE6A80001465B /* JPStructPointer.m in Sources */,\n\t\t\t\t36CC3A571CFEE6A80001465B /* JPUIGeometry.m in Sources */,\n\t\t\t\t36CC3A551CFEE6A80001465B /* JPCGTransform.m in Sources */,\n\t\t\t\t36CC3A561CFEE6A80001465B /* JPCoreGraphics.m in Sources */,\n\t\t\t\t3613C38D1C6329F300E915CB /* RSA.m in Sources */,\n\t\t\t\t3613C3891C6329F300E915CB /* ioapi.c in Sources */,\n\t\t\t\t36CC3A4F1CFEE6A80001465B /* JPCGBitmapContext.m in Sources */,\n\t\t\t\t2D5D89251B0B8BFF009382EC /* JPViewController.m in Sources */,\n\t\t\t\t3613C38A1C6329F300E915CB /* mztools.c in Sources */,\n\t\t\t\t36CC3A581CFEE6A80001465B /* JPUIGraphics.m in Sources */,\n\t\t\t\t36CC3A4B1CFEE6A80001465B /* JPCFunction.m in Sources */,\n\t\t\t\t36B3252D1E290D0C006945DF /* JPMethodSignature.m in Sources */,\n\t\t\t\t3613C38C1C6329F300E915CB /* zip.c in Sources */,\n\t\t\t\t2D6D12FF1B0B8CF20095A435 /* main.m in Sources */,\n\t\t\t\t3646F8B41CA0F89C00E10774 /* JPLocker.m in Sources */,\n\t\t\t\t367650481E2CC3BD00828E12 /* JPBlockWrapper.m in Sources */,\n\t\t\t\t369EC2971C9925A400334A64 /* JPSpecialInit.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\tDE94AE201AF246C000E461D4 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t6C6CAC751C5F0BCA00444348 /* JPSuperTestObject.m in Sources */,\n\t\t\t\t6C72B7961C352BA80086C98D /* newProtocolTest.m in Sources */,\n\t\t\t\tDE94AE461AF2480000E461D4 /* JPTestObject.m in Sources */,\n\t\t\t\t36CE191E1CAEA1DE007D73AC /* JPJSClassTest.m in Sources */,\n\t\t\t\t36CE19251CB3E709007D73AC /* JPPerformanceTest.m in Sources */,\n\t\t\t\tE1B89EA31B218986000645C2 /* JPInheritanceTestObjects.m in Sources */,\n\t\t\t\t4F9EBFC91D50749200EC72C1 /* JPNumberTest.m in Sources */,\n\t\t\t\tDE94AE2B1AF246C000E461D4 /* JSPatchTests.m in Sources */,\n\t\t\t\t2DA3C42B206A1892005877CB /* newBlockTest.m in Sources */,\n\t\t\t\t3694925F1CFEFE42003F44CA /* JPCFunctionTest.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\tDE94AE261AF246C000E461D4 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = DE94AE0A1AF246BF00E461D4 /* JSPatchDemo */;\n\t\t\ttargetProxy = DE94AE251AF246C000E461D4 /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin XCBuildConfiguration section */\n\t\tDE94AE2C1AF246C000E461D4 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tDE94AE2D1AF246C000E461D4 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = YES;\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tDE94AE2F1AF246C000E461D4 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tDEVELOPMENT_TEAM = \"\";\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tINFOPLIST_FILE = \"$(SRCROOT)/JSPatchDemo/Supporting Files/Info.plist\";\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tLD_GENERATE_MAP_FILE = YES;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)\",\n\t\t\t\t\t\"../../**\",\n\t\t\t\t);\n\t\t\t\tONLY_ACTIVE_ARCH = NO;\n\t\t\t\tOTHER_LDFLAGS = \"\";\n\t\t\t\tPRODUCT_NAME = JSPatchDemo;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tDE94AE301AF246C000E461D4 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tDEVELOPMENT_TEAM = \"\";\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tINFOPLIST_FILE = \"$(SRCROOT)/JSPatchDemo/Supporting Files/Info.plist\";\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tLD_GENERATE_MAP_FILE = YES;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)\",\n\t\t\t\t\t\"../../**\",\n\t\t\t\t);\n\t\t\t\tONLY_ACTIVE_ARCH = NO;\n\t\t\t\tOTHER_LDFLAGS = \"\";\n\t\t\t\tPRODUCT_NAME = JSPatchDemo;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tDE94AE321AF246C000E461D4 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tDEVELOPMENT_TEAM = \"\";\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(SDKROOT)/Developer/Library/Frameworks\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = JSPatchTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_NAME = JSPatchDemoTests;\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/JSPatchDemo.app/JSPatchDemo\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tDE94AE331AF246C000E461D4 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tBUNDLE_LOADER = \"$(TEST_HOST)\";\n\t\t\t\tDEVELOPMENT_TEAM = \"\";\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(SDKROOT)/Developer/Library/Frameworks\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = JSPatchTests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tPRODUCT_NAME = JSPatchDemoTests;\n\t\t\t\tTEST_HOST = \"$(BUILT_PRODUCTS_DIR)/JSPatchDemo.app/JSPatchDemo\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\tDE94AE061AF246BF00E461D4 /* Build configuration list for PBXProject \"JSPatchDemo\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tDE94AE2C1AF246C000E461D4 /* Debug */,\n\t\t\t\tDE94AE2D1AF246C000E461D4 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tDE94AE2E1AF246C000E461D4 /* Build configuration list for PBXNativeTarget \"JSPatchDemo\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tDE94AE2F1AF246C000E461D4 /* Debug */,\n\t\t\t\tDE94AE301AF246C000E461D4 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\tDE94AE311AF246C000E461D4 /* Build configuration list for PBXNativeTarget \"JSPatchTests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tDE94AE321AF246C000E461D4 /* Debug */,\n\t\t\t\tDE94AE331AF246C000E461D4 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = DE94AE031AF246BF00E461D4 /* Project object */;\n}\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchDemo.xcodeproj/xcshareddata/xcschemes/JSPatchDemo.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0630\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"DE94AE0A1AF246BF00E461D4\"\n               BuildableName = \"JSPatchDemo.app\"\n               BlueprintName = \"JSPatchDemo\"\n               ReferencedContainer = \"container:JSPatchDemo.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"NO\"\n            buildForArchiving = \"NO\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"DE94AE231AF246C000E461D4\"\n               BuildableName = \"JSPatchDemoTests.xctest\"\n               BlueprintName = \"JSPatchTests\"\n               ReferencedContainer = \"container:JSPatchDemo.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Release\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <Testables>\n         <TestableReference\n            skipped = \"NO\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"DE94AE231AF246C000E461D4\"\n               BuildableName = \"JSPatchDemoTests.xctest\"\n               BlueprintName = \"JSPatchTests\"\n               ReferencedContainer = \"container:JSPatchDemo.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n      </Testables>\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"DE94AE0A1AF246BF00E461D4\"\n            BuildableName = \"JSPatchDemo.app\"\n            BlueprintName = \"JSPatchDemo\"\n            ReferencedContainer = \"container:JSPatchDemo.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"DE94AE0A1AF246BF00E461D4\"\n            BuildableName = \"JSPatchDemo.app\"\n            BlueprintName = \"JSPatchDemo\"\n            ReferencedContainer = \"container:JSPatchDemo.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"DE94AE0A1AF246BF00E461D4\"\n            BuildableName = \"JSPatchDemo.app\"\n            BlueprintName = \"JSPatchDemo\"\n            ReferencedContainer = \"container:JSPatchDemo.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>net.cnbang.$(PRODUCT_NAME:rfc1034identifier)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/InheritTest.js",
    "content": "var global = this;\n\n(function() {\n  defineClass(\"JPInheritTest01ObjectB\", {\n    m1: function() {\n      return \"JP_01ObjB_m1\";\n    }\n  });\n \n\n  defineClass(\"JPInheritTest02ObjectB\", {\n    m1: function() {\n      return \"JP_02ObjB_m1\";\n    }\n  });\n  defineClass(\"JPInheritTest02ObjectC\", {\n    m2: function() {\n      return \"JP_02ObjC_m2\";\n    }\n  });\n })();\n\n(function(){\n  defineClass(\"JPInheritTest02ObjectB\", {\n    m1:function(){\n      return \"JP_02ObjB_m1\";\n    },\n    m3:function(){\n      return \"JP_02ObjC_m3\";\n    }\n  },\n  {});\n  defineClass(\"JPInheritTest02ObjectC\", {\n    m2:function(){\n      return \"JP_02ObjC_m2\";\n    },\n    m3:function(){\n      return self.super().m3();\n    }\n  },\n  {});\n })();\n\n(function(){\n  defineClass(\"JPInheritTest03ObjectB\", {\n    m1:function(){\n      return \"JP_03ObjB_m1\";\n    }\n  },\n  {});\n  defineClass(\"JPInheritTest03ObjectC\", {\n    m2:function(){\n      return \"JP_03ObjC_m2\";\n    }\n  },\n  {});\n })();"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/JPCFunctionTest.h",
    "content": "//\n//  JPCFunctionTest.h\n//  JSPatchDemo\n//\n//  Created by bang on 6/1/16.\n//  Copyright © 2016 bang. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n@interface JPCFunctionTest : NSObject\n+ (BOOL)testCfuncWithCGSize;\n+ (BOOL)testCfuncWithCGRect;\n+ (BOOL)testCfuncWithId;\n+ (BOOL)testCfuncWithInt;\n+ (BOOL)testCfuncWithCGFloat;\n+ (BOOL)testCfuncReturnPointer;\n+ (BOOL)testCFunctionReturnClass;\n+ (BOOL)testCFunctionVoid;\n@end\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/JPCFunctionTest.m",
    "content": "//\n//  JPCFunctionTest.m\n//  JSPatchDemo\n//\n//  Created by bang on 6/1/16.\n//  Copyright © 2016 bang. All rights reserved.\n//\n\n#import \"JPCFunctionTest.h\"\n#import <UIKit/UIKit.h>\n#import \"JPEngine.h\"\n\nstatic bool voidFuncRet = false;\n\nCGSize cfuncWithCGSize(CGSize size){\n    return size;\n}\n\nCGRect cfuncWithCGRect(CGRect rect){\n    return rect;\n}\n\nid cfuncWithId(NSString *str){\n    return str;\n}\n\nint cfuncWithInt(int num) {\n    return num;\n}\n\nCGFloat cfuncWithCGFloat(CGFloat num) {\n    return num;\n}\n\nvoid *cfuncReturnPointer() {\n    char *a = \"abc\";\n    return a;\n}\n\nbool cfuncWithPointerIsEqual(char *a) {\n    return a[0] == 'a';\n}\nvoid cfuncVoid() {\n    NSLog(@\"dsssdfsdf\");\n}\n\n@implementation JPCFunctionTest\n+ (BOOL)testCfuncWithCGSize{\n    return NO;\n}\n+ (BOOL)testCfuncWithCGRect{\n    return NO;\n}\n+ (BOOL)testCfuncWithId{\n    return NO;\n};\n+ (BOOL)testCfuncWithInt{\n    return NO;\n};\n+ (BOOL)testCfuncWithCGFloat{\n    return NO;\n};\n+ (BOOL)testCfuncReturnPointer{\n    return NO;\n};\n+ (BOOL)testCFunctionReturnClass{\n    return NO;\n};\n+ (BOOL)testCFunctionVoid{\n    return voidFuncRet;\n};\n+ (void)setupCFunctionVoidSucc{\n    voidFuncRet = true;\n}\n@end\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/JPInheritanceTestObjects.h",
    "content": "//\n//  JPInheritanceTestObjects.h\n//  JSPatchDemo\n//\n//  Created by Qiu WeiJia on 6/5/15.\n//  Copyright (c) 2015 bang. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n@interface JPInheritTest01ObjectA : NSObject\n\n- (NSString*)m1;\n- (NSString*)m2;\n\n@end\n\n@interface JPInheritTest01ObjectB : JPInheritTest01ObjectA\n\n- (NSString*)m1;\n\n@end\n\n@interface JPInheritTest02ObjectA : NSObject\n\n- (NSString*)m1;\n- (NSString*)m2;\n- (NSString*)m3;\n\n@end\n\n@interface JPInheritTest02ObjectB : JPInheritTest02ObjectA\n\n- (NSString*)m1;\n- (NSString*)m3;\n\n@end\n\n@interface JPInheritTest02ObjectC : JPInheritTest02ObjectB\n\n- (NSString*)m2;\n\n@end\n\n@interface JPInheritTest03ObjectA : NSObject\n\n- (NSString*)m1;\n- (NSString*)m2;\n\n@end\n\n@interface JPInheritTest03ObjectB : JPInheritTest03ObjectA\n\n- (NSString*)m1;\n\n@end\n\n@interface JPInheritTest03ObjectC : JPInheritTest03ObjectA\n\n- (NSString*)m2;\n\n@end"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/JPInheritanceTestObjects.m",
    "content": "//\n//  JPInheritanceTestObjects.m\n//  JSPatchDemo\n//\n//  Created by Qiu WeiJia on 6/5/15.\n//  Copyright (c) 2015 bang. All rights reserved.\n//\n\n#import \"JPInheritanceTestObjects.h\"\n\n@implementation JPInheritTest01ObjectA\n\n- (NSString*)m1\n{\n    return @\"01ObjA_m1\";\n}\n\n- (NSString*)m2\n{\n    return @\"01ObjA_m2\";\n}\n\n@end\n\n@implementation JPInheritTest01ObjectB\n\n- (NSString*)m1\n{\n    return @\"01ObjB_m1\";\n}\n\n@end\n\n\n@implementation JPInheritTest02ObjectA\n\n- (NSString*)m1\n{\n    return @\"02ObjA_m1\";\n}\n\n- (NSString*)m2\n{\n    return @\"02ObjA_m2\";\n}\n\n- (NSString*)m3\n{\n    return @\"02ObjA_m3\";\n}\n\n@end\n\n@implementation JPInheritTest02ObjectB\n\n- (NSString*)m1\n{\n    return @\"02ObjB_m1\";\n}\n\n- (NSString*)m3\n{\n    return @\"02ObjB_m3\";\n}\n\n@end\n\n@implementation JPInheritTest02ObjectC\n\n- (NSString*)m2\n{\n    return @\"02ObjC_m2\";\n}\n\n@end\n\n@implementation JPInheritTest03ObjectA\n\n- (NSString*)m1\n{\n    return @\"03ObjA_m1\";\n}\n\n- (NSString*)m2\n{\n    return @\"03ObjA_m2\";\n}\n\n@end\n\n@implementation JPInheritTest03ObjectB\n\n- (NSString*)m1\n{\n    return @\"03ObjB_m1\";\n}\n\n\n@end\n\n@implementation JPInheritTest03ObjectC\n\n- (NSString*)m2\n{\n    return @\"03ObjC_m2\";\n}\n\n@end\n\n\n\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/JPJSClassTest.h",
    "content": "//\n//  JPJSClassTest.h\n//  JSPatchDemo\n//\n//  Created by bang on 4/1/16.\n//  Copyright © 2016 bang. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n@interface JPJSClassTest : NSObject\n+ (BOOL)isPassA;\n+ (BOOL)isPassB;\n+ (BOOL)isPassC;\n@end\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/JPJSClassTest.m",
    "content": "//\n//  JPJSClassTest.m\n//  JSPatchDemo\n//\n//  Created by bang on 4/1/16.\n//  Copyright © 2016 bang. All rights reserved.\n//\n\n#import \"JPJSClassTest.h\"\n\n@implementation JPJSClassTest\n+ (BOOL)isPassA\n{\n    return NO;\n}\n+ (BOOL)isPassB\n{\n    return NO;\n}\n+ (BOOL)isPassC\n{\n    return NO;\n}\n@end\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/JPMultithreadTestObject.h",
    "content": "//\n//  MultithreadTestObject.h\n//  JSPatchDemo\n//\n//  Created by Qiu WeiJia on 15/6/4.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n@interface JPMultithreadTestObject : NSObject\n{\n    NSMutableArray *_values;\n}\n\n@property int objectId;\n\n- (instancetype)init;\n- (void)addValueJS:(NSNumber*)number;\n- (void)addValue:(NSNumber*)number;\n- (void)addValueNoPatch:(NSNumber*)number;\n- (BOOL)checkAllValues;\n\n@end\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/JPMultithreadTestObject.m",
    "content": "//\n//  MultithreadTestObject.m\n//  JSPatchDemo\n//\n//  Created by Qiu WeiJia on 15/6/4.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import \"JPMultithreadTestObject.h\"\n\n@implementation JPMultithreadTestObject\n\n- (instancetype)init {\n    self = [super init];\n    if (self) {\n        _values = [[NSMutableArray alloc] init];\n        \n        [_values addObject:[NSNumber numberWithInt:-1]];\n        \n    }\n    return self;\n}\n\n- (void)addValueJS:(NSNumber*)number\n{\n}\n\n- (void)addValue:(NSNumber*)number\n{\n    if ([_values count] > 0 && [[_values objectAtIndex:0] integerValue] < 0) {\n        [_values removeAllObjects];\n    }\n    [_values addObject:number];\n}\n\n- (void)addValueNoPatch:(NSNumber*)number\n{\n    [_values addObject:number];\n}\n\n- (BOOL)checkAllValues\n{\n    for (NSNumber *num in _values) {\n        if ([num intValue] != self.objectId) {\n            return FALSE;\n        }\n    }\n    return TRUE;\n}\n\n@end\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/JPNumberTest.h",
    "content": "//\n//  JPNumberTest.h\n//  JSPatchDemo\n//\n//  Created by pucheng on 16/8/2.\n//  Copyright © 2016年 bang. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n@interface JPNumberTest : NSObject\n\n+ (BOOL)testJPNumNSNumber;\n+ (BOOL)testJPNumNSDecimalNumber;\n+ (BOOL)testJPNumToJS;\n+ (BOOL)testJPNUmToOC;\n\n@end\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/JPNumberTest.m",
    "content": "//\n//  JPNumberTest.m\n//  JSPatchDemo\n//\n//  Created by pucheng on 16/8/2.\n//  Copyright © 2016年 bang. All rights reserved.\n//\n\n#import \"JPNumberTest.h\"\n\n@implementation JPNumberTest\n\n+ (BOOL)testJPNumNSNumber {\n    return NO;\n}\n\n+ (BOOL)testJPNumNSDecimalNumber {\n    return NO;\n}\n\n+ (BOOL)testJPNumToJS {\n    return NO;\n}\n\n+ (BOOL)testJPNUmToOC {\n    return NO;\n}\n\n@end\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/JPPerformanceTest.h",
    "content": "//\n//  JPPerformanceTest.h\n//  JSPatchDemo\n//\n//  Created by bang on 4/5/16.\n//  Copyright © 2016 bang. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n@interface JPPerformanceTest : NSObject\n- (void)testJSCallOCEmptyMethod;\n- (void)testJSCallOCMethodWithParamObject;\n- (void)testJSCallOCMethodReturnObject;\n\n- (void)testJSCallJSEmptyMethod;\n- (void)testJSCallJSMethodWithLargeDictionaryParam;\n- (void)testJSCallJSMethodWithLargeDictionaryParamAutoConvert;\n- (void)testJSCallJSMethodWithParam;\n\n- (void)testOCCallEmptyMethod;\n- (void)testOCCallMethodWithParamObject;\n- (void)testOCCallMethodReturnObject;\n\n- (void)testJSCallMallocJPMemory;\n- (void)testJSCallMallocJPCFunction;\n\n@end\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/JPPerformanceTest.m",
    "content": "//\n//  JPPerformanceTest.m\n//  JSPatchDemo\n//\n//  Created by bang on 4/5/16.\n//  Copyright © 2016 bang. All rights reserved.\n//\n\n#import \"JPPerformanceTest.h\"\n#import <UIKit/UIKit.h>\n\n@implementation JPPerformanceTest\n\n//overrided in JS\n- (void)testJSCallOCEmptyMethod {}\n- (void)testJSCallOCMethodWithParamObject{}\n- (void)testJSCallOCMethodReturnObject{}\n\n- (void)testJSCallJSEmptyMethod{}\n- (void)testJSCallJSMethodWithLargeDictionaryParam{}\n- (void)testJSCallJSMethodWithLargeDictionaryParamAutoConvert{}\n- (void)testJSCallJSMethodWithParam{}\n\n\n- (void)testOCCallEmptyMethod {\n    for (int i = 0; i < 10000; i ++) {\n        [self emptyMethodToOverride];\n    }\n}\n\n- (void)testOCCallMethodWithParamObject {\n    NSObject *obj = [[NSObject alloc] init];\n    for (int i = 0; i < 10000; i ++) {\n        [self methodWithParamObjectToOverride:obj];\n    }\n}\n\n- (void)testOCCallMethodReturnObject {\n    id ret;\n    for (int i = 0; i < 10000; i ++) {\n        ret = [self methodReturnObjectToOverride];\n    }\n}\n\n- (void)testJSCallMallocJPMemory{}\n- (void)testJSCallMallocJPCFunction{}\n\n#pragma mark performance\nstatic NSObject *testPerformanceObj;\n- (void)initTestPerformanceObj {\n    if (!testPerformanceObj) testPerformanceObj = [[NSObject alloc] init];\n}\n- (void)emptyMethod {\n}\n\n- (void)methodWithParamObject:(NSObject *)obj {\n    \n}\n- (NSObject *)methodReturnObject {\n    return testPerformanceObj;\n}\n\n- (void)emptyMethodToOverride {\n    \n}\n- (void)methodWithParamObjectToOverride:(NSObject *)obj {\n    \n}\n- (NSObject *)methodReturnObjectToOverride {\n    return nil;\n}\n\n- (void)allArgSumWithBlock:(double (^)(CGFloat arg0, CGPoint arg1, NSInteger arg2, id arg3))block {\n    \n    NSNumber *arg3 = [NSNumber numberWithDouble:3.3];\n    double sum = block(3.2, (CGPoint){1.1,1.2}, 10,arg3);\n    NSLog(@\"==== sum = %@\",@(sum));\n}\n\n\n@end\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/JPSuperTestObject.h",
    "content": "//\n//  JPSuperTestObject.h\n//  JSPatchDemo\n//\n//  Created by bang on 4/1/16.\n//  Copyright © 2016 bang. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\n@interface JPSuperTestA : NSObject\n\n@end\n\n\n@interface JPSuperTestB : NSObject\n\n@end\n\n@interface JPSuperTestB1 : JPSuperTestB\n\n@end\n\n\n\n@interface JPSuperTestC : NSObject\n\n@end\n\n@interface JPSuperTestC1 : JPSuperTestC\n\n@end\n\n@interface JPSuperTestC2 : JPSuperTestC1\n\n@end\n\n@interface JPSuperTestResult : NSObject\n+ (BOOL)isPassA;\n+ (BOOL)isPassB;\n+ (BOOL)isPassC;\n@end"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/JPSuperTestObject.m",
    "content": "//\n//  JPSuperTestObject.m\n//  JSPatchDemo\n//\n//  Created by bang on 4/1/16.\n//  Copyright © 2016 bang. All rights reserved.\n//\n\n#import \"JPSuperTestObject.h\"\n\n@implementation JPSuperTestA\n\n- (NSString *)method {\n    return @\"A\";\n}\n\n@end\n\n\n@implementation JPSuperTestB\n\n- (NSString *)method {\n    return @\"B\";\n}\n\n@end\n\n@implementation JPSuperTestB1\n\n- (NSString *)method {\n    return [NSString stringWithFormat:@\"%@%@\", [super method], @\"1\"];\n}\n\n@end\n\n\n\n\n\n@implementation JPSuperTestC\n\n- (NSString *)method {\n    return @\"C\";\n}\n\n@end\n\n@implementation JPSuperTestC1\n\n- (NSString *)method {\n    return [NSString stringWithFormat:@\"%@%@\", [super method], @\"1\"];\n}\n\n@end\n\n@implementation JPSuperTestC2\n\n- (NSString *)method {\n    return [NSString stringWithFormat:@\"%@%@\", [super method], @\"2\"];\n}\n\n@end\n\n\n\n\n\n@implementation JPSuperTestResult\n\n+ (BOOL)isPassA {\n    return NO;\n}\n\n+ (BOOL)isPassB {\n    return NO;\n}\n\n+ (BOOL)isPassC {\n    JPSuperTestC2 *c = [[JPSuperTestC2 alloc] init];\n    return [[c method] isEqualToString:@\"C1C2\"];\n}\n@end\n\n\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/JPTestObject.h",
    "content": "//\n//  ISTestObject.h\n//  InstaScript\n//\n//  Created by bang on 15/4/30.\n//  Copyright (c) 2015 bang. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import <UIKit/UIKit.h>\n\n@interface JPTestObject : NSObject\n- (void)funcWithInt:(int)intValue;\n@property (nonatomic, assign) BOOL funcReturnVoidPassed;\n@property (nonatomic, assign) BOOL funcReturnStringPassed;\n@property (nonatomic, assign) BOOL funcReturnDoublePassed;\n@property (nonatomic, assign) BOOL funcReturnClassPassed;\n@property (nonatomic, assign) BOOL funcReturnViewWithFramePassed;\n@property (nonatomic, assign) BOOL funcWithViewAndReturnViewPassed;\n\n@property (nonatomic, assign) BOOL funcWithIntPassed;\n@property (nonatomic, assign) BOOL funcWithNilPassed;\n@property (nonatomic, assign) BOOL funcReturnNilPassed;\n@property (nonatomic, assign) BOOL funcWithNilAndOthersPassed;\n@property (nonatomic, assign) BOOL funcWithNullPassed;\n@property (nonatomic, assign) BOOL funcTestBoolPassed;\n@property (nonatomic, assign) BOOL funcTestNSNumberPassed;\n\n\n@property (nonatomic, assign) BOOL funcWithDictAndDoublePassed;\n\n@property (nonatomic, assign) BOOL funcWithRangeAndReturnRangePassed;\n@property (nonatomic, assign) BOOL funcWithRectAndReturnRectPassed;\n@property (nonatomic, assign) BOOL funcWithPointAndReturnPointPassed;\n@property (nonatomic, assign) BOOL funcWithSizeAndReturnSizePassed;\n@property (nonatomic, assign) BOOL funcWithClassAndReturnStringPassed;\n\n@property (nonatomic, assign) BOOL funcReturnDictStringIntPassed;\n@property (nonatomic, assign) BOOL funcReturnDictStringViewPassed;\n@property (nonatomic, assign) BOOL funcReturnArrayControllerViewStringPassed;\n@property (nonatomic, assign) BOOL funcReturnDictPassed;\n@property (nonatomic, assign) BOOL testBoxingObjPassed;\n\n@property (nonatomic, assign) BOOL funcReturnBlockPassed;\n@property (nonatomic, assign) BOOL funcReturnObjectBlockPassed;\n@property (nonatomic, assign) BOOL funcReturnObjectBlockReturnValuePassed;\n@property (nonatomic, assign) BOOL funcReturnJSBlockPassed;\n@property (nonatomic, assign) BOOL callBlockWithStringAndIntPassed;\n@property (nonatomic, assign) BOOL callBlockWithStringAndIntReturnValuePassed;\n@property (nonatomic, assign) BOOL callBlockWithArrayAndViewPassed;\n@property (nonatomic, assign) BOOL callBlockWithBoolAndBlockPassed;\n@property (nonatomic, assign) BOOL callBlockWithObjectAndBlockPassed;\n@property (nonatomic, assign) BOOL callBlockWithObjectAndBlockReturnValuePassed;\n@property (nonatomic, assign) BOOL callBlockWithDoubleAndReturnDoublePassed;\n\n\n@property (nonatomic, assign) BOOL funcToSwizzleWithStringViewIntPassed;\n@property (nonatomic, assign) BOOL funcToSwizzleViewPassed;\n@property (nonatomic, assign) BOOL funcToSwizzleViewCalledOriginalPassed;\n@property (nonatomic, assign) BOOL funcToSwizzleReturnViewPassed;\n@property (nonatomic, assign) BOOL funcToSwizzleParamNilPassed;\n@property (nonatomic, assign) BOOL funcToSwizzleReturnIntPassed;\n@property (nonatomic, assign) BOOL funcToSwizzleWithBlockPassed;\n@property (nonatomic, assign) BOOL funcToSwizzle_withUnderLine_Passed;\n@property (nonatomic, assign) BOOL funcToSwizzleReturnRectPassed;\n@property (nonatomic, assign) BOOL funcToSwizzleReturnPointPassed;\n@property (nonatomic, assign) BOOL funcToSwizzleReturnSizePassed;\n@property (nonatomic, assign) BOOL funcToSwizzleReturnRangePassed;\n@property (nonatomic, assign) BOOL funcToSwizzleReturnEdgeInsetsPassed;\n@property (nonatomic, assign) BOOL funcToSwizzleReturnRectJSPassed;\n@property (nonatomic, assign) BOOL funcToSwizzleReturnPointJSPassed;\n@property (nonatomic, assign) BOOL funcToSwizzleReturnSizeJSPassed;\n@property (nonatomic, assign) BOOL funcToSwizzleReturnRangeJSPassed;\n@property (nonatomic, assign) BOOL funcToSwizzleReturnEdgeInsetsJSPassed;\n@property (nonatomic, assign) BOOL funcToSwizzleTestGCDPassed;\n@property (nonatomic, assign) BOOL funcToSwizzleTestClassPassed;\n@property (nonatomic, assign) BOOL funcToSwizzleTestSelectorPassed;\n@property (nonatomic, assign) BOOL funcToSwizzleTestCharPassed;\n@property (nonatomic, assign) BOOL funcToSwizzleReturnClassPassed;\n@property (nonatomic, assign) BOOL funcTestCharPassed;\n@property (nonatomic, assign) BOOL funcToSwizzleTestPointerPassed;\n@property (nonatomic, assign) BOOL funcTestPointerPassed;\n@property (nonatomic, assign) BOOL funcTestSizeofPassed;\n@property (nonatomic, assign) BOOL funcTestGetPointerPassed;\n@property (nonatomic, assign) BOOL funcTestNSErrorPointerPassed;\n@property (nonatomic, assign) BOOL funcTestNilParametersInBlockPassed;\n@property (nonatomic, assign) BOOL classFuncToSwizzlePassed;\n@property (nonatomic, assign) BOOL classFuncToSwizzleReturnObjPassed;\n@property (nonatomic, assign) BOOL classFuncToSwizzleReturnObjCalledOriginalPassed;\n@property (nonatomic, assign) BOOL classFuncToSwizzleReturnIntPassed;\n@property (nonatomic, assign) BOOL classFuncToSwizzleReturnDoublePassed;\n\n\n@property (nonatomic, assign) BOOL funcCallSuperPassed;\n@property (nonatomic, assign) BOOL callForwardInvocationPassed;\n\n@property (nonatomic, strong) UIView *testView;\n@property (nonatomic, assign) BOOL propertySetFramePassed;\n@property (nonatomic, assign) BOOL propertySetViewPassed;\n\n@property (nonatomic, assign) BOOL newTestObjectReturnViewPassed;\n@property (nonatomic, assign) BOOL newTestObjectReturnBoolPassed;\n@property (nonatomic, assign) BOOL newTestObjectCustomFuncPassed;\n\n@property (nonatomic, assign) BOOL mutableArrayPassed;\n@property (nonatomic, assign) BOOL mutableStringPassed;\n@property (nonatomic, assign) BOOL mutableDictionaryPassed;\n\n@property (nonatomic, assign) BOOL funcWithTransformPassed;\n@property (nonatomic, assign) BOOL transformTranslatePassed;\n@property (nonatomic, assign) BOOL funcWithRectPointerPassed;\n@property (nonatomic, assign) BOOL funcWithTransformPointerPassed;\n\n@property (nonatomic, assign) BOOL consoleLogPassed;\n@property (nonatomic, assign) BOOL overrideParentMethodPassed;\n\n@property (nonatomic, assign) BOOL variableParameterMethodPassed;\n\n- (NSString*)funcOverrideParentMethod;\n- (void)funcToSwizzleTestGCD:(void(^)())block;\n\n- (NSDictionary *)funcToSwizzleReturnDictionary:(NSDictionary *)dict;\n- (NSDictionary *)funcToSwizzleReturnJSDictionary;\n- (NSArray *)funcToSwizzleReturnArray:(NSArray *)arr;\n- (NSString *)funcToSwizzleReturnString:(NSString *)str;\n@end\n\n\n@interface JPTestSubObject : JPTestObject\n@property (nonatomic, assign) BOOL funcCallSuperSubObjectPassed;\n@end\n\n@protocol JPTestProtocol <NSObject>\n- (double)protocolWithDouble:(double)num dict:(NSDictionary *)dictionary;\n+ (NSString *)classProtocolWithString:(NSString *)string int:(NSInteger)num;\n@end\n\n@protocol JPTestProtocol2 <NSObject>\n@optional\n- (NSInteger)protocolWithInt:(NSInteger)num;\n@end\n\n@interface JPTestProtocolObject : NSObject <JPTestProtocol, JPTestProtocol2>\n- (BOOL)testProtocolMethods;\n@end\n\n@interface JPTestSwizzledForwardInvocationSuperObject : NSObject\n\n@property (nonatomic, assign) BOOL callSwizzledSuperForwardInvocationPassed;\n\n- (void)swizzleSuperForwoardInvocation;\n\n@end\n\n@interface JPTestSwizzledForwardInvocationSubObject : JPTestSwizzledForwardInvocationSuperObject\n\n- (void)callTestSwizzledSuperForwardInvocation;\n\n@end\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/JPTestObject.m",
    "content": "//\n//  JPTestObject.m\n//  InstaScript\n//\n//  Created by bang on 15/4/30.\n//  Copyright (c) 2015 bang. All rights reserved.\n//\n\n#import \"JPTestObject.h\"\n#import <objc/runtime.h>\n\n@implementation JPTestObject\n- (void)funcReturnVoid\n{\n    self.funcReturnVoidPassed = YES;\n}\n\n- (NSString *)funcReturnString\n{\n    return @\"stringFromOC\";\n}\n\n+ (NSString *)classFunCallReturnString\n{\n    return @\"classFunCallReturnString\";\n}\n\n- (Class)funcReturnClass\n{\n    return [self class];\n}\n\n- (Class)funcToSwizzleReturnClass\n{\n    return nil;\n}\n\n\n- (double)funcReturnDouble {\n    return 100.0;\n}\n\n- (CGRect)funcWithRectAndReturnRect:(CGRect)rect\n{\n    return rect;\n}\n\n- (CGPoint)funcWithPointAndReturnPoint:(CGPoint)point\n{\n    return point;\n}\n\n- (CGSize)funcWithSizeAndReturnSize:(CGSize)size\n{\n    return size;\n}\n\n- (NSRange)funcWithRangeAndReturnRange:(NSRange)range\n{\n    return range;\n}\n\n- (UIView *)funcReturnViewWithFrame:(CGRect)frame\n{\n    UIView *view = [[UIView alloc] initWithFrame:frame];\n    return view;\n}\n\n- (UIView *)funcWithViewAndReturnView:(UIView *)view\n{\n    return view;\n}\n\n- (NSString *)funcWithClassAndReturnString:(Class)cls\n{\n    return NSStringFromClass(cls);\n}\n\n\n- (void)funcWithInt:(int)intValue\n{\n    self.funcWithIntPassed = intValue == 42;\n}\n\n- (void)funcWithNil:(NSObject *)nilObj\n{\n    self.funcWithNilPassed = nilObj == nil;\n}\n\n- (id)funcReturnNil\n{\n    return nil;\n}\n\n- (BOOL)funcTestBool:(BOOL)b\n{\n    return b;\n}\n\n- (NSNumber *)funcTestNSNumber:(NSNumber *)num\n{\n    return num;\n}\n\n- (void)funcWithNil:(NSObject *)nilObj dict:(NSDictionary *)dict str:(NSString *)str num:(double)num\n{\n    self.funcWithNilAndOthersPassed = nilObj == nil && [dict[@\"k\"] isEqualToString:@\"JSPatch\"] && [str isEqualToString:@\"JSPatch\"] && num - 4.2 < 0.001;\n}\n- (void)funcWithNull:(NSNull *)nullObj\n{\n    self.funcWithNullPassed = [nullObj isKindOfClass:[NSNull class]];\n}\n\n#pragma mark - NSDictionary / NSArray\n\n- (void)funcWithDict:(NSDictionary *)dict andDouble:(double)doubleValue\n{\n    BOOL dictPass = [dict[@\"test\"] isEqualToString:@\"test\"];\n    BOOL doublePass = doubleValue - 4.2 < 0.001;\n    self.funcWithDictAndDoublePassed = dictPass && doublePass;\n}\n\n- (NSDictionary *)funcReturnDict:(NSDictionary *)dict\n{\n    return dict;\n}\n- (NSDictionary *)funcReturnDictStringInt\n{\n    return @{@\"str\": @\"stringFromOC\", @\"num\": @(42)};\n}\n\n- (NSDictionary *)funcReturnDictStringView\n{\n    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];\n    return @{@\"view\": view, @\"str\": @\"stringFromOC\"};\n}\n\n- (NSArray *)funcReturnArrayControllerViewString\n{\n    UIViewController *controller = [[UIViewController alloc] init];\n    UIView *view = [[UIView alloc] init];\n    return @[controller, view, @\"stringFromOC\"];\n}\n\n- (NSString *)getString\n{\n    return @\"JSPatch\";\n}\n\n- (NSArray *)getArray\n{\n    return @[@\"JSPatch\", @(1)];\n}\n\n- (NSDictionary *)getDictionary\n{\n    return @{@\"k\": @\"JSPatch\"};\n}\n\n- (void)funcTestBoxingObj:(NSArray *)data\n{\n    NSString *str = data[0];\n    NSDictionary *dict = data[1];\n    NSArray *arr = data[2];\n    self.testBoxingObjPassed = [str isEqualToString:[self getString]] && [dict[@\"k\"] isEqualToString:[[self getDictionary] objectForKey:@\"k\"]] && [arr[0] isEqualToString:[[self getArray] objectAtIndex:0]];\n}\n\n\n#pragma mark - block\n\ntypedef void (^ISTestBlock)(NSString *str, int num);\n- (ISTestBlock)funcReturnBlock\n{\n    ISTestBlock block = ^(NSString *str, int num) {\n        self.funcReturnBlockPassed = [str isEqualToString:@\"stringFromJS\"] && num == 42;\n    };\n    return block;\n}\n\ntypedef id (^JPTestObjectBlock)(NSDictionary *dict, UIView *view);\n- (JPTestObjectBlock)funcReturnObjectBlock\n{\n    JPTestObjectBlock block = ^(NSDictionary *dict, UIView *view) {\n        self.funcReturnObjectBlockPassed = [dict[@\"str\"] isEqualToString:@\"stringFromJS\"] && [dict[@\"view\"] isKindOfClass:[UIView class]] && view.frame.size.width == 100;\n        return @\"succ\";\n    };\n    return block;\n}\n\n- (ISTestBlock)funcReturnJSBlock:(ISTestBlock)jsblock\n{\n    return jsblock;\n}\n\n- (void)callBlockWithStringAndInt:(id(^)(NSString *str, int num))block\n{\n    id ret = block(@\"stringFromOC\", 42);\n    self.callBlockWithStringAndIntReturnValuePassed = [ret isEqualToString:@\"succ\"];\n}\n\n- (void)callBlockDelay:(id(^)(NSString *str, int num))block\n{\n    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{\n        id ret = block(@\"stringFromOC\", 42);\n        self.callBlockWithStringAndIntReturnValuePassed = [ret isEqualToString:@\"succ\"];\n    });\n}\n\n- (void)callBlockWithArrayAndView:(void(^)(NSArray *arr, UIView *view))block\n{\n    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];\n    block(@[@\"stringFromOC\", view], view);\n}\n\n- (void)callBlockWithBoolAndBlock:(void(^)(BOOL b, ISTestBlock block))block\n{\n    ISTestBlock cbBlock = ^(NSString *str, int num) {\n        self.callBlockWithBoolAndBlockPassed = [str isEqualToString:@\"stringFromJS\"] && num == 42;\n    };\n    block(YES, cbBlock);\n}\n\n- (void)callBlockWithObjectAndBlock:(void(^)(UIView *view, JPTestObjectBlock block))block\n{\n    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];\n    JPTestObjectBlock cbBlock = ^id(NSDictionary *dict, UIView *view) {\n        self.callBlockWithObjectAndBlockPassed = [dict[@\"str\"] isEqualToString:@\"stringFromJS\"] && [dict[@\"view\"] isKindOfClass:[UIView class]] && view.frame.size.width == 100;\n        return @\"succ\";\n    };\n    block(view, cbBlock);\n}\n\n- (void)callBlockWithDouble:(double(^)(double num))block\n{\n    double ret = block(4.2);\n    self.callBlockWithDoubleAndReturnDoublePassed = fabs(ret - 8.4) < 0.1;\n}\n\n#pragma mark - swizzle\n\ntypedef struct {\n    char *name;\n    int idx;\n}JPTestStruct;\n\n- (void)callSwizzleMethod\n{\n    [self funcToSwizzleWithString:@\"stringFromOC\" view:[[UIView alloc] init] int:42];\n    [self funcToSwizzle:4.2 view:[[UIView alloc] init]];\n    UIView *view = [self funcToSwizzleReturnView:[[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]];\n    self.funcToSwizzleReturnViewPassed = view.frame.size.width == 100;\n    \n    UIView *nilView = [self funcToSwizzleReturnView:nil];\n    self.funcToSwizzleParamNilPassed = !nilView;\n\n    int num = [self funcToSwizzleReturnInt:42];\n    self.funcToSwizzleReturnIntPassed = num == 42;\n    \n    [JPTestObject classFuncToSwizzle:self int:10];\n    id ret = [JPTestObject classFuncToSwizzleReturnObj:self];\n    if ([ret isKindOfClass:[JPTestObject class]]) {\n        self.classFuncToSwizzleReturnObjPassed = YES;\n    }\n    \n    int retI = [JPTestObject classFuncToSwizzleReturnInt:42];\n    if (retI == 42) {\n        self.classFuncToSwizzleReturnIntPassed = YES;\n    }\n    \n    double retD = [JPTestObject classFuncToSwizzleReturnDouble:100.0];\n    if (fabs(retD - 100.0) < FLT_EPSILON) {\n        self.classFuncToSwizzleReturnDoublePassed = YES;\n    }\n    \n    [self funcToSwizzleWithBlock:^(UIView *view, int num) {\n        self.funcToSwizzleWithBlockPassed = view && num == 42;\n    }];\n    \n    [self funcToSwizzle_withUnderLine_:42];\n    \n    CGRect rect = [self funcToSwizzleReturnRect:CGRectMake(0, 0, 100, 100)];\n    self.funcToSwizzleReturnRectPassed = rect.size.width == 100;\n    \n    CGPoint point = [self funcToSwizzleReturnPoint:CGPointMake(42, 42)];\n    self.funcToSwizzleReturnPointPassed = point.x == 42;\n    \n    CGSize size = [self funcToSwizzleReturnSize:CGSizeMake(42, 42)];\n    self.funcToSwizzleReturnSizePassed = size.width == 42;\n    \n    NSRange range = [self funcToSwizzleReturnRange:NSMakeRange(0, 42)];\n    self.funcToSwizzleReturnRangePassed = range.length == 42;\n    \n    UIEdgeInsets edgeInsets = [self funcToSwizzleReturnEdgeInsets:UIEdgeInsetsMake(42, 42, 0, 0)];\n    self.funcToSwizzleReturnEdgeInsetsPassed = edgeInsets.left == 42;\n    \n    SEL selector = [self funcToSwizzleTestSelector:@selector(funcToSwizzleTestSelector:)];\n    self.funcToSwizzleTestSelectorPassed = [NSStringFromSelector(selector) isEqualToString:@\"funcToSwizzleTestSelector:\"];\n    \n    char *cStr = [self funcToSwizzleTestChar:\"JSPatch\"];\n    self.funcToSwizzleTestCharPassed = strcmp(\"JSPatch\", cStr) == 0;\n    \n    Class myClass = [self funcToSwizzleReturnClass];\n    self.funcToSwizzleReturnClassPassed = [NSStringFromClass(myClass) isEqualToString:@\"UIView\"];\n    \n    JPTestStruct *testStruct = (JPTestStruct*)malloc(sizeof(JPTestStruct));\n    testStruct->idx = 42;\n    testStruct->name = \"JSPatch\";\n    \n    JPTestStruct *testStructReturn = [self funcToSwizzleTestPointer:testStruct];\n    self.funcToSwizzleTestPointerPassed = testStructReturn->idx == 42 && strcmp(testStructReturn->name, \"JSPatch\") == 0;\n}\n- (void)funcToSwizzleWithString:(NSString *)str view:(UIView *)view int:(NSInteger)i\n{\n    self.funcToSwizzleWithStringViewIntPassed = NO;\n}\n\n- (void)funcToSwizzle:(double)num view:(UIView *)view\n{\n    self.funcToSwizzleViewCalledOriginalPassed = 4.2 - num< 0.01 && view;\n}\n\n- (UIView *)funcToSwizzleReturnView:(UIView *)view\n{\n    return nil;\n}\n\n- (int)funcToSwizzleReturnInt:(int)num\n{\n    return 0;\n}\n\n- (NSDictionary *)funcToSwizzleReturnDictionary:(NSDictionary *)dict\n{\n    return nil;\n}\n\n- (NSDictionary *)funcToSwizzleReturnJSDictionary\n{\n    return nil;\n}\n\n- (NSArray *)funcToSwizzleReturnArray:(NSArray *)arr\n{\n    return nil;\n}\n\n- (NSString *)funcToSwizzleReturnString:(NSString *)str\n{\n    return nil;\n}\n\n- (void)funcToSwizzleWithBlock:(void(^)(UIView *view, int num))block\n{\n\n}\n\n- (void)funcToSwizzle_withUnderLine_:(int)num\n{\n    \n}\n\n- (CGRect)funcToSwizzleReturnRect:(CGRect)rect\n{\n    return CGRectZero;\n}\n- (CGPoint)funcToSwizzleReturnPoint:(CGPoint)point\n{\n    return CGPointZero;\n}\n- (CGSize)funcToSwizzleReturnSize:(CGSize)size\n{\n    return CGSizeZero;\n}\n- (NSRange)funcToSwizzleReturnRange:(NSRange)range\n{\n    return NSMakeRange(0, 0);\n}\n- (UIEdgeInsets)funcToSwizzleReturnEdgeInsets:(UIEdgeInsets)edgeInsets\n{\n    return UIEdgeInsetsZero;\n}\n\n- (void)funcToSwizzleTestGCD:(void(^)())block\n{\n    \n}\n\n- (Class)funcToSwizzleTestClass:(Class)cls\n{\n    return nil;\n}\n\n- (SEL)funcToSwizzleTestSelector:(SEL)selector\n{\n    return nil;\n}\n\n- (char *)funcToSwizzleTestChar:(char *)cStr\n{\n    return NULL;\n}\n\n- (char *)funcReturnChar\n{\n    return \"JSPatch\";\n}\n\n- (void)funcTestChar:(char *)cStr\n{\n    self.funcTestCharPassed = strcmp(\"JSPatch\", cStr) == 0;\n}\n\n- (void *)funcToSwizzleTestPointer:(void *)pointer\n{\n    return NULL;\n}\n\n- (BOOL)funcTestNSErrorPointer:(NSError **)error\n{\n    NSError *tmp = [[NSError alloc]initWithDomain:@\"com.albert43\" code:43 userInfo:@{@\"msg\":@\"test error\"}];\n    if (error)\n        *error = tmp;\n    \n    return NO;\n}\n\n- (void *)funcReturnPointer\n{\n    JPTestStruct *testStruct = (JPTestStruct*)malloc(sizeof(JPTestStruct));\n    testStruct->idx = 42;\n    testStruct->name = \"JSPatch\";\n    return testStruct;\n}\n\n- (void)funcTestPointer:(void *)pointer\n{\n    JPTestStruct *testStruct = pointer;\n    self.funcTestPointerPassed = testStruct->idx == 42 && strcmp(testStruct->name, \"JSPatch\") == 0;\n}\n\n- (BOOL)funcTestGetPointer1:(NSString *)str\n{\n    if ([str isEqualToString:@\"JSPatch\"]) {\n        return YES;\n    }\n    return NO;\n}\n\n- (BOOL)funcTestGetPointer2:(NSError *)error\n{\n    if ([[[error userInfo] description] isEqualToString:[@{@\"msg\":@\"test\"} description]]) {\n        return YES;\n    }\n    return NO;\n}\n\n- (BOOL)funcTestGetPointer3:(void *)arr\n{\n    char *p = arr;\n    for (int i = 0; i < 10; i++) {\n        if (p[i] != 'A') {\n            return false;\n        }\n    }\n    return true;\n}\n\ntypedef NSString * (^JSBlock)(NSError *);\n- (JSBlock)funcGenerateBlock {\n    JSBlock block = ^(NSError *err) {\n        if (err) {\n            return [err description];\n        }else {\n            return @\"no error\";\n        }\n    };\n    return block;\n}\n\n- (NSString *)excuteBlockWithNilParameters:(JSBlock)blk {\n    if (blk) {\n        return blk(nil);\n    }\n    return nil;\n}\n\n+ (void)classFuncToSwizzle:(JPTestObject *)testObject int:(NSInteger)i\n{\n    \n}\n\n+ (id)classFuncToSwizzleReturnObj:(JPTestObject *)obj\n{\n    obj.classFuncToSwizzleReturnObjCalledOriginalPassed = YES;\n    return nil;\n}\n\n+ (int)classFuncToSwizzleReturnInt:(int)i\n{\n    return 0;\n}\n\n+ (double)classFuncToSwizzleReturnDouble:(double)d\n{\n    return 0;\n}\n\n\n#pragma mark - super\n- (void)funcCallSuper\n{\n    self.funcCallSuperPassed = YES;\n}\n\n#pragma mark - performance\n- (void)pFuncVoid\n{\n    \n}\n- (int)pFuncReturnInt\n{\n    return 42;\n}\n- (void)pFuncParamInt:(int)num\n{\n    \n}\n- (id)pFuncReturnSelf\n{\n    return self;\n}\n- (void)pFuncParamSelf:(id)obj\n{\n    \n}\n\n#pragma mark - forward\n- (void)callTestForward\n{\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wundeclared-selector\"\n    [self performSelector:@selector(testForward) withObject:nil];\n#pragma clang diagnostic pop\n}\n- (void)funcToForward\n{\n    self.callForwardInvocationPassed = YES;\n}\n- (void)forwardInvocation:(NSInvocation *)anInvocation\n{\n    if ([NSStringFromSelector(anInvocation.selector) isEqualToString:@\"testForward\"]) {\n        [self funcToForward];\n    }\n}\n- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector\n{\n    if ([NSStringFromSelector(aSelector) isEqualToString:@\"funcToSwizzleRect:\"]) {\n        NSLog(@\"ss\");\n    }\n    if ([NSStringFromSelector(aSelector) isEqualToString:@\"testForward\"]) {\n        return [self methodSignatureForSelector:@selector(funcToForward)];\n    }\n    return [super methodSignatureForSelector:aSelector];\n}\n\n\n#pragma mark -\n- (NSString*)funcOverrideParentMethod\n{\n    return @\"orgi\";\n}\n\n#pragma mark CGAffineTransform\n- (CGAffineTransform)funcWithTransform:(CGAffineTransform)transform\n{\n    return transform;\n}\n\n#pragma mark structPointer\n- (void)funcWithRectPointer:(CGRect *)rect\n{\n    self.funcWithRectPointerPassed = rect->size.width == 100;\n    rect->origin.x = 42;\n}\n- (void)funcWithTransformPointer:(CGAffineTransform *)transform\n{\n    self.funcWithTransformPointerPassed = transform->a == 100;\n    transform->tx = 42;\n}\n\n\n@end\n\n\n\n@implementation JPTestSubObject\n- (instancetype)init\n{\n    self = [super init];\n    if (self) {\n        self.funcCallSuperSubObjectPassed = YES;\n    }\n    return self;\n}\n- (void)funcCallSuper\n{\n    self.funcCallSuperSubObjectPassed = NO;\n}\n\n@end\n\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wprotocol\"\n@implementation JPTestProtocolObject\n- (BOOL)testProtocolMethods\n{\n    double dNum = [self protocolWithDouble:4.2 dict:@{@\"name\": @\"JSPatch\"}];\n    NSInteger iNum = [self protocolWithInt:42];\n    NSString *str = [JPTestProtocolObject classProtocolWithString:@\"JSPatch\" int:42];\n    return dNum - 4.2 < 0.001 && iNum == 42 && [str isEqualToString:@\"JSPatch\"];\n}\n#pragma clang diagnostic pop\n@end\n\n@implementation JPTestSwizzledForwardInvocationSuperObject\n\n- (void)swizzleSuperForwoardInvocation\n{\n    class_replaceMethod([JPTestSwizzledForwardInvocationSuperObject class], @selector(forwardInvocation:), (IMP)SwizzledSuperForwardInvocation, \"v@:@\");\n}\n\nstatic void SwizzledSuperForwardInvocation(__unsafe_unretained id assignSlf, SEL selector, NSInvocation *invocation)\n{\n    if ([NSStringFromSelector(invocation.selector) isEqualToString:@\"testSwizzledSuperForwardInvocation\"]) {\n        ((JPTestSwizzledForwardInvocationSuperObject *)assignSlf).callSwizzledSuperForwardInvocationPassed = YES;\n    }\n}\n\n- (void)forwardInvocation:(NSInvocation *)anInvocation\n{\n    if ([NSStringFromSelector(anInvocation.selector) isEqualToString:@\"testSwizzledSuperForwardInvocation\"]) {\n        self.callSwizzledSuperForwardInvocationPassed = NO;\n    }\n}\n\n@end\n\n@implementation JPTestSwizzledForwardInvocationSubObject\n\n- (void)callTestSwizzledSuperForwardInvocation\n{\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wundeclared-selector\"\n    [self performSelector:@selector(testSwizzledSuperForwardInvocation) withObject:nil];\n#pragma clang diagnostic pop\n}\n\n- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector\n{\n    if ([NSStringFromSelector(aSelector) isEqualToString:@\"testSwizzledSuperForwardInvocation\"]) {\n        return [self methodSignatureForSelector:@selector(callTestSwizzledSuperForwardInvocation)];\n    }\n    return [super methodSignatureForSelector:aSelector];\n}\n\n@end\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/JSPatchTests.m",
    "content": "//\n//  InstaScriptTests.m\n//  InstaScriptTests\n//\n//  Created by bang on 15/4/30.\n//  Copyright (c) 2015 bang. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n#import <XCTest/XCTest.h>\n#import \"JPEngine.h\"\n#import \"JPTestObject.h\"\n#import \"JPInheritanceTestObjects.h\"\n#import \"JPMultithreadTestObject.h\"\n#import \"newProtocolTest.h\"\n#import \"JPSuperTestObject.h\"\n#import \"JPJSClassTest.h\"\n#import \"JPMemory.h\"\n#import \"JPPerformanceTest.h\"\n#import \"JPCFunctionTest.h\"\n#import \"JPNumberTest.h\"\n#import \"newBlockTest.h\"\n\n@interface JSPatchTests : XCTestCase\n\n@end\n\n@implementation JSPatchTests\n- (void)loadPatch:(NSString *)patchName\n{\n    NSString *jsPath = [[NSBundle bundleForClass:[self class]] pathForResource:patchName ofType:@\"js\"];\n    [JPEngine evaluateScriptWithPath:jsPath];\n}\n\n- (void)setUp {\n    [super setUp];\n    [JPEngine startEngine];\n    [JPEngine addExtensions:@[@\"JPMemory\", @\"JPStructPointer\", @\"JPCoreGraphics\", @\"JPUIKit\"]];\n}\n\n- (void)tearDown {\n    [super tearDown];\n}\n\n- (void)testEngine {\n    \n    [self loadPatch:@\"test\"];\n    \n    JSValue *objValue = [JPEngine context][@\"ocObj\"];\n    JPTestObject *obj = [objValue toObjectOfClass:[JPTestObject class]];\n    JSValue *subObjValue = [JPEngine context][@\"subObj\"];\n    JPTestSubObject *subObj = [subObjValue toObjectOfClass:[JPTestSubObject class]];\n    \n    XCTAssert(obj.funcReturnVoidPassed, @\"funcReturnVoidPassed\");\n    \n    XCTAssert(obj.funcReturnStringPassed, @\"funcReturnStringPassed\");\n    \n    XCTAssert(obj.funcReturnClassPassed, @\"funcReturnClassPassed\");\n    \n    // Test for functions which return double/float, cause there's a fatal bug in NSInvocation on iOS7.0\n    // This case shall fail if you comment line 957~959 in JPEngine.m on iOS7.0.\n    XCTAssert(obj.funcReturnDoublePassed, @\"funcReturnDoublePassed\");\n    \n    XCTAssert(obj.funcWithIntPassed, @\"funcWithIntPassed\");\n    XCTAssert(obj.funcWithNilPassed, @\"funcWithNilPassed\");\n    XCTAssert(obj.funcReturnNilPassed, @\"funcReturnNilPassed\");\n    XCTAssert(obj.funcWithNilAndOthersPassed, @\"funcWithNilAndOthersPassed\");\n    XCTAssert(obj.funcWithNullPassed, @\"funcWithNullPassed\");\n    XCTAssert(obj.funcTestBoolPassed, @\"funcTestBoolPassed\");\n    XCTAssert(obj.funcTestNSNumberPassed, @\"funcTestNSNumberPassed\");\n    \n    XCTAssert(obj.funcWithDictAndDoublePassed, @\"funcWithDictAndDoublePassed\");\n    \n    XCTAssert(obj.funcWithRectAndReturnRectPassed, @\"funcWithRectAndReturnRectPassed\");\n    XCTAssert(obj.funcWithSizeAndReturnSizePassed, @\"funcWithSizeAndReturnSizePassed\");\n    XCTAssert(obj.funcWithPointAndReturnPointPassed, @\"funcWithPointAndReturnPointPassed\");\n    XCTAssert(obj.funcWithRangeAndReturnRangePassed, @\"funcWithRangeAndReturnRangePassed\");\n    XCTAssert(obj.funcWithClassAndReturnStringPassed, @\"funcWithClassAndReturnInstancePassed\");\n    \n    XCTAssert(obj.funcReturnViewWithFramePassed, @\"funcReturnViewWithFramePassed\");\n    XCTAssert(obj.funcWithViewAndReturnViewPassed, @\"funcWithViewAndReturnViewPassed\");\n    \n    XCTAssert(obj.funcReturnDictStringViewPassed, @\"funcReturnDictStringViewPassed\");\n    XCTAssert(obj.funcReturnDictStringIntPassed, @\"funcReturnDictStringIntPassed\");\n    XCTAssert(obj.funcReturnArrayControllerViewStringPassed, @\"funcReturnArrayControllerViewStringPassed\");\n    XCTAssert(obj.funcReturnDictPassed, @\"funcReturnDictPassed\");\n    XCTAssert(obj.funcReturnDictPassed, @\"testBoxingObjPassed\");\n    \n    XCTAssert(obj.funcReturnBlockPassed, @\"funcReturnBlockPassed\");\n    XCTAssert(obj.funcReturnObjectBlockPassed, @\"funcReturnObjectBlockPassed\");\n    XCTAssert(obj.funcReturnObjectBlockReturnValuePassed, @\"funcReturnObjectBlockReturnValuePassed\");\n    XCTAssert(obj.funcReturnJSBlockPassed, @\"funcReturnBlockPassed\");\n    XCTAssert(obj.callBlockWithStringAndIntPassed, @\"callBlockWithStringAndIntPassed\");\n    XCTAssert(obj.callBlockWithStringAndIntReturnValuePassed, @\"callBlockWithStringAndIntReturnValuePassed\");\n    XCTAssert(obj.callBlockWithArrayAndViewPassed, @\"callBlockWithArrayAndViewPassed\");\n    XCTAssert(obj.callBlockWithBoolAndBlockPassed, @\"callBlockWithBoolAndBlockPassed\");\n    XCTAssert(obj.callBlockWithObjectAndBlockPassed, @\"callBlockWithObjectAndBlockPassed\");\n    XCTAssert(obj.callBlockWithObjectAndBlockReturnValuePassed, @\"callBlockWithObjectAndBlockReturnValuePassed\");\n    XCTAssert(obj.callBlockWithDoubleAndReturnDoublePassed, @\"callBlockWithDoubleAndReturnDoublePassed\");\n    \n    \n    XCTAssert(obj.funcToSwizzleWithStringViewIntPassed, @\"funcToSwizzleWithStringViewIntPassed\");\n    XCTAssert(obj.funcToSwizzleViewPassed, @\"funcToSwizzleViewPassed\");\n    XCTAssert(obj.funcToSwizzleViewCalledOriginalPassed, @\"funcToSwizzleViewCalledOriginalPassed\");\n    XCTAssert(obj.funcToSwizzleReturnViewPassed, @\"funcToSwizzleReturnViewPassed\");\n    XCTAssert(obj.funcToSwizzleParamNilPassed, @\"funcToSwizzleParamNilPassed\");\n    XCTAssert(obj.funcToSwizzleReturnIntPassed, @\"funcToSwizzleReturnIntPassed\");\n    XCTAssert(obj.funcToSwizzleWithBlockPassed, @\"funcToSwizzleWithBlockPassed\");\n    XCTAssert(obj.funcToSwizzle_withUnderLine_Passed, @\"funcToSwizzle_withUnderLine_Passed\");\n    XCTAssert(obj.funcToSwizzleReturnRectPassed, @\"funcToSwizzleReturnRectPassed\");\n    XCTAssert(obj.funcToSwizzleReturnPointPassed, @\"funcToSwizzleReturnPointPassed\");\n    XCTAssert(obj.funcToSwizzleReturnSizePassed, @\"funcToSwizzleReturnSizePassed\");\n    XCTAssert(obj.funcToSwizzleReturnRangePassed, @\"funcToSwizzleReturnRangePassed\");\n    XCTAssert(obj.funcToSwizzleReturnEdgeInsetsPassed, @\"funcToSwizzleReturnEdgeInsetsPassed\");\n    \n    \n    XCTAssert(obj.funcToSwizzleReturnRectJSPassed, @\"funcToSwizzleReturnRectJSPassed\");\n    XCTAssert(obj.funcToSwizzleReturnPointJSPassed, @\"funcToSwizzleReturnPointJSPassed\");\n    XCTAssert(obj.funcToSwizzleReturnSizeJSPassed, @\"funcToSwizzleReturnSizeJSPassed\");\n    XCTAssert(obj.funcToSwizzleReturnRangeJSPassed, @\"funcToSwizzleReturnRangeJSPassed\");\n    XCTAssert(obj.funcToSwizzleReturnEdgeInsetsJSPassed, @\"funcToSwizzleReturnEdgeInsetsJSPassed\");\n    \n    \n    XCTAssert(obj.funcToSwizzleTestClassPassed, @\"funcToSwizzleTestClassPassed\");\n    XCTAssert(obj.funcToSwizzleTestSelectorPassed, @\"funcToSwizzleTestSelectorPassed\");\n    XCTAssert(obj.funcToSwizzleTestCharPassed, @\"funcToSwizzleTestCharPassed\");\n    XCTAssert(obj.funcToSwizzleTestClassPassed,@\"funcToSwizzleTestClassPassed\");\n    XCTAssert(obj.funcTestCharPassed, @\"funcTestCharPassed\");\n    XCTAssert(obj.funcToSwizzleTestPointerPassed, @\"funcToSwizzleTestPointerPassed\");\n    XCTAssert(obj.funcTestPointerPassed, @\"funcTestPointerPassed\");\n    XCTAssert(obj.funcTestSizeofPassed,@\"funcSizeofPassed\");\n    XCTAssert(obj.funcTestGetPointerPassed, @\"funcGetPointerPassed\");\n    XCTAssert(obj.funcTestNSErrorPointerPassed, @\"funcTestNSErrorPointerPassed\");\n    XCTAssert(obj.funcTestNilParametersInBlockPassed, @\"funcTestNilParametersInBlockPassed\");\n    NSDictionary *originalDict = @{@\"k\": @\"v\"};\n    NSDictionary *dict = [obj funcToSwizzleReturnDictionary:originalDict];\n    XCTAssert(originalDict == dict, @\"funcToSwizzleReturnDictionary\");\n    \n    dict = [obj funcToSwizzleReturnJSDictionary];\n    XCTAssertEqualObjects(dict[@\"str\"], @\"js_string\", @\"funcToSwizzleReturnJSDictionary\");\n    \n    NSArray *originalArr = @[@\"js\", @\"patch\"];\n    NSArray *arr = [obj funcToSwizzleReturnArray:originalArr];\n    XCTAssert(originalArr == arr, @\"funcToSwizzleReturnArray\");\n    \n    NSString *originalStr = @\"JSPatch\";\n    NSString *str = [obj funcToSwizzleReturnString:originalStr];\n    XCTAssert(originalStr == str, @\"funcToSwizzleReturnString\");\n    \n    \n    XCTAssert(obj.classFuncToSwizzlePassed, @\"classFuncToSwizzlePassed\");\n    XCTAssert(obj.classFuncToSwizzleReturnObjPassed, @\"classFuncToSwizzleReturnObjPassed\");\n    XCTAssert(obj.classFuncToSwizzleReturnObjCalledOriginalPassed, @\"classFuncToSwizzleReturnObjCalledOriginalPassed\");\n    XCTAssert(obj.classFuncToSwizzleReturnIntPassed, @\"classFuncToSwizzleReturnIntPassed\");\n    // Test for functions which return double/float, cause there's a fatal bug in NSInvocation on iOS7.0\n    // This case shall fail if you comment line 1050~1052 in JPEngine.m on iOS7.0.\n    XCTAssert(obj.classFuncToSwizzleReturnDoublePassed, @\"classFuncToSwizzleReturnDoublePassed\");\n    \n    XCTAssert(subObj.funcCallSuperSubObjectPassed, @\"funcCallSuperSubObjectPassed\");\n    XCTAssert(subObj.funcCallSuperPassed, @\"funcCallSuperPassed\");\n    XCTAssert(obj.callForwardInvocationPassed, @\"callForwardInvocationPassed\");\n    \n    JPTestSwizzledForwardInvocationSubObject *tmp = [[JPTestSwizzledForwardInvocationSubObject alloc] init];\n    [tmp callTestSwizzledSuperForwardInvocation];\n    XCTAssert(!tmp.callSwizzledSuperForwardInvocationPassed);\n    [tmp swizzleSuperForwoardInvocation];\n    [tmp callTestSwizzledSuperForwardInvocation];\n    XCTAssert(tmp.callSwizzledSuperForwardInvocationPassed);\n    \n    XCTAssert(obj.propertySetFramePassed, @\"propertySetFramePassed\");\n    XCTAssert(obj.propertySetViewPassed, @\"propertySetViewPassed\");\n    \n    XCTAssert(obj.newTestObjectReturnViewPassed, @\"newTestObjectReturnViewPassed\");\n    XCTAssert(obj.newTestObjectReturnBoolPassed, @\"newTestObjectReturnBoolPassed\");\n\n    XCTAssert(obj.mutableArrayPassed, @\"mutableArrayPassed\");\n    XCTAssert(obj.mutableDictionaryPassed, @\"mutableDictionaryPassed\");\n    XCTAssert(obj.mutableStringPassed, @\"mutableStringPassed\");\n    \n    XCTAssert(obj.funcWithTransformPassed, @\"funcWithTransformPassed\");\n    XCTAssert(obj.transformTranslatePassed, @\"funcWithTransformPassed\");\n    XCTAssert(obj.funcWithRectPointerPassed, @\"funcWithRectPointerPassed\");\n    XCTAssert(obj.funcWithTransformPointerPassed, @\"funcWithTransformPointerPassed\");\n    \n    XCTAssertEqualObjects(@\"overrided\",[subObj funcOverrideParentMethod]);\n    \n    XCTAssert(obj.variableParameterMethodPassed, @\"variableParameterMethodPassed\");\n    \n    \n    JPTestProtocolObject *testProtocolObj = [[JPTestProtocolObject alloc] init];\n    XCTAssert([testProtocolObj testProtocolMethods], @\"testProtocolMethodsPassed\");\n    \n    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);\n    [obj funcToSwizzleTestGCD:^{\n        XCTAssert(obj.funcToSwizzleTestGCDPassed, @\"funcToSwizzleTestGCDPassed\");\n        dispatch_semaphore_signal(semaphore);\n    }];\n    \n    while (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW))\n        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode\n                                 beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]];\n}\n\n- (void)testJSClass\n{\n    [self loadPatch:@\"jsClassTest\"];\n    XCTAssert([JPJSClassTest isPassA]);\n    XCTAssert([JPJSClassTest isPassB]);\n    XCTAssert([JPJSClassTest isPassC]);\n}\n\n- (void)testSuperClass\n{\n    [self loadPatch:@\"superTest\"];\n    XCTAssert([JPSuperTestResult isPassA]);\n    XCTAssert([JPSuperTestResult isPassB]);\n    XCTAssert([JPSuperTestResult isPassC]);\n}\n\n- (void)testInheritance\n{\n    /*get values before patch*/\n    id t1objB = [[JPInheritTest01ObjectB alloc] init];\n    NSString* t1m1Return = [t1objB m1];\n    NSString* t1m2Return = [t1objB m2];\n    \n    id t2objA = [[JPInheritTest02ObjectA alloc] init];\n    id t2objB = [[JPInheritTest02ObjectB alloc] init];\n    id t2objC = [[JPInheritTest02ObjectC alloc] init];\n    NSString* t2m1Return = [t2objA m1];\n    NSString* t2m2Return = [t2objA m2];\n    NSString* t2Bm1Return = [t2objB m1];\n    NSString* t2Bm2Return = [t2objB m2];\n    NSString* t2Cm1Return = [t2objC m1];\n    NSString* t2Cm2Return = [t2objC m2];\n    \n    id t3objA = [[JPInheritTest03ObjectA alloc] init];\n    id t3objB = [[JPInheritTest03ObjectB alloc] init];\n    id t3objC = [[JPInheritTest03ObjectC alloc] init];\n    NSString* t3m1Return = [t3objA m1];\n    NSString* t3m2Return = [t3objA m2];\n    NSString* t3Bm1Return = [t3objB m1];\n    NSString* t3Bm2Return = [t3objB m2];\n    NSString* t3Cm1Return = [t3objC m1];\n    NSString* t3Cm2Return = [t3objC m2];\n    \n    [self loadPatch:@\"inheritTest\"];\n    \n    /*Test 1*/\n    XCTAssertNotEqualObjects(t1m1Return, [t1objB m1]);\n    XCTAssertEqualObjects(@\"JP_01ObjB_m1\", [t1objB m1]);\n    XCTAssertEqualObjects(t1m2Return,[t1objB m2]);\n    \n    /*Test 2*/\n    XCTAssertEqualObjects(t2m1Return,[t2objA m1]);\n    XCTAssertEqualObjects(t2m2Return,[t2objA m2]);\n    \n    XCTAssertNotEqualObjects(t2Bm1Return,[t2objB m1]);\n    XCTAssertEqualObjects(@\"JP_02ObjB_m1\",[t2objB m1]);\n    \n    XCTAssertEqualObjects(t2Bm2Return,[t2objB m2]);\n    \n    XCTAssertNotEqualObjects(t2Cm1Return,[t2objC m1]);\n    XCTAssertEqualObjects(@\"JP_02ObjB_m1\",[t2objC m1]);\n    \n    XCTAssertNotEqualObjects(t2Cm2Return,[t2objC m2]);\n    XCTAssertEqualObjects(@\"JP_02ObjC_m2\",[t2objC m2]);\n    \n    XCTAssertEqualObjects(@\"JP_02ObjC_m3\", [t2objC m3]);\n    \n    /*Test 3*/\n    XCTAssertEqualObjects(t3m1Return,[t3objA m1]);\n    XCTAssertEqualObjects(t3m2Return,[t3objA m2]);\n    \n    XCTAssertNotEqualObjects(t3Bm1Return,[t3objB m1]);\n    XCTAssertEqualObjects(@\"JP_03ObjB_m1\",[t3objB m1]);\n    \n    XCTAssertEqualObjects(t3Bm2Return,[t3objB m2]);\n    \n    XCTAssertEqualObjects(t3Cm1Return,[t3objC m1]);\n    \n    XCTAssertNotEqualObjects(t3Cm2Return,[t3objC m2]);\n    XCTAssertEqualObjects(@\"JP_03ObjC_m2\",[t3objC m2]);\n}\n\n\n- (void)testCFunction\n{\n    [self loadPatch:@\"jsCFunctionTest\"];\n    XCTAssert([JPCFunctionTest testCfuncWithCGSize], @\"testCfuncWithCGSize\");\n    XCTAssert([JPCFunctionTest testCfuncWithCGRect], @\"testCfuncWithCGRect\");\n    XCTAssert([JPCFunctionTest testCfuncWithId], @\"testCfuncWithId\");\n    XCTAssert([JPCFunctionTest testCfuncWithInt], @\"testCfuncWithInt\");\n    XCTAssert([JPCFunctionTest testCfuncWithCGFloat], @\"testCfuncWithCGFloat\");\n    XCTAssert([JPCFunctionTest testCfuncReturnPointer], @\"testCfuncReturnPointer\");\n    XCTAssert([JPCFunctionTest testCFunctionReturnClass], @\"testCFunctionReturnClass\");\n    XCTAssert([JPCFunctionTest testCFunctionVoid], @\"testCFunctionVoid\");\n}\n\n#pragma mark - jsNumberTest\n\n- (void)testJPNumber {\n    [self loadPatch:@\"jsNumberTest\"];\n    XCTAssert([JPNumberTest testJPNumNSNumber], @\"testJPNumNSNumber\");\n    XCTAssert([JPNumberTest testJPNumNSDecimalNumber], @\"testJPNumNSDecimalNumber\");\n    XCTAssert([JPNumberTest testJPNumToJS], @\"testJPNumToJS\");\n    XCTAssert([JPNumberTest testJPNUmToOC], @\"testJPNumToOC\");\n}\n\n#pragma mark - multithreadTest\n\ndispatch_semaphore_t sem;\nint finishcount = 0;\nbool success = false;\n#define LOOPCOUNT 100\nvoid thread(void* context);\n\n- (void)testDispatchQueue\n{\n    [self loadPatch:@\"multithreadTest\"];\n    \n    success = false;\n    NSMutableArray *objs = [[NSMutableArray alloc] init];\n    for (int i = 0; i < LOOPCOUNT; i++) {\n        JPMultithreadTestObject *obj = [[JPMultithreadTestObject alloc] init];\n        obj.objectId = i;\n        [objs addObject:obj];\n    }\n    \n    dispatch_queue_t q1 = dispatch_queue_create(\"serial queue\", DISPATCH_QUEUE_SERIAL);\n    for (int i = 0; i < LOOPCOUNT; i++) {\n        dispatch_async_f(q1, (__bridge void*)[objs objectAtIndex:i], thread);\n    }\n    \n    sem = dispatch_semaphore_create(0);\n    dispatch_semaphore_wait(sem,DISPATCH_TIME_FOREVER);\n    \n    XCTAssertTrue(success,@\"serial queue test failed\");\n    \n    success = false;\n    dispatch_queue_t q2 = dispatch_queue_create(\"concurrent queue\", DISPATCH_QUEUE_CONCURRENT);\n    for (int i = 0; i < LOOPCOUNT; i++) {\n        dispatch_async_f(q2, (__bridge void*)[objs objectAtIndex:i], thread);\n    }\n    \n    sem = dispatch_semaphore_create(0);\n    dispatch_semaphore_wait(sem,DISPATCH_TIME_FOREVER);\n    \n    XCTAssertTrue(success,@\"concurrent queue test failed\");\n}\n\n\nvoid thread(void* context)\n{\n    JPMultithreadTestObject *obj = (__bridge JPMultithreadTestObject*)context;\n    for (int i = 0; i < LOOPCOUNT; i++) {\n        [obj addValue:[NSNumber numberWithInt:obj.objectId]];\n    }\n    \n    finishcount++;\n    \n    if (![obj checkAllValues]) {\n        NSLog(@\"found wrong data in object %d\", obj.objectId);\n        dispatch_semaphore_signal(sem);\n        return;\n    }\n    \n    if (finishcount == LOOPCOUNT) {\n        finishcount = 0;\n        success = true;\n        dispatch_semaphore_signal(sem);\n    }\n}\n\n\n\n\n#pragma mark - performance\n- (void)testJSCallEmptyMethodPerformance\n{\n    [self loadPatch:@\"performanceTest\"];\n    JPPerformanceTest *obj = [[JPPerformanceTest alloc] init];\n    [self measureBlock:^{\n        [obj testJSCallOCEmptyMethod];\n    }];\n}\n\n- (void)testJSCallMethodWithParamObjectPerformance\n{\n    [self loadPatch:@\"performanceTest\"];\n    JPPerformanceTest *obj = [[JPPerformanceTest alloc] init];\n    [self measureBlock:^{\n        [obj testJSCallOCMethodWithParamObject];\n    }];\n}\n- (void)testJSCallMethodReturnObjectPerformance\n{\n    [self loadPatch:@\"performanceTest\"];\n    JPPerformanceTest *obj = [[JPPerformanceTest alloc] init];\n    [self measureBlock:^{\n        [obj testJSCallOCMethodReturnObject];\n    }];\n}\n- (void)testOCCallJSEmptyMethodPerformance\n{\n    [self loadPatch:@\"performanceTest\"];\n    JPPerformanceTest *obj = [[JPPerformanceTest alloc] init];\n    [self measureBlock:^{\n        [obj testOCCallEmptyMethod];\n    }];\n}\n- (void)testOCCallJSMethodWithParamObjectPerformance\n{\n    [self loadPatch:@\"performanceTest\"];\n    JPPerformanceTest *obj = [[JPPerformanceTest alloc] init];\n    [self measureBlock:^{\n        [obj testOCCallMethodWithParamObject];\n    }];\n}\n- (void)testOCCallJSMethodReturnObjectPerformance\n{\n    [self loadPatch:@\"performanceTest\"];\n    JPPerformanceTest *obj = [[JPPerformanceTest alloc] init];\n    [self measureBlock:^{\n        [obj testOCCallMethodReturnObject];\n    }];\n}\n\n- (void)testJSCallJSEmptyMethod\n{\n    [self loadPatch:@\"performanceTest\"];\n    JPPerformanceTest *obj = [[JPPerformanceTest alloc] init];\n    [self measureBlock:^{\n        [obj testJSCallJSEmptyMethod];\n    }];\n}\n\n- (void)testJSCallJSMethodWithParam\n{\n    [self loadPatch:@\"performanceTest\"];\n    JPPerformanceTest *obj = [[JPPerformanceTest alloc] init];\n    [self measureBlock:^{\n        [obj testJSCallJSMethodWithParam];\n    }];\n}\n\n- (void)testJSCallJSMethodWithLargeDictionaryParam\n{\n    [self loadPatch:@\"performanceTest\"];\n    JPPerformanceTest *obj = [[JPPerformanceTest alloc] init];\n    [self measureBlock:^{\n        [obj testJSCallJSMethodWithLargeDictionaryParam];\n    }];\n}\n\n- (void)testJSCallJSMethodWithLargeDictionaryParamAutoConvert\n{\n    [self loadPatch:@\"performanceTest\"];\n    JPPerformanceTest *obj = [[JPPerformanceTest alloc] init];\n    [self measureBlock:^{\n        [obj testJSCallJSMethodWithLargeDictionaryParamAutoConvert];\n    }];\n}\n\n- (void)testJSCallMallocJPMemory\n{\n    [self loadPatch:@\"performanceTest\"];\n    JPPerformanceTest *obj = [[JPPerformanceTest alloc] init];\n    [self measureBlock:^{\n        [obj testJSCallMallocJPMemory];\n    }];\n}\n\n- (void)testJSCallMallocJPCFunction\n{\n    [self loadPatch:@\"performanceTest\"];\n    JPPerformanceTest *obj = [[JPPerformanceTest alloc] init];\n    [self measureBlock:^{\n        [obj testJSCallMallocJPCFunction];\n    }];\n}\n\n- (void)testNewBlock {\n    [self loadPatch:@\"newBlockTest\"];\n    newBlockTest *obj = [[newBlockTest alloc] init];\n    [obj removeJPBlock];\n    [obj testJSBlockToOCCall];\n    XCTAssert(obj.success, @\"testJSBlockToOCCall\");\n}\n\n- (void)testNewProtocol{\n    [self loadPatch:@\"newProtocolTest\"];\n    \n    //Protocol baseTest\n    baseTestProtocolObject *baseTest = [baseTestProtocolObject new];\n    int retBaseTest1 = [baseTest testProtocol:YES];\n    XCTAssertEqual(retBaseTest1, 1);\n    \n    [baseTest test2Protocol:2];\n    [baseTest test3Protocol:NO withB:0.2f withC:3.4f];\n    NSLog(@\"new protocol base test end\");\n    \n    //Protocol structTest\n    structTestProtocolObject *structTest = [structTestProtocolObject new];\n    int retStructTest1 = [structTest testProtocol:CGRectZero];\n    XCTAssertEqual(retStructTest1, 1);\n    CGPoint retStructTest2 = [structTest test2Protocol:CGSizeZero];\n    XCTAssertTrue(CGPointEqualToPoint(retStructTest2, CGPointMake(100, 100)));\n    CGSize retStructTest3 = [structTest test3Protocol:CGRectZero withB:3.1f withC:4];\n    XCTAssertTrue(CGSizeEqualToSize(retStructTest3, CGSizeMake(100, 100)));\n    NSLog(@\"new protocol struct test end\");\n    \n    //Protocol objectTest\n    objectTestProtocolObject *objectTest = [objectTestProtocolObject new];\n    int retObjectTest1 = [objectTest testProtocol:@\"teststring\"];\n    XCTAssertEqual(retObjectTest1, 1);\n    int retObjectTest2 = [objectTest test2Protocol:@\"teststring\"];\n    XCTAssertEqual(retObjectTest2, 1);\n    CGSize retObjectTest3 = [objectTest test3Protocol:@[@1,@2] withB:@\"teststring\" withC:2];\n    XCTAssertTrue(CGSizeEqualToSize(retObjectTest3, CGSizeMake(100, 100)));\n    NSLog(@\"new protocol object test end\");\n    \n    //Protocol sepcialTest\n    specialTestProtocolObject *specialTest = [specialTestProtocolObject new];\n    [specialTest testProtocol:@selector(viewDidLoad)];\n    [specialTest test2Protocol:^{\n        NSLog(@\"11\");\n    }];\n    [specialTest test3Protocol:0.5f withB:^{\n        NSLog(@\"11\");\n    } withC:@selector(viewDidLoad)];\n    NSLog(@\"new protocol special test end\");\n    \n    //Protocol typeEncodeTest\n    typeEncodeTestProtocolObject *encodeTest = [typeEncodeTestProtocolObject new];\n    [encodeTest testProtocol:@\"teststring\"];\n    NSString* retEncodeTest2 = [encodeTest test2Protocol:@[@1,@2] withB:@\"testtest\"];\n    XCTAssertTrue([retEncodeTest2 isEqualToString:@\"string\"]);\n    NSLog(@\"new protocol encode test end\");\n    \n    \n    //Protocol classTest\n    int retClassTest1 = [classTestProtocolObject testProtocol:@\"teststring\"];\n    XCTAssertEqual(retClassTest1, 1);\n    int retClassTest2 = [classTestProtocolObject test2Protocol:@\"teststring\"];\n    XCTAssertEqual(retClassTest2, 1);\n    CGSize retClassTest3 = [classTestProtocolObject test3Protocol:@[@1,@2] withB:@\"teststring\" withC:2];\n    XCTAssertTrue(CGSizeEqualToSize(retClassTest3, CGSizeMake(100, 100)));\n    NSLog(@\"new protocol object test end\");\n}\n\n@end\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/jsCFunctionTest.js",
    "content": "require('JPEngine').addExtensions(['JPCFunction'])\nrequire('JPEngine').defineStruct({\n    \"name\": \"CGSize\",\n    \"types\": \"FF\",\n    \"keys\": [\"width\", \"height\"]\n});\nrequire('JPEngine').defineStruct({\n    \"name\": \"CGPoint\",\n    \"types\": \"FF\",\n    \"keys\": [\"x\", \"y\"]\n});\nrequire('JPEngine').defineStruct({\n    \"name\": \"CGRect\",\n    \"types\": \"{CGPoint}{CGSize}\",\n    \"keys\": [\"origin\", \"size\"]\n});\n\ndefineClass('JPCFunctionTest', {}, {\n    testCfuncWithCGSize: function() {\n        defineCFunction(\"cfuncWithCGSize\", \"{CGSize}, {CGSize}\")\n        var ret = cfuncWithCGSize({width:1, height:2});\n        return ret.width == 1 && ret.height == 2;\n    },\n    testCfuncWithCGRect: function() {\n        defineCFunction(\"cfuncWithCGRect\", \"{CGRect}, {CGRect}\")\n        var ret = cfuncWithCGRect({origin:{x:1,y:2},size:{width:3, height:4}});\n        console.log(\"testCfuncWithCGRect\", JSON.stringify(ret), ret.origin, ret.origin.x);\n        return ret.origin.x == 1 && ret.origin.y == 2 && ret.size.width == 3 && ret.size.height == 4;\n    },\n    testCfuncWithId: function() {\n        defineCFunction(\"cfuncWithId\", \"id, NSString *\")\n        var ret = cfuncWithId(\"JSPatch\");\n        return ret.toJS() == \"JSPatch\";\n    },\n    testCfuncWithInt: function() {\n        defineCFunction(\"cfuncWithInt\", \"int, int\")\n        return cfuncWithInt(42) == 42\n    },\n    testCfuncWithCGFloat: function() {\n        defineCFunction(\"cfuncWithCGFloat\", \"CGFloat, CGFloat\")\n        return cfuncWithCGFloat(42.2) - 42.2 < 0.1\n    },\n    testCfuncReturnPointer: function() {\n        defineCFunction(\"cfuncReturnPointer\", \"void*\")\n        defineCFunction(\"cfuncWithPointerIsEqual\", \"bool, void*\")\n        var ptr = cfuncReturnPointer()\n        return cfuncWithPointerIsEqual(ptr)\n    },\n    testCFunctionReturnClass: function() {\n        defineCFunction(\"NSClassFromString\", \"Class, NSString *\")\n        var viewCls = NSClassFromString(\"UIView\")\n        var view = require('UIView').alloc().init()\n        return view.isKindOfClass(viewCls);\n    },\n    testCFunctionVoid: function() {\n        defineCFunction(\"cfuncVoid\", \"void\")\n        self.setupCFunctionVoidSucc();\n        return self.ORIGtestCFunctionVoid();\n    },\n})\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/jsClassTest.js",
    "content": "defineClass('JSClsA', ['prop1', 'prop2'], {\n    init: function(){\n        self = self.super().init();\n        self.setProp1('1');\n        self.setProp2('2');\n        return self;\n    },\n    _privateMethod: function() {\n        return 'P';\n    },\n    method: function() {\n        return 'A' + self.prop1() + self.prop2();\n    },\n}, {\n    clsMethod: function() {\n        return 'A'\n    },\n})\n\n\n\n\ndefineClass('JSSuperTestA', {\n    method: function(){\n        return 'A'\n    }\n})\n\ndefineClass('JSSuperTestA1: JSSuperTestA', {\n    method: function(){\n        return self.super().method() + '1'\n    }\n})\n\ndefineClass('JSSuperTestA2: JSSuperTestA1', {\n    method: function(){\n        return self.super().method() + '2'\n    }\n})\n\n\ndefineJSClass('JSClassA', {\n    init: function() {\n        this.prop1 = 'A'\n        return this\n    },\n    method: function() {\n        return this.prop1\n    }\n}, {\n    clsMethod: function() {\n        return '1'\n    }\n})\n\ndefineJSClass('JSClassA1: JSClassA', {\n    method: function() {\n        return this.super().method() + '1'; //should be 'A1'\n    }\n})\n\ndefineJSClass('JSClassA2: JSClassA1', {\n    method: function() {\n        return this.super().method() + '2'; //should be 'A12'\n    }\n})\n\n\ndefineClass('JPJSClassTest', {}, {\n    isPassA: function() {\n        var o = JSClsA.alloc().init();\n        return o.method() == 'A12' && o._privateMethod() == 'P' && JSClsA.clsMethod() == 'A';\n    },\n    isPassB: function() {\n        var o = JSSuperTestA2.alloc().init();\n        return o.method() == 'A12';\n    },\n    isPassC: function() {\n        var o = JSClassA2.alloc().init();\n        return o.method() == 'A12' && JSClassA.clsMethod() == '1';\n    }\n})\n\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/jsNumberTest.js",
    "content": "require('JPEngine').addExtensions(['JPNumber'])\n\ndefineClass('JPNumberTest', {}, {\n    testJPNumNSNumber: function() {\n        var oc_n = OCNumber(\"NSNumber\", \"numberWithInt:\", [233])\n        \n        return oc_n.compare(233) == 0\n    },\n    testJPNumNSDecimalNumber: function() {\n        var oc_n = OCNumber(\"NSDecimalNumber\", \"decimalNumberWithMantissa:exponent:isNegative:\", [10, 2, 0])\n        return oc_n.compare(1000) == 0\n    },\n    testJPNumToJS: function() {\n        var oc_n = OCNumber(\"NSNumber\", \"numberWithFloat:\", [0.14])\n        var js_n = toJSNumber(oc_n)\n        return js_n + 3 - 3.14 < 0.0001\n    },\n    testJPNUmToOC: function() {\n        var oc_n = toOCNumber(2.14)\n        return oc_n.compare(2.14) == 0\n    }\n})"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/multithreadTest.js",
    "content": "var global = this;\n\n(function() {\n\t\n  defineClass('JPMultithreadTestObject', {\n    addValueJS: function(num) {\n      self.addValue(num);\n    },\n    addValue: function(num) {\n      self.ORIGaddValue(num);\n    }\n  });\n\n})();"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/newBlockTest.h",
    "content": "//\n//  newBlockTest.h\n//  JSPatchTests\n//\n//  Created by WELCommand on 2018/3/27.\n//  Copyright © 2018年 bang. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import <UIKit/UIKit.h>\n\n@interface newBlockTest : NSObject\n\n@property (nonatomic, assign) BOOL success;\n\n- (void)removeJPBlock;\n\n- (void)testJSBlockToOCCall;\n\n@end\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/newBlockTest.js",
    "content": "defineClass(\"newBlockTest\", {\ntestJSBlockToOCCall: function() {\n    self.performBlock(block(\"CGFloat, int, CGPoint, double, CGFloat, NSNumber*, NSString*, NSInteger\", function(arg1, arg2, arg3, arg4, arg5, arg6, arg7) {\n        return arg1 + arg2.x + arg2.y + arg3 + arg4 + arg5 + arg6.doubleValue() + arg7;\n    }));\n}\n}, {});\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/newBlockTest.m",
    "content": "//\n//  newBlockTest.m\n//  JSPatchTests\n//\n//  Created by WELCommand on 2018/3/27.\n//  Copyright © 2018年 bang. All rights reserved.\n//\n\n#import \"newBlockTest.h\"\n#import <JavaScriptCore/JavaScriptCore.h>\n#import \"JPEngine.h\"\n\n@implementation newBlockTest\n\n- (void)testJSBlockToOCCall {}\n\n\n+ (void)main:(JSContext *)context\n{\n    context[@\"__genBlock\"] = nil;\n}\n\n- (void)removeJPBlock {\n    [JPEngine addExtensions:@[@\"newBlockTest\"]];\n}\n\n- (void)performBlock:(CGFloat (^)(int arg1, CGPoint arg2, double arg3, CGFloat arg4, NSNumber *arg5, NSString *arg6, NSInteger arg7))block {\n    _success = (block(1, (CGPoint){3.3, 3.3}, 1.1, 1.1, @(11), @\"4.4\", 17) == (CGFloat)(1 + 3.3 + 3.3 + 1.1 + 1.1 + 11 + 4.4 + 17)) && (block(1, (CGPoint){3.3, 3.3}, 1.1, 1.1, @(11), @\"4.4\", 17) == (CGFloat)(1 + 3.3 + 3.3 + 1.1 + 1.1 + 11 + 4.4 + 17));\n}\n\n@end\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/newProtocolTest.h",
    "content": "//\n//  newProrotcolTest.h\n//  JSPatchDemo\n//\n//  Created by Awhisper on 15/12/27.\n//  Copyright © 2015年 bang. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import <UIKit/UIKit.h>\n\n@interface baseTestProtocolObject : NSObject\n\n-(int)testProtocol:(BOOL)arg;\n\n-(void)test2Protocol:(NSInteger)arg;\n\n-(void)test3Protocol:(BOOL)arg1 withB:(float)arg2 withC:(CGFloat)arg3;\n\n@end\n\n@interface structTestProtocolObject : NSObject\n\n-(int)testProtocol:(CGRect)arg;\n\n-(CGPoint)test2Protocol:(CGSize)arg;\n\n-(CGSize)test3Protocol:(CGRect)arg1 withB:(float)arg2 withC:(NSInteger)arg3;\n\n@end\n\n@interface objectTestProtocolObject : NSObject\n\n-(int)testProtocol:(NSString*)arg;\n\n-(int)test2Protocol:(NSString*)arg;\n\n-(CGSize)test3Protocol:(NSArray*)arg1 withB:(NSString*)arg2 withC:(NSInteger)arg3;\n\n@end\n\n//typedef void(^name)(void);\n@interface specialTestProtocolObject : NSObject\n\n-(void)testProtocol:(SEL)arg;\n\n-(void)test2Protocol:(void(^)(void))arg;\n\n-(void)test3Protocol:(float)arg1 withB:(void(^)(void))arg2 withC:(SEL)arg3;\n\n@end\n\n@interface typeEncodeTestProtocolObject : NSObject\n\n-(void)testProtocol:(id)arg;\n\n-(NSString*)test2Protocol:(NSArray*)arg1 withB:(NSString*)arg2;\n\n@end\n\n@interface classTestProtocolObject : NSObject\n\n+(int)testProtocol:(NSString*)arg;\n\n+(int)test2Protocol:(NSString*)arg;\n\n+(CGSize)test3Protocol:(NSArray*)arg1 withB:(NSString*)arg2 withC:(NSInteger)arg3;\n\n@end\n\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/newProtocolTest.js",
    "content": "defineProtocol(\"baseTestProtocol\",{\n//argument type can be bool  BOOL int NSInterger float CGFloat ... any base type\n       \n//one argument BOOL  return int\n  testProtocol:{\n    paramsType:\"BOOL\",\n    returnType:\"int\",\n  },\n       \n  //one argument NSInterger  return void\n    test2Protocol:{\n    paramsType:\"BOOL\",\n  //returnType:\"void\",//option no returnType mean void\n  },\n       \n  //multiArguments seperated by \",\"\n  test3Protocol_withB_withC:{\n    paramsType:\"BOOL , float , CGFloat\",\n    //returnType:\"void\",//option no returnType mean void\n  },\n})\n\n//with new protocol  you can add basetype args method\ndefineClass('baseTestProtocolObject : NSObject <baseTestProtocol>' , {\n  testProtocol:function(arg1){\n    console.log(arg1);\n    return 1;\n  },\n  test2Protocol: function(arg1) {\n    console.log(arg1);\n  },\n  test3Protocol_withB_withC:function(arg1,arg2,arg3){\n    console.log(arg1);\n  },\n})\n\n\n\ndefineProtocol(\"structTestProtocol\",{\n//argument type can be CGRect  CGSize CGPoint ... many systemstruct\n//only support system struct\n//custom struct see  encodeTypeTest\n       \n  //one argument CGRect  return int\n  testProtocol:{\n    paramsType:\"CGRect\",\n    returnType:\"int\",\n  },\n\n  //one argument CGSize  return CGPoint\n  test2Protocol:{\n    paramsType:\"CGSize\",\n    returnType:\"CGPoint\",\n  },\n\n  //multiArguments seperated by \",\"  struct & baseType mix\n  test3Protocol_withB_withC:{\n    paramsType:\"CGRect , float , NSInteger\",\n    returnType:\"CGSize\",\n  },\n})\n\n//with new protocol  you can add struct type args method\ndefineClass('structTestProtocolObject : NSObject <structTestProtocol>' , {\n  testProtocol:function(arg1){\n    console.log(arg1);\n    return 1;\n  },\n  test2Protocol: function(arg1) {\n    console.log(arg1);\n    var point = {x:100,y:100};\n    return point;\n  },\n  test3Protocol_withB_withC:function(arg1,arg2,arg3){\n    console.log(arg1);\n    var size = {width:100,height:100};\n    return size;\n  },\n})\n\n\ndefineProtocol(\"objectTestProtocol\",{\n//argument type can be any NSObject\n     \n  //one argument NSString ,  return int\n  //you can turn NSString to id\n  testProtocol:{\n    paramsType:\"id\",\n    returnType:\"int\",\n  },\n\n  //you can use NSString is All ok\n  test2Protocol:{\n    paramsType:\"NSString\",\n    returnType:\"int\",\n  },\n\n  //multiArguments seperated by \",\"  object & baseType mix\n  test3Protocol_withB_withC:{\n    paramsType:\"id , NSString , NSInteger\",\n    returnType:\"CGSize\",\n  },\n\n})\n\n//with new protocol  you can add mix type args method\ndefineClass('objectTestProtocolObject : NSObject <objectTestProtocol>' , {\n  testProtocol:function(arg1){\n    console.log(arg1);\n    return 1;\n  },\n  test2Protocol: function(arg1) {\n    console.log(arg1);\n    return 1;\n  },\n  test3Protocol_withB_withC:function(arg1,arg2,arg3){\n    console.log(arg1);\n    var size = {width:100,height:100};\n    return size;\n    },\n})\n\n\n\ndefineProtocol(\"specialTestProtocol\",{\n//argument type can be selector and block\n  //one argument Selctor  must use \"SEL\"\n  testProtocol:{\n    paramsType:\"SEL\",\n    //returnType:\"int\",//option no returnType mean void\n  },\n\n  //one argument bloc  must use \"block\"\n  test2Protocol:{\n    paramsType:\"block\",\n    // returnType:\"CGPoint\",//option no returnType mean void\n  },\n\n  //multiArguments seperated by \",\"  struct & baseType mix\n  test3Protocol_withB_withC:{\n    paramsType:\"CGFloat , block , SEL\",\n    // returnType:\"CGSize\",//option no returnType mean void\n  },\n})\n\n//with new protocol  you can add mix type args method\ndefineClass('specialTestProtocolObject : NSObject <specialTestProtocol>' , {\n  testProtocol:function(arg1){\n    console.log(arg1);\n  },\n  test2Protocol: function(arg1) {\n    console.log(arg1);\n    arg1();\n  },\n  test3Protocol_withB_withC:function(arg1,arg2,arg3){\n    console.log(arg1);\n    arg2();\n  },\n})\n\n\ndefineProtocol(\"encodeTestProtocol\",{\n//use typeEncode to define complex method\n\n  //you can write typeEncode by using runtime\n  //you can input any string\n  //makesure the number of args  is right\n  testProtocol:{\n    paramsType:\"unknown\",\n    returnType:\"something\",\n    typeEncode:\"v12@0:4@8\",\n  },\n\n  //you can write typeEncode by yourself\n  //you can input any string\n  //makesure the number of args  is right\n  testProtocol_withB:{\n    paramsType:\"idontknown , mygod\",\n    returnType:\"wooo\",\n    typeEncode:\"@@:@@\",\n  },\n\n//if your paramsType or returnType is complex\n//youcan input any string just make sure number is right\n//write the whole typeEncode  or  use runtime to generate typeEncode\n})\n\n//with new protocol  you can add encodetype method\ndefineClass('typeEncodeTestProtocolObject : NSObject <encodeTestProtocol>' , {\n  testProtocol:function(arg1){\n    console.log(arg1);\n  },\n  test2Protocol_withB: function(arg1,arg2) {\n    console.log(arg1);\n    var ret = \"string\";\n    return ret;\n  },\n})\n\n\ndefineProtocol(\"classTestProtocol\",{},{\n//argument type can be any NSObject\n\n  //one argument NSString ,  return int\n  //you can turn NSString to id\n  testProtocol:{\n    paramsType:\"id\",\n    returnType:\"int\",\n  },\n\n  //you can use NSString is All ok\n  test2Protocol:{\n    paramsType:\"NSString\",\n    returnType:\"int\",\n  },\n\n  //multiArguments seperated by \",\"  object & baseType mix\n  test3Protocol_withB_withC:{\n    paramsType:\"id , NSString , NSInteger\",\n    returnType:\"CGSize\",\n  },\n})\n\n//with new protocol  you can add class method\ndefineClass('classTestProtocolObject : NSObject <classTestProtocol>' ,{}, {\n  testProtocol:function(arg1){\n    console.log(arg1);\n    return 1;\n  },\n  test2Protocol: function(arg1) {\n    console.log(arg1);\n    return 1;\n  },\n  test3Protocol_withB_withC:function(arg1,arg2,arg3){\n    console.log(arg1);\n    var size = {width:100,height:100};\n    return size;\n  },\n})\n\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/newProtocolTest.m",
    "content": "//\n//  newProrotcolTest.m\n//  JSPatchDemo\n//\n//  Created by Awhisper on 15/12/27.\n//  Copyright © 2015年 bang. All rights reserved.\n//\n\n#import \"newProtocolTest.h\"\n#import \"JPEngine.h\"\n\n#pragma clang diagnostic push\n\n#pragma clang diagnostic ignored \"-Wincomplete-implementation\"\n@implementation baseTestProtocolObject\n// no method definition\n// no crash means addProtocol success\n@end\n\n@implementation structTestProtocolObject\n// no method definition\n// no crash means addProtocol success\n@end\n\n@implementation objectTestProtocolObject\n// no method definition\n// no crash means addProtocol success\n@end\n\n@implementation specialTestProtocolObject\n// no method definition\n// no crash means addProtocol success\n@end\n\n@implementation typeEncodeTestProtocolObject\n// no method definition\n// no crash means addProtocol success\n@end\n\n@implementation classTestProtocolObject\n// no method definition\n// no crash means addProtocol success\n@end\n\n#pragma clang diagnostic pop\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/performanceTest.js",
    "content": "var performanceTestObj = require('NSObject').alloc().init();\nvar largeDict = {\n    \"id\": 2619381,\n    \"title\": \"Seaborn Oyster Co.\",\n    \"description\": null,\n    \"width\": 400,\n    \"height\": 300,\n    \"images\": {\n        \"hidpi\": \"https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher.jpg\",\n        \"normal\": \"https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher_1x.jpg\",\n        \"teaser\": \"https://d13yacurqjgara.cloudfront.net/users/52758/screenshots/2619381/seaborn_oyster_co_j_fletcher_teaser.jpg\"\n    },\n    \"views_count\": 2166,\n    \"likes_count\": 235,\n    \"comments_count\": 2,\n    \"attachments_count\": 0,\n    \"rebounds_count\": 0,\n    \"buckets_count\": 11,\n    \"created_at\": \"2016-03-29T17:12:41Z\",\n    \"updated_at\": \"2016-03-29T17:12:53Z\",\n    \"html_url\": \"https://dribbble.com/shots/2619381-Seaborn-Oyster-Co\",\n    \"attachments_url\": \"https://api.dribbble.com/v1/shots/2619381/attachments\",\n    \"buckets_url\": \"https://api.dribbble.com/v1/shots/2619381/buckets\",\n    \"comments_url\": \"https://api.dribbble.com/v1/shots/2619381/comments\",\n    \"likes_url\": \"https://api.dribbble.com/v1/shots/2619381/likes\",\n    \"projects_url\": \"https://api.dribbble.com/v1/shots/2619381/projects\",\n    \"rebounds_url\": \"https://api.dribbble.com/v1/shots/2619381/rebounds\",\n    \"animated\": false,\n    \"tags\": [\n        \"charleston\",\n        \"company\",\n        \"ocean\",\n        \"oyster\",\n        \"sea\",\n        \"wave\"\n        ],\n    \"user\": {\n        \"id\": 52758,\n        \"name\": \"Jay Fletcher\",\n        \"username\": \"jfletcherdesign\",\n        \"html_url\": \"https://dribbble.com/jfletcherdesign\",\n        \"avatar_url\": \"https://d13yacurqjgara.cloudfront.net/users/52758/avatars/normal/J_FLETCHER_DESIGN_LOGO-01.jpg?1401983283\",\n        \"bio\": \"\",\n        \"location\": \"Charleston, SC\",\n        \"links\": {\n            \"web\": \"http://www.jfletcherdesign.com\",\n            \"twitter\": \"https://twitter.com/jfletcherdesign\"\n        },\n        \"buckets_count\": 0,\n        \"comments_received_count\": 5239,\n        \"followers_count\": 13803,\n        \"followings_count\": 558,\n        \"likes_count\": 6531,\n        \"likes_received_count\": 104895,\n        \"projects_count\": 10,\n        \"rebounds_received_count\": 325,\n        \"shots_count\": 481,\n        \"teams_count\": 0,\n        \"can_upload_shot\": true,\n        \"type\": \"Player\",\n        \"pro\": true,\n        \"buckets_url\": \"https://api.dribbble.com/v1/users/52758/buckets\",\n        \"followers_url\": \"https://api.dribbble.com/v1/users/52758/followers\",\n        \"following_url\": \"https://api.dribbble.com/v1/users/52758/following\",\n        \"likes_url\": \"https://api.dribbble.com/v1/users/52758/likes\",\n        \"projects_url\": \"https://api.dribbble.com/v1/users/52758/projects\",\n        \"shots_url\": \"https://api.dribbble.com/v1/users/52758/shots\",\n        \"teams_url\": \"https://api.dribbble.com/v1/users/52758/teams\",\n        \"created_at\": \"2011-08-13T23:30:38Z\",\n        \"updated_at\": \"2016-03-29T17:12:53Z\"\n    },\n    \"team\": null\n};\ndefineClass('JPPerformanceTest', {\n    testJSCallOCEmptyMethod: function() {\n        var slf = self\n        for (var i = 0; i < 10000; i ++) {\n            slf.emptyMethod();\n        }\n    },\n    testJSCallOCMethodWithParamObject: function() {\n        var slf = self\n        for (var i = 0; i < 10000; i ++) {\n            slf.methodWithParamObject(performanceTestObj);\n        }\n    },\n    testJSCallOCMethodReturnObject: function() {\n        var slf = self\n        for (var i = 0; i < 10000; i ++) {\n            slf.methodReturnObject();\n        }\n    },\n    \n    testJSCallJSEmptyMethod: function() {\n        var slf = self\n        for (var i = 0; i < 10000; i ++) {\n            slf.newJSEmptyMethod();\n        }\n    },\n    \n    testJSCallJSMethodWithParam: function() {\n        var slf = self\n        for (var i = 0; i < 10000; i ++) {\n            slf.newJSMethodWithParam(performanceTestObj);\n        }\n    },\n    \n    testJSCallJSMethodWithLargeDictionaryParam: function() {\n        var slf = self\n        for (var i = 0; i < 1000; i ++) {\n            slf.newJSMethodWithLargeDictionaryParam(largeDict);\n        }\n    },\n    \n    testJSCallJSMethodWithLargeDictionaryParamAutoConvert: function() {\n        var slf = self\n        autoConvertOCType(1);\n        for (var i = 0; i < 1000; i ++) {\n            slf.newJSMethodWithLargeDictionaryParam(largeDict);\n        }\n        autoConvertOCType(0);\n    },\n    \n    emptyMethodToOverride: function() {\n        \n    },\n    methodWithParamObjectToOverride: function(obj) {\n        \n    },\n    methodReturnObjectToOverride: function() {\n        return performanceTestObj;\n    },\n    \n    newJSEmptyMethod: function() {\n        \n    },\n    \n    newJSMethodWithParam: function(param) {\n    \n    },\n    \n    newJSMethodWithLargeDictionaryParam: function(dict) {\n        \n    },\n    \n    testJSCallMallocJPMemory: function() {\n        require('JPEngine').addExtensions(['JPMemory'])\n        for (var i = 0; i < 100000; i ++) {\n            var p = malloc(10)\n        }\n    },\n    \n    testJSCallMallocJPCFunction: function() {\n        require('JPEngine').addExtensions(['JPCFunction'])\n        for (var i = 0; i < 100000; i ++) {\n            defineCFunction(\"malloc\", \"void *, size_t\")\n            var p = malloc(10)\n        }\n    }\n})\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/protocolTest.js",
    "content": "var global = this;\n\n(function() {\n  defineClass(\"JPTestProtocolObject : NSObject <JPTestProtocol, JPTestProtocol2>\", {\n    protocolWithDouble_dict: function(num, dict) {\n      if (dict.objectForKey(\"name\").toJS() == \"JSPatch\" && num - 4.2 < 0.001) {\n        return num\n      }\n      return 0\n    },\n    protocolWithInt: function(num) {\n      return num\n    }\n  }, {\n    classProtocolWithString_int: function(str, num) {\n      if (num == 42) return str\n      return null\n    }\n  })\n})();"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/superTest.js",
    "content": "defineClass('JPJSSuperTestA1 : JPSuperTestA', {\n    method: function() {\n        var str = self.super().method().toJS();\n        return str + '1';\n    }\n})\n\n\ndefineClass('JPJSSuperTestA2 : JPJSSuperTestA1', {\n    method: function() {\n        var str = self.super().method();\n        return str + '2';\n    }\n})\n\n\n\n\ndefineClass('JPJSSuperTestB2 : JPSuperTestB1', {\n    method: function() {\n        var str = self.super().method().toJS();\n        return str + '2';\n    }\n})\n\n\ndefineClass('JPJSSuperTestB3 : JPJSSuperTestB2', {\n    method: function() {\n        var str = self.super().method();\n        return str + '3';\n    }\n})\n\ndefineClass('JPSuperTestC1', {\n    method: function() {\n        var ret = self.ORIGmethod().toJS();  //should be C1\n        console.log(\"ttttt: \" + ret + self.super().method().toJS())\n        return ret + self.super().method().toJS(); //should be C1C\n    }\n})\n\n\n\n\ndefineClass('JPSuperTestResult', {}, {\n    isPassA: function() {\n        var o = JPJSSuperTestA2.alloc().init();\n        return o.method() == 'A12';\n    },\n    isPassB: function (){\n        var o2 = JPJSSuperTestB2.alloc().init();\n        var o3 = JPJSSuperTestB3.alloc().init();\n        return o2.method() == 'B12' && o3.method() == 'B123';\n    }\n})\n\n"
  },
  {
    "path": "Demo/iOSDemo/JSPatchTests/test.js",
    "content": "include('protocolTest.js')\ninclude('newProtocolTest.js')\nvar global = this;\n\nrequire('JPEngine').defineStruct({\n    \"name\": \"UIEdgeInsets\",\n    \"types\": \"FFFF\",\n    \"keys\": [\"top\", \"left\", \"bottom\", \"right\"]\n});\n\n(function() {\n  defineClass(\"JPTestObject\", {\n    funcToSwizzle_view: function(num, view) {\n      self.ORIGfuncToSwizzle_view(num, view) \n      self.setFuncToSwizzleViewPassed(view && 4.2 - num < 0.01)\n    },\n    funcToSwizzleWithString_view_int: function(str, view, i) {\n      self.setFuncToSwizzleWithStringViewIntPassed(str.toJS() == \"stringFromOC\" && view && i == 42)\n    },\n    funcToSwizzleReturnView: function(view) {\n      return view\n    },\n    funcToSwizzleReturnInt: function(num) {\n      return num\n    },\n    funcToSwizzleReturnDictionary: function(dict) {\n      return dict\n    },\n    funcToSwizzleReturnJSDictionary: function() {\n      return {\"str\" : \"js_string\"};\n    },\n    funcToSwizzleReturnArray: function(arr) {\n      return arr\n    },\n    funcToSwizzleReturnString: function(str) {\n      return str\n    },\n    funcToSwizzleWithBlock: function(blk) {\n      blk(UIView.alloc().init(), 42)\n    },\n    funcToSwizzle__withUnderLine__: function(num) {\n      self.setFuncToSwizzle__withUnderLine__Passed(num == 42)\n    },\n    funcOverrideParentMethod:function(){\n      return \"overrided\";\n    },\n    funcToSwizzleReturnRect: function(rect) {\n      self.setFuncToSwizzleReturnRectJSPassed(rect.width == 100)\n      return rect;\n    },\n    funcToSwizzleReturnSize: function(size) {\n      self.setFuncToSwizzleReturnSizeJSPassed(size.width == 42)\n      return size;\n    },\n    funcToSwizzleReturnPoint: function(point) {\n      self.setFuncToSwizzleReturnPointJSPassed(point.x == 42)\n      return point;\n    },\n    funcToSwizzleReturnRange: function(range) {\n      self.setFuncToSwizzleReturnRangeJSPassed(range.length == 42)\n      return range;\n    },\n    funcToSwizzleReturnEdgeInsets: function(edge) {\n        self.setFuncToSwizzleReturnEdgeInsetsJSPassed(edge.top == 42)\n        return edge;\n    },\n    funcToSwizzleTestGCD: function(completeBlock) {\n      var execCount = 0\n      var slf = self\n      var dispatchExecBlock = function() {\n        if (++execCount >= 4) {\n          slf.setFuncToSwizzleTestGCDPassed(1)\n          completeBlock()\n        }\n      }\n      dispatch_async_main(dispatchExecBlock);\n      dispatch_async_global_queue(dispatchExecBlock);\n      dispatch_sync_main(dispatchExecBlock);\n      dispatch_after(1, dispatchExecBlock);\n    },\n    funcToSwizzleTestClass: function(cls) {\n      return cls\n    },\n    funcToSwizzleTestSelector: function(sel) {\n      return sel\n    },\n    funcToSwizzleTestChar: function(cStr) {\n      return cStr\n    },\n    funcToSwizzleTestPointer: function(pointer) {\n      return pointer\n    },\n    funcToSwizzleReturnClass:function(){\n      return require('JPTestObject').class()\n    }\n  },\n  {\n    classFuncToSwizzle_int: function(o, num) {\n      o.setClassFuncToSwizzlePassed(num == 10)\n    },\n    classFuncToSwizzleReturnObj: function(o) {\n      self.ORIGclassFuncToSwizzleReturnObj(o)\n      return o\n    },\n    classFuncToSwizzleReturnInt: function(i) {\n      return i\n    },\n    ///////Test for function which return double/float, cause there's a fatal bug in NSInvocation on iOS7.0\n    classFuncToSwizzleReturnDouble: function(d) {\n      return d\n    }\n  })\n  defineClass(\"JPTestSwizzledForwardInvocationSubObject\",{\n    stubMethod: function() {}\n  })\n\n  var JPTestObject = require(\"JPTestObject\") \n  var UIView = require(\"UIView\") \n  var obj = JPTestObject.alloc().init() \n  global.ocObj = obj.__obj;\n\n  ////////Swizzle\n  obj.callSwizzleMethod()\n\n  var cls = obj.funcToSwizzleTestClass(JPTestObject.class())\n  obj.setFuncToSwizzleTestClassPassed(obj.isKindOfClass(cls))\n\n  obj.funcTestChar(obj.funcReturnChar())\n  var pointer = obj.funcReturnPointer()\n\n  ////////Base\n  obj.funcReturnVoid();\n  var testReturnString = obj.funcReturnString().toJS();\n  obj.setFuncReturnStringPassed(testReturnString == \"stringFromOC\")\n\n  ////////Test Class function call\n  testReturnString = obj.funcReturnClass().classFunCallReturnString().toJS();\n  testReturnString2 = obj.funcToSwizzleReturnClass().classFunCallReturnString().toJS();\n  obj.setFuncReturnClassPassed(testReturnString == \"classFunCallReturnString\" && testReturnString2 == \"classFunCallReturnString\")\n \n  ////////Test Parameter Class return String\n  var instanceString = obj.funcWithClassAndReturnString(JPTestObject.class()).toJS()\n  var instanceString2 = obj.funcWithClassAndReturnString(obj.funcToSwizzleReturnClass()).toJS()\n  var instanceString3 = obj.funcWithClassAndReturnString(obj.funcReturnClass()).toJS()\n  var instanceString4 = obj.funcWithClassAndReturnString(require('JPTestObject')).toJS()\n  obj.setFuncWithClassAndReturnStringPassed(\n      instanceString == \"JPTestObject\" &&\n      instanceString2 == \"JPTestObject\" &&\n      instanceString3 == \"JPTestObject\" &&\n      instanceString4 == \"JPTestObject\"\n  )\n\n  ///////Test for functions which return double/float, cause there's a fatal bug in NSInvocation on iOS7.0\n  var testReturnDouble = obj.funcReturnDouble()\n  console.log(testReturnDouble == 100)\n  obj.setFuncReturnDoublePassed(testReturnDouble == 100)\n\n  obj.funcWithInt(42);\n  obj.funcWithDict_andDouble({test: \"test\"}, 4.2)\n \n  //////nil / NSNull\n  obj.funcWithNil_dict_str_num(null, {k: \"JSPatch\"}, \"JSPatch\", 4.2)\n  obj.funcWithNull(nsnull)\n  var o = obj.funcReturnNil()\n  obj.funcWithNil(o)\n  obj.setFuncReturnNilPassed(!o)\n  o.callAnyMethod().willNotCrash()\n  \n  var bTrue = obj.funcTestBool(true)\n  var bFalse = obj.funcTestBool(false)\n  var bFalseNum = obj.funcTestBool(0)\n  obj.setFuncTestBoolPassed(bTrue && !bFalse && !bFalseNum)\n \n  var num0 = obj.funcTestNSNumber(0)\n  var num1 = obj.funcTestNSNumber(1)\n  obj.setFuncTestNSNumberPassed(num0 === 0 && num1 === 1)\n\n  ///////UIView/NSObject\n  var view = obj.funcReturnViewWithFrame({\n    x: 0,\n    y: 0,\n    width: 100,\n    height: 100\n  });\n  var viewFrame = view.frame() \n  obj.setFuncReturnViewWithFramePassed(viewFrame.width == 100 && viewFrame.height == 100)\n\n  var newView = UIView.alloc().initWithFrame({\n    x: 10,\n    y: 10,\n    width: 20,\n    height: 20\n  })\n  var returnedView = obj.funcWithViewAndReturnView(newView);\n  var returnedViewFrame = returnedView.frame() \n  obj.setFuncWithViewAndReturnViewPassed(returnedViewFrame.width == 20 && returnedViewFrame.x == 10)\n\n  //////CGRect/CGPoint/CGSize/NSRange\n  var rect = obj.funcWithRectAndReturnRect({\n    x: 10,\n    y: 10,\n    width: 4.2,\n    height: 4.2\n  });\n  obj.setFuncWithRectAndReturnRectPassed(rect.x == 10 && rect.y == 10 && rect.width - 4.2 < 0.01 && rect.height - 4.2 < 0.01)\n\n  var point = obj.funcWithPointAndReturnPoint({\n    x: 10,\n    y: 10\n  });\n  obj.setFuncWithPointAndReturnPointPassed(point.x == 10 && point.y == 10)\n\n  var size = obj.funcWithSizeAndReturnSize({\n    width: 10,\n    height: 10\n  });\n  obj.setFuncWithSizeAndReturnSizePassed(size.width == 10 && size.height == 10)\n\n  var range = obj.funcWithRangeAndReturnRange({\n    location: 0,\n    length: 100\n  });\n  obj.setFuncWithRangeAndReturnRangePassed(range.location == 0 && range.length == 100)\n\n  /////Dictionary/Array\n  var dict = obj.funcReturnDictStringInt().toJS()\n  obj.setFuncReturnDictStringIntPassed(dict[\"str\"] == \"stringFromOC\" && dict[\"num\"] == 42)\n\n  var dict = obj.funcReturnDictStringView().toJS();\n  var dictViewFrame = dict[\"view\"].frame() \n  obj.setFuncReturnDictStringViewPassed(dict.str == \"stringFromOC\" && dictViewFrame.width == 100)\n\n  var arr = obj.funcReturnArrayControllerViewString().toJS()\n  obj.setFuncReturnArrayControllerViewStringPassed(arr[0] && arr[1] && arr[2] == \"stringFromOC\")\n\n  var dict = obj.funcReturnDict({name: \"JSPatch\"}).toJS()\n  obj.setFuncReturnDictPassed(dict.name == \"JSPatch\")\n \n  //////property\n  var view = UIView.alloc().init();\n  view.setFrame({\n    x: 10,\n    y: 10,\n    width: 100,\n    height: 100\n  }) \n  obj.setPropertySetFramePassed(view.frame().width == 100 && view.bounds().height == 100)\n\n  obj.testView = view \n  obj.setPropertySetViewPassed(obj.testView.frame().x == 10)\n\n  /////Block\n  require('JPEngine').addExtensions(['JPBlock']);\n  var blk = obj.funcReturnBlock();\n  blk(\"stringFromJS\", 42);\n\n  var blk = obj.funcReturnObjectBlock();\n  var view = UIView.alloc().initWithFrame({\n    x: 10,\n    y: 10,\n    width: 100,\n    height: 100\n  }) \n  var blkRet = blk({\n    str: \"stringFromJS\",\n    view: view\n  }, view)\n  obj.setFuncReturnObjectBlockReturnValuePassed(blkRet.toJS() == \"succ\")\n\n  var jsBlkRet = obj.funcReturnJSBlock(block(\"id, NSString *, int\", function(str, num) {\n    obj.setFuncReturnJSBlockPassed(str.toJS() == 'stringFromJS' && num == 42)\n  }))\n  jsBlkRet('stringFromJS', 42);\n    \n  obj.callBlockWithStringAndInt(block(\"id, NSString *, int\", function(str, num) {\n    obj.setCallBlockWithStringAndIntPassed(str.toJS() == \"stringFromOC\" && num == 42)\n    return \"succ\"\n  }))\n \n  obj.callBlockDelay(block(\"id, NSString *, int\", function(str, num) {\n    obj.setCallBlockWithStringAndIntPassed(str.toJS() == \"stringFromOC\" && num == 42)\n    return \"succ\"\n  }))\n \n // request big memory to trigger JSContext gc\n // make sure the above argument function(str, num) not freed before calling.\n  require('JPEngine').addExtensions(['JPCFunction'])\n  for (var i = 0; i < 100000; i ++) {\n      defineCFunction(\"malloc\", \"void *, size_t\")\n      var p = malloc(10)\n  }\n\n  obj.callBlockWithArrayAndView(block(\"id, NSArray *, UIView *\", function(arr, view) {\n    var viewFrame = view.frame()\n    arr = arr.toJS()\n    obj.setCallBlockWithArrayAndViewPassed(arr[0] == \"stringFromOC\" && arr[1] && viewFrame.width == 100)\n  }))\n\n  obj.callBlockWithBoolAndBlock(block(\"id, BOOL, NSBlock *\", function(b, blk) {\n    blk(\"stringFromJS\", b ? 42 : 0);\n  }))\n\n  obj.callBlockWithObjectAndBlock(block(\"id, UIView *, NSBlock *\", function(view, blk) {\n    var viewFrame = view.frame()\n    var ret = blk((viewFrame.width == 100 ? {\n      \"str\": \"stringFromJS\",\n      \"view\": view\n    }: {}), view)\n    obj.setCallBlockWithObjectAndBlockReturnValuePassed(ret.toJS() == \"succ\")\n  }))\n    \n  obj.callBlockWithDouble(block(\"double, double\", function(num) {\n    return num + 4.2;\n  }));\n    \n  //////super\n  var subObj = require(\"JPTestSubObject\").alloc().init() \n  global.subObj = subObj.__obj;\n  subObj.super().funcCallSuper()\n\n  //////forwardInvocation\n  obj.callTestForward()\n\n  //////new class\n  var JPNewTestObject = defineClass(\"JPNewTestObject\", {\n    funcReturnView: function(x) {\n      var view = UIView.alloc().initWithFrame({\n        x: x,\n        y: 10,\n        width: 20,\n        height: 20\n      }) \n      return view\n    }\n  },\n  {\n    funcReturnBool: function(view, num) {\n      return view && num == 42\n    }\n  })\n\n  var newTestObj = JPNewTestObject.alloc().init()\n\n  var view = newTestObj.funcReturnView(42) \n  obj.setNewTestObjectReturnViewPassed(view.frame().x == 42) \n  obj.setNewTestObjectReturnBoolPassed(JPNewTestObject.funcReturnBool(view, 42))\n \n  //mutable\n  var arr = require('NSMutableArray').alloc().init()\n  arr.addObject(\"ctn\")\n  obj.setMutableArrayPassed(arr.objectAtIndex(0).toJS() == \"ctn\")\n\n  var dict = require('NSMutableDictionary').alloc().init()\n  dict.setObject_forKey(\"ctn\", \"k\")\n  obj.setMutableDictionaryPassed(dict.objectForKey(\"k\").toJS() == \"ctn\")\n\n  var str = require('NSMutableString').alloc().init()\n  str.appendString(\"JS\")\n  str.appendString(\"Patch\")\n  obj.setMutableStringPassed(str.toJS() == \"JSPatch\")\n \n  var arr = []\n  arr.push(obj.getString(), obj.getDictionary(), obj.getArray())\n  obj.funcTestBoxingObj(arr)\n\n  obj.setConsoleLogPassed(console.log != undefined)\n\n\n\n  //extension\n  var transform = obj.funcWithTransform({tx: 100, ty: 100, a: 1, b: 0, c: 0, d: 1})\n  obj.setFuncWithTransformPassed(transform.tx == 100 && transform.ty == 100 && transform.a == 1)\n  var translated = CGAffineTransformTranslate(transform, 10, 10);\n  obj.setTransformTranslatePassed(translated.tx == 110 && translated.ty == 110)\n \n  obj.funcTestPointer(pointer)\n  free(pointer)\n \n  //sizeof\n  var rectSize       = sizeof(\"CGRect\")\n  var pointSize      = sizeof(\"CGPoint\")\n  var sizeSize       = sizeof(\"CGSize\")\n  var vectorSize     = sizeof(\"CGVector\")\n  var edgeInsetsSize = sizeof(\"UIEdgeInsets\")\n  var transformSize  = sizeof(\"CGAffineTransform\")\n  var rangeSize      = sizeof(\"NSRange\")\n  obj.setFuncTestSizeofPassed(rectSize > 0 && pointSize > 0 && sizeSize > 0 && vectorSize > 0 && edgeInsetsSize > 0 && transformSize > 0 && rangeSize > 0)\n \n//getPointerTest1 - Test Object in JPBoxing\n  var sig = require('JPTestObject').instanceMethodSignatureForSelector(\"funcTestGetPointer1:\");\n  var invocation = require('NSInvocation').invocationWithMethodSignature(sig)\n  var str = require('NSString').stringWithString('JSPatch')\n  invocation.setTarget(obj)\n  invocation.setSelector(\"funcTestGetPointer1:\")\n  invocation.setArgument_atIndex(getPointer(str), 2)\n  invocation.invoke()\n  var ret1 = malloc(1)\n  invocation.getReturnValue(ret1)\n  var bool1 =  pvalBool(ret1)\n \n//getPointerTest2 -  Test Normal Object\n  var sig = require('JPTestObject').instanceMethodSignatureForSelector(\"funcTestGetPointer2:\");\n  var invocation = require('NSInvocation').invocationWithMethodSignature(sig)\n  var err = require('NSError').errorWithDomain_code_userInfo(\"com.albert43\",45,{msg:\"test\"});\n  invocation.setTarget(obj)\n  invocation.setSelector(\"funcTestGetPointer2:\")\n  invocation.setArgument_atIndex(getPointer(err), 2)\n  invocation.invoke()\n  var ret2 = malloc(1)\n  invocation.getReturnValue(ret2);\n  var bool2 =  pvalBool(ret2)\n\n//getPointerTest3 -  Test Pointer\n  var ptr = malloc(10)\n  memset(ptr, 65, 10)\n  var sig = require('JPTestObject').instanceMethodSignatureForSelector(\"funcTestGetPointer3:\");\n  var invocation = require('NSInvocation').invocationWithMethodSignature(sig)\n  invocation.setTarget(obj)\n  invocation.setSelector(\"funcTestGetPointer3:\")\n  invocation.setArgument_atIndex(getPointer(ptr), 2)\n  invocation.invoke()\n  var ret3 = malloc(1)\n  invocation.getReturnValue(ret3);\n  var bool3 =  pvalBool(ret3)\n  obj.setFuncTestGetPointerPassed(bool1 && bool2 && bool3)\n  free(ret1)\n  free(ret2)\n  free(ret3)\n  free(ptr)\n \n//funcTestNSErrorPointer\n  var p_error = malloc(8)\n  obj.funcTestNSErrorPointer(p_error)\n  var error = pval(p_error)\n  if (!error) {\n     obj.setFuncTestNSErrorPointerPassed(false)\n  } else {\n    var code = error.code()\n    obj.setFuncTestNSErrorPointerPassed(code==43)\n  }\n  releaseTmpObj(p_error)\n  free(p_error)\n\n//funcTestNilParametersInBlock\n  var blk  = obj.funcGenerateBlock()\n  var str1 = blk(obj.funcReturnNil())\n  var str2 = blk(null)\n  var str3 = obj.excuteBlockWithNilParameters(block(\"NSError *\", blk))\n  if (str1.toJS() == \"no error\" && str2.toJS() == \"no error\" && str3.toJS() == \"no error\") {\n    obj.setFuncTestNilParametersInBlockPassed(true)\n  }\n\n//newStruct\n  var pRect = newStruct('CGRect', {x:0, y:0, width:100, height:100});\n  obj.funcWithRectPointer(pRect);\n  var rect = pvalStruct('CGRect', pRect);\n  obj.setFuncWithRectPointerPassed(obj.funcWithRectPointerPassed() && rect.x == 42)\n  free(pRect);\n \n  var pTransform = newStruct('CGAffineTransform', {tx:0, ty:0, a:100, b:100, c:0, d:0});\n  obj.funcWithTransformPointer(pTransform);\n  var transform = pvalStruct('CGAffineTransform', pTransform);\n  obj.setFuncWithTransformPointerPassed(obj.funcWithTransformPointerPassed() && transform.tx == 42)\n  free(pTransform);\n\n    \n//variable parameter method\n  var strWithFormat = require('NSString').stringWithFormat(\"%@ %@\", \"a\", \"b\");\n  obj.setVariableParameterMethodPassed(strWithFormat.toJS() == \"a b\");\n   \n})();\n"
  },
  {
    "path": "Demo/iOSPlayground/JSPatchPlayground/AppDelegate.h",
    "content": "//\n//  AppDelegate.h\n//  JSPatchPlayground\n//\n//  Created by bang on 5/14/16.\n//  Copyright © 2016 bang. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface AppDelegate : UIResponder <UIApplicationDelegate>\n\n@property (strong, nonatomic) UIWindow *window;\n\n\n@end\n\n"
  },
  {
    "path": "Demo/iOSPlayground/JSPatchPlayground/AppDelegate.m",
    "content": "//\n//  AppDelegate.m\n//  JSPatchPlayground\n//\n//  Created by bang on 5/14/16.\n//  Copyright © 2016 bang. All rights reserved.\n//\n\n#import \"AppDelegate.h\"\n#import \"JPRootViewController.h\"\n\n@interface AppDelegate ()\n@end\n\n@implementation AppDelegate\n\n\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {\n    \n    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];\n    JPRootViewController *rootViewController = [[JPRootViewController alloc] init];\n    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];\n    self.window.rootViewController = navigationController;\n    [self.window makeKeyAndVisible];\n        \n    return YES;\n}\n\n\n- (void)applicationWillResignActive:(UIApplication *)application {\n    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.\n    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.\n}\n\n- (void)applicationDidEnterBackground:(UIApplication *)application {\n    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.\n    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.\n}\n\n- (void)applicationWillEnterForeground:(UIApplication *)application {\n    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.\n}\n\n- (void)applicationDidBecomeActive:(UIApplication *)application {\n    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.\n}\n\n- (void)applicationWillTerminate:(UIApplication *)application {\n    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.\n}\n\n@end\n"
  },
  {
    "path": "Demo/iOSPlayground/JSPatchPlayground/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"60x60\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"60x60\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Demo/iOSPlayground/JSPatchPlayground/Assets.xcassets/Brand Assets.launchimage/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"orientation\" : \"portrait\",\n      \"idiom\" : \"iphone\",\n      \"minimum-system-version\" : \"7.0\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"orientation\" : \"portrait\",\n      \"idiom\" : \"iphone\",\n      \"minimum-system-version\" : \"7.0\",\n      \"subtype\" : \"retina4\",\n      \"scale\" : \"2x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Demo/iOSPlayground/JSPatchPlayground/Assets.xcassets/Contents.json",
    "content": "{\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Demo/iOSPlayground/JSPatchPlayground/Assets.xcassets/LaunchImage.launchimage/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"extent\" : \"full-screen\",\n      \"idiom\" : \"iphone\",\n      \"subtype\" : \"736h\",\n      \"filename\" : \"Default-576@2x.png\",\n      \"minimum-system-version\" : \"8.0\",\n      \"orientation\" : \"portrait\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"extent\" : \"full-screen\",\n      \"idiom\" : \"iphone\",\n      \"subtype\" : \"736h\",\n      \"filename\" : \"Default-736@3x.png\",\n      \"minimum-system-version\" : \"8.0\",\n      \"orientation\" : \"landscape\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"extent\" : \"full-screen\",\n      \"idiom\" : \"iphone\",\n      \"subtype\" : \"667h\",\n      \"filename\" : \"Default-667@2x.png\",\n      \"minimum-system-version\" : \"8.0\",\n      \"orientation\" : \"portrait\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"orientation\" : \"portrait\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Default@2x.png\",\n      \"extent\" : \"full-screen\",\n      \"minimum-system-version\" : \"7.0\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"extent\" : \"full-screen\",\n      \"idiom\" : \"iphone\",\n      \"subtype\" : \"retina4\",\n      \"filename\" : \"Default-568h@2x.png\",\n      \"minimum-system-version\" : \"7.0\",\n      \"orientation\" : \"portrait\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"orientation\" : \"portrait\",\n      \"idiom\" : \"ipad\",\n      \"extent\" : \"full-screen\",\n      \"minimum-system-version\" : \"7.0\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"orientation\" : \"landscape\",\n      \"idiom\" : \"ipad\",\n      \"extent\" : \"full-screen\",\n      \"minimum-system-version\" : \"7.0\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"orientation\" : \"portrait\",\n      \"idiom\" : \"ipad\",\n      \"extent\" : \"full-screen\",\n      \"minimum-system-version\" : \"7.0\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"orientation\" : \"landscape\",\n      \"idiom\" : \"ipad\",\n      \"extent\" : \"full-screen\",\n      \"minimum-system-version\" : \"7.0\",\n      \"scale\" : \"2x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Demo/iOSPlayground/JSPatchPlayground/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n\t<key>LSRequiresIPhoneOS</key>\n\t<true/>\n\t<key>projectPath</key>\n\t<string>$(SRCROOT)/$(TARGET_NAME)</string>\n\t<key>UIRequiredDeviceCapabilities</key>\n\t<array>\n\t\t<string>armv7</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "Demo/iOSPlayground/JSPatchPlayground/JPErrorMsgViewController.h",
    "content": "//\n//  JPErrorMsgViewController.h\n//  JSPatchPlayground\n//\n//  Created by bang on 5/14/16.\n//  Copyright © 2016 bang. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface JPErrorMsgViewController : UIViewController\n- (instancetype)initWithMsg:(NSString *)msg;\n@end\n"
  },
  {
    "path": "Demo/iOSPlayground/JSPatchPlayground/JPErrorMsgViewController.m",
    "content": "//\n//  JPErrorMsgViewController.m\n//  JSPatchPlayground\n//\n//  Created by bang on 5/14/16.\n//  Copyright © 2016 bang. All rights reserved.\n//\n\n#import \"JPErrorMsgViewController.h\"\n\n@interface JPErrorMsgViewController ()\n@property (nonatomic) NSString *msg;\n@end\n\n@implementation JPErrorMsgViewController\n\n- (instancetype)initWithMsg:(NSString *)msg\n{\n    self = [super init];\n    if (self) {\n        self.msg = msg;\n    }\n    return self;\n}\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    UITextView *textView = [[UITextView alloc] initWithFrame:[UIScreen mainScreen].bounds];\n    textView.scrollEnabled = YES;\n    textView.text = self.msg;\n    [self.view addSubview:textView];\n    \n    self.title = @\"JSPatch Error\";\n    [self.navigationItem setLeftBarButtonItem:[[UIBarButtonItem alloc] initWithTitle:@\"Close\" style:UIBarButtonItemStyleDone target:self action:@selector(handleBack)]];\n}\n\n- (void)handleBack\n{\n    [self.navigationController dismissViewControllerAnimated:YES completion:nil];\n}\n\n@end\n"
  },
  {
    "path": "Demo/iOSPlayground/JSPatchPlayground/JPRootViewController.h",
    "content": "//\n//  ViewController.h\n//  JSPatchPlayground\n//\n//  Created by bang on 5/14/16.\n//  Copyright © 2016 bang. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface JPRootViewController : UIViewController\n\n\n@end\n\n"
  },
  {
    "path": "Demo/iOSPlayground/JSPatchPlayground/JPRootViewController.m",
    "content": "//\n//  ViewController.m\n//  JSPatchPlayground\n//\n//  Created by bang on 5/14/16.\n//  Copyright © 2016 bang. All rights reserved.\n//\n\n#import \"JPRootViewController.h\"\n#import \"JPEngine.h\"\n#import \"SGDirWatchdog.h\"\n#import \"JPCleaner.h\"\n#import \"JPErrorMsgViewController.h\"\n\n@interface JPRootViewController ()\n@property (nonatomic) NSMutableArray *watchDogs;\n@property (nonatomic) UIWindow *errorWindow;\n@property (nonatomic) NSString *errMsg;\n@end\n\n@implementation JPRootViewController\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    self.view.backgroundColor = [UIColor whiteColor];\n    \n#if TARGET_IPHONE_SIMULATOR\n    NSString *rootPath = [[NSBundle mainBundle] objectForInfoDictionaryKey:@\"projectPath\"];\n#else\n    NSString *rootPath = [[NSBundle mainBundle] bundlePath];\n#endif\n    \n    [JPEngine handleException:^(NSString *msg) {\n        if (!self.errorWindow) {\n            self.errorWindow = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 20)];\n            self.errorWindow.windowLevel = UIWindowLevelStatusBar + 1.0f;\n            self.errorWindow.backgroundColor = [UIColor blackColor];\n            UIButton *errBtn = [[UIButton alloc] initWithFrame:CGRectMake(5, 0, [UIScreen mainScreen].bounds.size.width - 10, 20)];\n            errBtn.titleLabel.font = [UIFont systemFontOfSize:10];\n            [errBtn setTitle:msg forState:UIControlStateNormal];\n            [errBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];\n            errBtn.tag = 100;\n            [errBtn addTarget:self action:@selector(handleTapErrorBtn) forControlEvents:UIControlEventTouchDown];\n            [self.errorWindow addSubview:errBtn];\n            [self.errorWindow makeKeyAndVisible];\n        } else {\n            UIButton *errBtn = [self.errorWindow viewWithTag:100];\n            [errBtn setTitle:msg forState:UIControlStateNormal];\n        }\n        self.errMsg = msg;\n        \n        self.errorWindow.hidden = NO;\n    }];\n    \n    NSString *scriptRootPath = [rootPath stringByAppendingPathComponent:@\"src\"];\n    NSString *mainScriptPath = [NSString stringWithFormat:@\"%@/%@\", scriptRootPath, @\"/main.js\"];\n    [JPEngine evaluateScriptWithPath:mainScriptPath];\n    \n    self.watchDogs = [[NSMutableArray alloc] init];\n    NSArray *contentOfFolder = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:scriptRootPath error:NULL];\n    [self watchFolder:scriptRootPath mainScriptPath:mainScriptPath];\n    for (NSString *aPath in contentOfFolder) {\n        NSString * fullPath = [scriptRootPath stringByAppendingPathComponent:aPath];\n        BOOL isDir;\n        if ([[NSFileManager defaultManager] fileExistsAtPath:fullPath isDirectory:&isDir] && isDir) {\n            [self watchFolder:fullPath mainScriptPath:mainScriptPath];\n        }\n    }\n    [self showController];\n    \n    UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 100, [UIScreen mainScreen].bounds.size.width, 50)];\n    [btn setTitle:@\"Push Playground\" forState:UIControlStateNormal];\n    [btn addTarget:self action:@selector(showController) forControlEvents:UIControlEventTouchUpInside];\n    [btn setBackgroundColor:[UIColor grayColor]];\n    [self.view addSubview:btn];\n}\n\n- (void)handleTapErrorBtn\n{\n    JPErrorMsgViewController *errorMsgVC = [[JPErrorMsgViewController alloc] initWithMsg:self.errMsg];\n    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:errorMsgVC];\n    [self.navigationController presentViewController:navigationController animated:YES completion:nil];\n}\n\n- (void)watchFolder:(NSString *)folderPath mainScriptPath:(NSString *)mainScriptPath\n{\n    SGDirWatchdog *watchDog = [[SGDirWatchdog alloc] initWithPath:folderPath update:^{\n        self.errorWindow.hidden = YES;\n        [JPCleaner cleanAll];\n        [JPEngine evaluateScriptWithPath:mainScriptPath];\n        [self.navigationController popToRootViewControllerAnimated:NO];\n        [self showController];\n    }];\n    [watchDog start];\n    [self.watchDogs addObject:watchDog];\n}\n\n- (void)showController\n{\n    //override in JSPatch\n}\n\n\n@end\n"
  },
  {
    "path": "Demo/iOSPlayground/JSPatchPlayground/libs/SGDirWatchdog.h",
    "content": "//\n//  SGDirObserver.h\n//  DirectoryObserver\n//\n//  Copyright (c) 2011 Simon Grätzer.\n//\n\n#import <Foundation/Foundation.h>\n\n@interface SGDirWatchdog : NSObject\n\n@property (readonly, nonatomic) NSString *path;\n@property (copy, nonatomic) void (^update)(void);\n\n+ (NSString *)documentsPath;\n+ (id)watchtdogOnDocumentsDir:(void (^)(void))update;\n\n- (id)initWithPath:(NSString *)path update:(void (^)(void))update;\n\n- (void)start;\n- (void)stop;\n\n@end\n"
  },
  {
    "path": "Demo/iOSPlayground/JSPatchPlayground/libs/SGDirWatchdog.m",
    "content": "//\n//  SGDirObserver.m\n//  DirectoryObserver\n//\n//  Copyright (c) 2011 Simon Grätzer.\n//\n\n#import \"SGDirWatchdog.h\"\n#import <fcntl.h>\n#import <unistd.h>\n#import <sys/event.h>\n\n@interface SGDirWatchdog ()\n@property (nonatomic, readonly) CFFileDescriptorRef kqRef;\n- (void)kqueueFired;\n@end\n\n\nstatic void KQCallback(CFFileDescriptorRef kqRef, CFOptionFlags callBackTypes, void *info) {\n\t// Pick up the object passed in the \"info\" member of the CFFileDescriptorContext passed to CFFileDescriptorCreate\n    SGDirWatchdog* obj = (__bridge SGDirWatchdog*) info;\n\t\n\tif ([obj isKindOfClass:[SGDirWatchdog class]]\t\t&&\t// If we can call back to the proper sort of object ...\n\t\t(kqRef == obj.kqRef)\t\t\t\t\t\t\t\t&&\t// and the FD that issued the CB is the expected one ...\n\t\t(callBackTypes == kCFFileDescriptorReadCallBack)\t)\t// and we're processing the proper sort of CB ...\n\t{\n\t\t[obj kqueueFired];\t\t\t\t\t\t\t\t\t\t// Invoke the instance's CB handler\n\t}\n}\n\n@implementation SGDirWatchdog {\n    int\t\t\t\t\t_dirFD;\n    CFFileDescriptorRef _kqRef;\n}\n\n+ (NSString *)documentsPath {\n\tNSArray *documentsPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);\n    \n\treturn documentsPaths[0]; // Path to the application's \"Documents\" directory\n}\n\n+ (id)watchtdogOnDocumentsDir:(void (^)(void))update; {\n    return [[SGDirWatchdog alloc]initWithPath:[self documentsPath] update:update];\n}\n\n\n- (id)initWithPath:(NSString *)path update:(void (^)(void))update; {\n    if ((self = [super init])) {\n        _path = path;\n        _update = [update copy];\n    }\n    return self;\n}\n\n- (void)dealloc {\n    [self stop];\n    \n    \n}\n\n#pragma mark -\n#pragma mark Extension methods\n\n- (void)kqueueFired {\n\t// Pull the native FD around which the CFFileDescriptor was wrapped\n    int kq = CFFileDescriptorGetNativeDescriptor(_kqRef);\n\tif (kq < 0) return;\n\t\n\t// If we pull a single available event out of the queue, assume the directory was updated\n    struct kevent event;\n    struct timespec timeout = {0, 0};\n    if (kevent(kq, NULL, 0, &event, 1, &timeout) == 1 && _update) {\n\t\t_update();\n    }    \n\t\n\t// (Re-)Enable a one-shot (the only kind) callback\n    CFFileDescriptorEnableCallBacks(_kqRef, kCFFileDescriptorReadCallBack);\n}\n\n\n- (void)start {\n\t// One ping only\n    if (_kqRef != NULL) return;\n\t\n\t// Fetch pathname of the directory to monitor\n\tNSString* docPath = self.path;\n\tif (!docPath) return;\n    \n\t// Open an event-only file descriptor associated with the directory\n    int dirFD = open([docPath fileSystemRepresentation], O_EVTONLY);\n\tif (dirFD < 0) return;\n\t\n\t// Create a new kernel event queue\n    int kq = kqueue();\n\tif (kq < 0)\n\t{\n\t\tclose(dirFD);\n\t\treturn;\n\t}\n    \n\t// Set up a kevent to monitor\n    struct kevent eventToAdd;\t\t\t\t\t// Register an (ident, filter) pair with the kqueue\n    eventToAdd.ident  = dirFD;\t\t\t\t\t// The object to watch (the directory FD)\n    eventToAdd.filter = EVFILT_VNODE;\t\t\t// Watch for certain events on the VNODE spec'd by ident\n    eventToAdd.flags  = EV_ADD | EV_CLEAR;\t\t// Add a resetting kevent\n    eventToAdd.fflags = NOTE_WRITE;\t\t\t\t// The events to watch for on the VNODE spec'd by ident (writes)\n    eventToAdd.data   = 0;\t\t\t\t\t\t// No filter-specific data\n    eventToAdd.udata  = NULL;\t\t\t\t\t// No user data\n    \n\t// Add a kevent to monitor \n\tif (kevent(kq, &eventToAdd, 1, NULL, 0, NULL)) {\n\t\tclose(kq);\n\t\tclose(dirFD);\n\t\treturn;\n\t}\n\t\n\t// Wrap a CFFileDescriptor around a native FD\n\tCFFileDescriptorContext context = {0, (__bridge void *)(self), NULL, NULL, NULL};\n    _kqRef = CFFileDescriptorCreate(NULL,\t\t// Use the default allocator\n\t\t\t\t\t\t\t\t\tkq,\t\t\t// Wrap the kqueue\n\t\t\t\t\t\t\t\t\ttrue,\t\t// Close the CFFileDescriptor if kq is invalidated\n\t\t\t\t\t\t\t\t\tKQCallback,\t// Fxn to call on activity\n\t\t\t\t\t\t\t\t\t&context);\t// Supply a context to set the callback's \"info\" argument\n    if (_kqRef == NULL) {\n\t\tclose(kq);\n\t\tclose(dirFD);\n\t\treturn;\n\t}\n\t\n\t// Spin out a pluggable run loop source from the CFFileDescriptorRef\n\t// Add it to the current run loop, then release it\n    CFRunLoopSourceRef rls = CFFileDescriptorCreateRunLoopSource(NULL, _kqRef, 0);\n    if (rls == NULL) {\n\t\tCFRelease(_kqRef); _kqRef = NULL;\n\t\tclose(kq);\n\t\tclose(dirFD);\n\t\treturn;\n\t}\n    CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);\n    CFRelease(rls);\n    \n\t// Store the directory FD for later closing\n\t_dirFD = dirFD;\n\t\n\t// Enable a one-shot (the only kind) callback\n    CFFileDescriptorEnableCallBacks(_kqRef, kCFFileDescriptorReadCallBack);\n}\n\n- (void)stop {\n\tif (_kqRef) {\n\t\tclose(_dirFD);\n\t\tCFFileDescriptorInvalidate(_kqRef);\n\t\tCFRelease(_kqRef);\n\t\t_kqRef = NULL;\n\t}\n}\n\n@end\n"
  },
  {
    "path": "Demo/iOSPlayground/JSPatchPlayground/main.m",
    "content": "//\n//  main.m\n//  JSPatchPlayground\n//\n//  Created by bang on 5/14/16.\n//  Copyright © 2016 bang. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n#import \"AppDelegate.h\"\n\nint main(int argc, char * argv[]) {\n    @autoreleasepool {\n        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));\n    }\n}\n"
  },
  {
    "path": "Demo/iOSPlayground/JSPatchPlayground/src/JPDemoController.js",
    "content": "require('UILabel, UIColor, UIFont, UIScreen, UIImageView, UIImage')\n\nvar screenWidth = UIScreen.mainScreen().bounds().width;\nvar screenHeight = UIScreen.mainScreen().bounds().height;\n\ndefineClass('JPDemoController: UIViewController', {\n    viewDidLoad: function() {\n        self.super().viewDidLoad();\n        self.view().setBackgroundColor(UIColor.whiteColor());\n        \n        var size = 120;\n        var imgView = UIImageView.alloc().initWithFrame({x: (screenWidth - size)/2, y: 150, width: size, height: size});\n        imgView.setImage(UIImage.imageWithContentsOfFile(resourcePath('apple.png')));\n        self.view().addSubview(imgView);\n            \n        var label = UILabel.alloc().initWithFrame({x: 0, y: 310, width: screenWidth, height: 30});\n        label.setText(\"JSPatch\");\n        label.setTextAlignment(1);\n        label.setFont(UIFont.systemFontOfSize(25));\n        self.view().addSubview(label);\n    }, \n})\n"
  },
  {
    "path": "Demo/iOSPlayground/JSPatchPlayground/src/main.js",
    "content": "include('JPDemoController.js');\ndefineClass('JPRootViewController', {\n    showController: function() {\n        var ctrl = JPDemoController.alloc().init();\n        self.navigationController().pushViewController_animated(ctrl, NO);\n    }\n});"
  },
  {
    "path": "Demo/iOSPlayground/JSPatchPlayground.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t361443641CE8041A00B303D4 /* JPCleaner.m in Sources */ = {isa = PBXBuildFile; fileRef = 361443461CE8041A00B303D4 /* JPCleaner.m */; };\n\t\t361443651CE8041A00B303D4 /* JPLocker.m in Sources */ = {isa = PBXBuildFile; fileRef = 361443481CE8041A00B303D4 /* JPLocker.m */; };\n\t\t361443671CE8041A00B303D4 /* JPSpecialInit.m in Sources */ = {isa = PBXBuildFile; fileRef = 3614434C1CE8041A00B303D4 /* JPSpecialInit.m */; };\n\t\t3614436D1CE8041A00B303D4 /* JPEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 3614435A1CE8041A00B303D4 /* JPEngine.m */; };\n\t\t3614436E1CE8041A00B303D4 /* JSPatch.js in Resources */ = {isa = PBXBuildFile; fileRef = 3614435B1CE8041A00B303D4 /* JSPatch.js */; };\n\t\t3660A8671CE3542A008970B4 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3660A8661CE3542A008970B4 /* main.m */; };\n\t\t3660A86A1CE3542A008970B4 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 3660A8691CE3542A008970B4 /* AppDelegate.m */; };\n\t\t3660A86D1CE3542A008970B4 /* JPRootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3660A86C1CE3542A008970B4 /* JPRootViewController.m */; };\n\t\t3660A8721CE3542A008970B4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3660A8711CE3542A008970B4 /* Assets.xcassets */; };\n\t\t3660A8B51CE365FB008970B4 /* src in Resources */ = {isa = PBXBuildFile; fileRef = 3660A8B41CE365FB008970B4 /* src */; };\n\t\t3660A8F21CE36D05008970B4 /* SGDirWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 3660A8F11CE36D05008970B4 /* SGDirWatchdog.m */; };\n\t\t3660A90D1CE4A546008970B4 /* JPErrorMsgViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3660A90C1CE4A546008970B4 /* JPErrorMsgViewController.m */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXFileReference section */\n\t\t361443451CE8041A00B303D4 /* JPCleaner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCleaner.h; sourceTree = \"<group>\"; };\n\t\t361443461CE8041A00B303D4 /* JPCleaner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCleaner.m; sourceTree = \"<group>\"; };\n\t\t361443471CE8041A00B303D4 /* JPLocker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPLocker.h; sourceTree = \"<group>\"; };\n\t\t361443481CE8041A00B303D4 /* JPLocker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPLocker.m; sourceTree = \"<group>\"; };\n\t\t3614434B1CE8041A00B303D4 /* JPSpecialInit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPSpecialInit.h; sourceTree = \"<group>\"; };\n\t\t3614434C1CE8041A00B303D4 /* JPSpecialInit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPSpecialInit.m; sourceTree = \"<group>\"; };\n\t\t361443591CE8041A00B303D4 /* JPEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPEngine.h; sourceTree = \"<group>\"; };\n\t\t3614435A1CE8041A00B303D4 /* JPEngine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPEngine.m; sourceTree = \"<group>\"; };\n\t\t3614435B1CE8041A00B303D4 /* JSPatch.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = JSPatch.js; sourceTree = \"<group>\"; };\n\t\t3660A8621CE3542A008970B4 /* JSPatchPlayground.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JSPatchPlayground.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t3660A8661CE3542A008970B4 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = \"<group>\"; };\n\t\t3660A8681CE3542A008970B4 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = \"<group>\"; };\n\t\t3660A8691CE3542A008970B4 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = \"<group>\"; };\n\t\t3660A86B1CE3542A008970B4 /* JPRootViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JPRootViewController.h; sourceTree = \"<group>\"; };\n\t\t3660A86C1CE3542A008970B4 /* JPRootViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JPRootViewController.m; sourceTree = \"<group>\"; };\n\t\t3660A8711CE3542A008970B4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = \"<group>\"; };\n\t\t3660A8761CE3542A008970B4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t3660A8B41CE365FB008970B4 /* src */ = {isa = PBXFileReference; lastKnownFileType = folder; name = src; path = JSPatchPlayground/src; sourceTree = SOURCE_ROOT; };\n\t\t3660A8F01CE36D05008970B4 /* SGDirWatchdog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGDirWatchdog.h; sourceTree = \"<group>\"; };\n\t\t3660A8F11CE36D05008970B4 /* SGDirWatchdog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGDirWatchdog.m; sourceTree = \"<group>\"; };\n\t\t3660A90B1CE4A546008970B4 /* JPErrorMsgViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPErrorMsgViewController.h; sourceTree = \"<group>\"; };\n\t\t3660A90C1CE4A546008970B4 /* JPErrorMsgViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPErrorMsgViewController.m; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t3660A85F1CE3542A008970B4 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t361443331CE8041A00B303D4 /* Extensions */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t361443451CE8041A00B303D4 /* JPCleaner.h */,\n\t\t\t\t361443461CE8041A00B303D4 /* JPCleaner.m */,\n\t\t\t\t361443471CE8041A00B303D4 /* JPLocker.h */,\n\t\t\t\t361443481CE8041A00B303D4 /* JPLocker.m */,\n\t\t\t\t3614434B1CE8041A00B303D4 /* JPSpecialInit.h */,\n\t\t\t\t3614434C1CE8041A00B303D4 /* JPSpecialInit.m */,\n\t\t\t);\n\t\t\tname = Extensions;\n\t\t\tpath = ../../../Extensions;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t361443581CE8041A00B303D4 /* JSPatch */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t361443591CE8041A00B303D4 /* JPEngine.h */,\n\t\t\t\t3614435A1CE8041A00B303D4 /* JPEngine.m */,\n\t\t\t\t3614435B1CE8041A00B303D4 /* JSPatch.js */,\n\t\t\t);\n\t\t\tname = JSPatch;\n\t\t\tpath = ../../../JSPatch;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t3660A8591CE3542A008970B4 = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3660A8641CE3542A008970B4 /* JSPatchPlayground */,\n\t\t\t\t3660A8631CE3542A008970B4 /* Products */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t3660A8631CE3542A008970B4 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3660A8621CE3542A008970B4 /* JSPatchPlayground.app */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t3660A8641CE3542A008970B4 /* JSPatchPlayground */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t361443331CE8041A00B303D4 /* Extensions */,\n\t\t\t\t361443581CE8041A00B303D4 /* JSPatch */,\n\t\t\t\t3660A8B61CE369F0008970B4 /* libs */,\n\t\t\t\t3660A8B41CE365FB008970B4 /* src */,\n\t\t\t\t3660A8681CE3542A008970B4 /* AppDelegate.h */,\n\t\t\t\t3660A8691CE3542A008970B4 /* AppDelegate.m */,\n\t\t\t\t3660A86B1CE3542A008970B4 /* JPRootViewController.h */,\n\t\t\t\t3660A86C1CE3542A008970B4 /* JPRootViewController.m */,\n\t\t\t\t3660A90B1CE4A546008970B4 /* JPErrorMsgViewController.h */,\n\t\t\t\t3660A90C1CE4A546008970B4 /* JPErrorMsgViewController.m */,\n\t\t\t\t3660A8711CE3542A008970B4 /* Assets.xcassets */,\n\t\t\t\t3660A8761CE3542A008970B4 /* Info.plist */,\n\t\t\t\t3660A8651CE3542A008970B4 /* Supporting Files */,\n\t\t\t);\n\t\t\tpath = JSPatchPlayground;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t3660A8651CE3542A008970B4 /* Supporting Files */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3660A8661CE3542A008970B4 /* main.m */,\n\t\t\t);\n\t\t\tname = \"Supporting Files\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t3660A8B61CE369F0008970B4 /* libs */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3660A8F01CE36D05008970B4 /* SGDirWatchdog.h */,\n\t\t\t\t3660A8F11CE36D05008970B4 /* SGDirWatchdog.m */,\n\t\t\t);\n\t\t\tpath = libs;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t3660A8611CE3542A008970B4 /* JSPatchPlayground */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 3660A8791CE3542A008970B4 /* Build configuration list for PBXNativeTarget \"JSPatchPlayground\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t3660A85E1CE3542A008970B4 /* Sources */,\n\t\t\t\t3660A85F1CE3542A008970B4 /* Frameworks */,\n\t\t\t\t3660A8601CE3542A008970B4 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = JSPatchPlayground;\n\t\t\tproductName = JSPatchPlayground;\n\t\t\tproductReference = 3660A8621CE3542A008970B4 /* JSPatchPlayground.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t3660A85A1CE3542A008970B4 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 0720;\n\t\t\t\tORGANIZATIONNAME = bang;\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t3660A8611CE3542A008970B4 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.2.1;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 3660A85D1CE3542A008970B4 /* Build configuration list for PBXProject \"JSPatchPlayground\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 3660A8591CE3542A008970B4;\n\t\t\tproductRefGroup = 3660A8631CE3542A008970B4 /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t3660A8611CE3542A008970B4 /* JSPatchPlayground */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t3660A8601CE3542A008970B4 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t3614436E1CE8041A00B303D4 /* JSPatch.js in Resources */,\n\t\t\t\t3660A8721CE3542A008970B4 /* Assets.xcassets in Resources */,\n\t\t\t\t3660A8B51CE365FB008970B4 /* src in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t3660A85E1CE3542A008970B4 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t3660A8F21CE36D05008970B4 /* SGDirWatchdog.m in Sources */,\n\t\t\t\t3660A90D1CE4A546008970B4 /* JPErrorMsgViewController.m in Sources */,\n\t\t\t\t361443641CE8041A00B303D4 /* JPCleaner.m in Sources */,\n\t\t\t\t361443671CE8041A00B303D4 /* JPSpecialInit.m in Sources */,\n\t\t\t\t361443651CE8041A00B303D4 /* JPLocker.m in Sources */,\n\t\t\t\t3660A86D1CE3542A008970B4 /* JPRootViewController.m in Sources */,\n\t\t\t\t3614436D1CE8041A00B303D4 /* JPEngine.m in Sources */,\n\t\t\t\t3660A86A1CE3542A008970B4 /* AppDelegate.m in Sources */,\n\t\t\t\t3660A8671CE3542A008970B4 /* main.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin XCBuildConfiguration section */\n\t\t3660A8771CE3542A008970B4 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 9.2;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t3660A8781CE3542A008970B4 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 9.2;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t3660A87A1CE3542A008970B4 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;\n\t\t\t\tINFOPLIST_FILE = JSPatchPlayground/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = net.cnbang.JSPatchPlayground;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t3660A87B1CE3542A008970B4 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;\n\t\t\t\tINFOPLIST_FILE = JSPatchPlayground/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = net.cnbang.JSPatchPlayground;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t3660A85D1CE3542A008970B4 /* Build configuration list for PBXProject \"JSPatchPlayground\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t3660A8771CE3542A008970B4 /* Debug */,\n\t\t\t\t3660A8781CE3542A008970B4 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t3660A8791CE3542A008970B4 /* Build configuration list for PBXNativeTarget \"JSPatchPlayground\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t3660A87A1CE3542A008970B4 /* Debug */,\n\t\t\t\t3660A87B1CE3542A008970B4 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 3660A85A1CE3542A008970B4 /* Project object */;\n}\n"
  },
  {
    "path": "Demo/iOSPlayground/JSPatchPlayground.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:JSPatchPlayground.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "Demo/iOSPlayground/README.md",
    "content": "# JSPatch Playground\n\n![Screenshot](https://raw.github.com/bang590/JSPatch/master/Demo/iOSPlayground/Screenshot.gif)\n\n## Introduce\n\nJSPatch Playground is an interactive JSPatch coding environment, the iOS simulator will refresh and displays results instantly as js files save.\n\nYou can also setup a playground in your own project to use JSPatch build user interface easily.\n\nTips: if there is error of the script code, the status bar will show the messages, tap the status bar if you want to see more details.\n\n## 介绍\n\nJSPatch Playground 可以让你快速看到 JSPatch 代码执行效果，APP在模拟器运行后，每次修改脚本保存模拟器都会自动刷新，无需重启模拟器，即时看到效果。\n\n你也可以仿照 JSPatch Playground 在你的项目里添加 JSPatch 脚本即时刷新功能，帮助你快速使用 JSPatch 开发功能模块。\n\nTips: 如果运行过程中脚本执行错误，会在状态栏里显示错误原因，点击状态栏可以看到更详细的错误提示。"
  },
  {
    "path": "Demo/iOSPlaygroundToolDemo/JSPatchPlaygroundDemo/AppDelegate.h",
    "content": "//\n//  AppDelegate.h\n//  JSPatch\n//\n//  Created by bang on 15/4/30.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface AppDelegate : UIResponder <UIApplicationDelegate>\n\n@property (strong, nonatomic) UIWindow *window;\n\n@end\n\n"
  },
  {
    "path": "Demo/iOSPlaygroundToolDemo/JSPatchPlaygroundDemo/AppDelegate.m",
    "content": "//\n//  AppDelegate.m\n//  JSPatch\n//\n//  Created by bang on 15/4/30.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import \"AppDelegate.h\"\n#import \"JPEngine.h\"\n#import \"JPRootViewController.h\"\n@implementation AppDelegate\n\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {\n    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];\n    JPRootViewController *rootViewController = [[JPRootViewController alloc] init];\n    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];\n    self.window.rootViewController = navigationController;\n    [self.window makeKeyAndVisible];\n    return YES;\n}\n@end\n"
  },
  {
    "path": "Demo/iOSPlaygroundToolDemo/JSPatchPlaygroundDemo/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"60x60\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"60x60\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"76x76\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"76x76\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"83.5x83.5\",\n      \"scale\" : \"2x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Demo/iOSPlaygroundToolDemo/JSPatchPlaygroundDemo/Assets.xcassets/Contents.json",
    "content": "{\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Demo/iOSPlaygroundToolDemo/JSPatchPlaygroundDemo/Assets.xcassets/apple.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"apple.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Demo/iOSPlaygroundToolDemo/JSPatchPlaygroundDemo/Base.lproj/LaunchScreen.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"8150\" systemVersion=\"15A204g\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" launchScreen=\"YES\" useTraitCollections=\"YES\" initialViewController=\"01J-lp-oVM\">\n    <dependencies>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"8122\"/>\n    </dependencies>\n    <scenes>\n        <!--View Controller-->\n        <scene sceneID=\"EHf-IW-A2E\">\n            <objects>\n                <viewController id=\"01J-lp-oVM\" sceneMemberID=\"viewController\">\n                    <layoutGuides>\n                        <viewControllerLayoutGuide type=\"top\" id=\"Llm-lL-Icb\"/>\n                        <viewControllerLayoutGuide type=\"bottom\" id=\"xb3-aO-Qok\"/>\n                    </layoutGuides>\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"Ze5-6b-2t3\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"600\" height=\"600\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <animations/>\n                        <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"calibratedWhite\"/>\n                    </view>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"iYj-Kq-Ea1\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"53\" y=\"375\"/>\n        </scene>\n    </scenes>\n</document>\n"
  },
  {
    "path": "Demo/iOSPlaygroundToolDemo/JSPatchPlaygroundDemo/Base.lproj/Main.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"6211\" systemVersion=\"14A298i\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" useTraitCollections=\"YES\" initialViewController=\"BYZ-38-t0r\">\n    <dependencies>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"6204\"/>\n    </dependencies>\n    <scenes>\n        <!--View Controller-->\n        <scene sceneID=\"tne-QT-ifu\">\n            <objects>\n                <viewController id=\"BYZ-38-t0r\" customClass=\"ViewController\" customModuleProvider=\"\" sceneMemberID=\"viewController\">\n                    <layoutGuides>\n                        <viewControllerLayoutGuide type=\"top\" id=\"y3c-jy-aDJ\"/>\n                        <viewControllerLayoutGuide type=\"bottom\" id=\"wfy-db-euE\"/>\n                    </layoutGuides>\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"8bC-Xf-vdC\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"600\" height=\"600\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"calibratedWhite\"/>\n                    </view>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"dkx-z0-nzr\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n        </scene>\n    </scenes>\n</document>\n"
  },
  {
    "path": "Demo/iOSPlaygroundToolDemo/JSPatchPlaygroundDemo/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n\t<key>LSRequiresIPhoneOS</key>\n\t<true/>\n\t<key>UILaunchStoryboardName</key>\n\t<string>LaunchScreen</string>\n\t<key>UIMainStoryboardFile</key>\n\t<string>Main</string>\n\t<key>UIRequiredDeviceCapabilities</key>\n\t<array>\n\t\t<string>armv7</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations~ipad</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationPortraitUpsideDown</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>projectPath</key>\n\t<string>$(SRCROOT)/$(TARGET_NAME)</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Demo/iOSPlaygroundToolDemo/JSPatchPlaygroundDemo/JPRootViewController.h",
    "content": "//\n//  ViewController.h\n//  JSPatchPlayground\n//\n//  Created by bang on 5/14/16.\n//  Copyright © 2016 bang. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface JPRootViewController : UIViewController\n\n\n@end\n\n"
  },
  {
    "path": "Demo/iOSPlaygroundToolDemo/JSPatchPlaygroundDemo/JPRootViewController.m",
    "content": "//\n//  ViewController.m\n//  JSPatchPlayground\n//\n//  Created by bang on 5/14/16.\n//  Copyright © 2016 bang. All rights reserved.\n//\n\n#import \"JPRootViewController.h\"\n#import \"JPEngine.h\"\n#import \"JPPlayground.h\"\n\n\n\n@interface JPRootViewController ()\n\n@end\n\n@implementation JPRootViewController\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    self.view.backgroundColor = [UIColor whiteColor];\n    \n    \n    [JPEngine startEngine];\n    \n    \n#if TARGET_IPHONE_SIMULATOR\n    //playground调试\n    //JS测试包的本地绝对路径\n    NSString *rootPath = [[NSBundle mainBundle] objectForInfoDictionaryKey:@\"projectPath\"];;\n    \n    NSString *scriptPath = [NSString stringWithFormat:@\"%@/js/%@\", rootPath, @\"/demo.js\"];\n    [JPPlayground setReloadCompleteHandler:^{\n        [self showController];\n    }];\n    [JPPlayground startPlaygroundWithJSPath:scriptPath];\n    \n#else\n    //正常执行JSPatch\n    NSString *rootPath = [[NSBundle mainBundle] bundlePath];\n    NSString *scriptPath = [rootPath stringByAppendingPathComponent:@\"demo.js\"];\n    [JPEngine evaluateScriptWithPath:scriptPath];\n#endif\n    \n    \n    \n    UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 100, [UIScreen mainScreen].bounds.size.width, 50)];\n    [btn setTitle:@\"Push Playground\" forState:UIControlStateNormal];\n    [btn addTarget:self action:@selector(showController) forControlEvents:UIControlEventTouchUpInside];\n    [btn setBackgroundColor:[UIColor grayColor]];\n    [self.view addSubview:btn];\n}\n\n\n- (void)showController\n{\n    Class clz = NSClassFromString(@\"JPDemoController\");\n    if (clz) {\n        id vc = [[clz alloc]init];\n        [self.navigationController popViewControllerAnimated:NO];\n        [self.navigationController pushViewController:vc animated:NO];\n    }\n}\n\n\n@end\n"
  },
  {
    "path": "Demo/iOSPlaygroundToolDemo/JSPatchPlaygroundDemo/js/demo.js",
    "content": "require('UILabel, UIColor, UIFont, UIScreen, UIImageView, UIImage')\n\nvar screenWidth = UIScreen.mainScreen().bounds().width;\nvar screenHeight = UIScreen.mainScreen().bounds().height;\n\ndefineClass('JPDemoController: UIViewController', {\n    viewDidLoad: function() {\n        self.super().viewDidLoad();\n        self.view().setBackgroundColor(UIColor.whiteColor());\n        var size = 120;\n        var imgView = UIImageView.alloc().initWithFrame({x: (screenWidth - size)/2, y: 150, width: size, height: size});\n        imgView.setImage(UIImage.imageNamed('apple'))\n        \n        self.view().addSubview(imgView);\n\n        var label = UILabesl.alloc().initWithFrame({x: 0, y: 310, width: screenWidth, height: 30});\n        label.setText(\"JSPatc22h\");\n        label.setTextAlignment(1);\n        label.setFont(UIFont.systemFontOfSize(25));\n        self.view().addSubview(label);\n    },\n})\n"
  },
  {
    "path": "Demo/iOSPlaygroundToolDemo/JSPatchPlaygroundDemo/main.m",
    "content": "//\n//  main.m\n//  JSPatchPlaygroundDemo\n//\n//  Created by Awhisper on 16/8/7.\n//  Copyright © 2016年 baidu. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n#import \"AppDelegate.h\"\n\nint main(int argc, char * argv[]) {\n    @autoreleasepool {\n        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));\n    }\n}\n"
  },
  {
    "path": "Demo/iOSPlaygroundToolDemo/JSPatchPlaygroundDemo.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t6C0910D41D5829C6006CB65E /* JPCFunction.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910771D5829C6006CB65E /* JPCFunction.m */; };\n\t\t6C0910D51D5829C6006CB65E /* JPMemory.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910791D5829C6006CB65E /* JPMemory.m */; };\n\t\t6C0910D61D5829C6006CB65E /* JPStructPointer.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C09107B1D5829C6006CB65E /* JPStructPointer.m */; };\n\t\t6C0910D71D5829C6006CB65E /* ffi_arm64.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910901D5829C6006CB65E /* ffi_arm64.c */; };\n\t\t6C0910D81D5829C6006CB65E /* sysv_arm64.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910911D5829C6006CB65E /* sysv_arm64.S */; };\n\t\t6C0910D91D5829C6006CB65E /* ffi_armv7.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910931D5829C6006CB65E /* ffi_armv7.c */; };\n\t\t6C0910DA1D5829C6006CB65E /* sysv_armv7.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910941D5829C6006CB65E /* sysv_armv7.S */; };\n\t\t6C0910DB1D5829C6006CB65E /* trampoline_armv7.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910951D5829C6006CB65E /* trampoline_armv7.S */; };\n\t\t6C0910DC1D5829C6006CB65E /* prep_cif.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910971D5829C6006CB65E /* prep_cif.c */; };\n\t\t6C0910DD1D5829C6006CB65E /* raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910981D5829C6006CB65E /* raw_api.c */; };\n\t\t6C0910DE1D5829C6006CB65E /* types.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910991D5829C6006CB65E /* types.c */; };\n\t\t6C0910DF1D5829C6006CB65E /* darwin64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C09109B1D5829C6006CB65E /* darwin64_x86_64.S */; };\n\t\t6C0910E01D5829C6006CB65E /* darwin_i386.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C09109C1D5829C6006CB65E /* darwin_i386.S */; };\n\t\t6C0910E11D5829C6006CB65E /* ffi64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C09109D1D5829C6006CB65E /* ffi64_x86_64.c */; };\n\t\t6C0910E21D5829C6006CB65E /* ffi_i386.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C09109E1D5829C6006CB65E /* ffi_i386.c */; };\n\t\t6C0910E31D5829C6006CB65E /* win32_i386.S in Sources */ = {isa = PBXBuildFile; fileRef = 6C09109F1D5829C6006CB65E /* win32_i386.S */; };\n\t\t6C0910E41D5829C6006CB65E /* JPCGBitmapContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910A31D5829C6006CB65E /* JPCGBitmapContext.m */; };\n\t\t6C0910E51D5829C6006CB65E /* JPCGColor.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910A51D5829C6006CB65E /* JPCGColor.m */; };\n\t\t6C0910E61D5829C6006CB65E /* JPCGContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910A71D5829C6006CB65E /* JPCGContext.m */; };\n\t\t6C0910E71D5829C6006CB65E /* JPCGGeometry.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910A91D5829C6006CB65E /* JPCGGeometry.m */; };\n\t\t6C0910E81D5829C6006CB65E /* JPCGImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910AB1D5829C6006CB65E /* JPCGImage.m */; };\n\t\t6C0910E91D5829C6006CB65E /* JPCGPath.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910AD1D5829C6006CB65E /* JPCGPath.m */; };\n\t\t6C0910EA1D5829C6006CB65E /* JPCGTransform.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910AF1D5829C6006CB65E /* JPCGTransform.m */; };\n\t\t6C0910EB1D5829C6006CB65E /* JPCoreGraphics.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910B11D5829C6006CB65E /* JPCoreGraphics.m */; };\n\t\t6C0910EC1D5829C6006CB65E /* JPUIGeometry.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910B41D5829C6006CB65E /* JPUIGeometry.m */; };\n\t\t6C0910ED1D5829C6006CB65E /* JPUIGraphics.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910B61D5829C6006CB65E /* JPUIGraphics.m */; };\n\t\t6C0910EE1D5829C6006CB65E /* JPUIImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910B81D5829C6006CB65E /* JPUIImage.m */; };\n\t\t6C0910EF1D5829C6006CB65E /* JPUIKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910BA1D5829C6006CB65E /* JPUIKit.m */; };\n\t\t6C0910F01D5829C6006CB65E /* JPCleaner.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910BC1D5829C6006CB65E /* JPCleaner.m */; };\n\t\t6C0910F11D5829C6006CB65E /* JPLocker.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910BE1D5829C6006CB65E /* JPLocker.m */; };\n\t\t6C0910F21D5829C6006CB65E /* JPPlayground.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910C11D5829C6006CB65E /* JPPlayground.m */; };\n\t\t6C0910F31D5829C6006CB65E /* JPKeyCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910C41D5829C6006CB65E /* JPKeyCommands.m */; };\n\t\t6C0910F41D5829C6006CB65E /* SGDirWatchdog.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910C61D5829C6006CB65E /* SGDirWatchdog.m */; };\n\t\t6C0910F51D5829C6006CB65E /* JPDevErrorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910C91D5829C6006CB65E /* JPDevErrorView.m */; };\n\t\t6C0910F61D5829C6006CB65E /* JPDevMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910CB1D5829C6006CB65E /* JPDevMenu.m */; };\n\t\t6C0910F71D5829C6006CB65E /* JPDevTipView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910CD1D5829C6006CB65E /* JPDevTipView.m */; };\n\t\t6C0910F81D5829C6006CB65E /* JPSpecialInit.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910CF1D5829C6006CB65E /* JPSpecialInit.m */; };\n\t\t6C0910F91D5829C6006CB65E /* JPEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C0910D21D5829C6006CB65E /* JPEngine.m */; };\n\t\t6C0910FA1D5829C6006CB65E /* JSPatch.js in Resources */ = {isa = PBXBuildFile; fileRef = 6C0910D31D5829C6006CB65E /* JSPatch.js */; };\n\t\t6C5D37AD1D56F58600B78CD9 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C5D37AC1D56F58600B78CD9 /* main.m */; };\n\t\t6C5D37B01D56F58600B78CD9 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C5D37AF1D56F58600B78CD9 /* AppDelegate.m */; };\n\t\t6C5D37B61D56F58600B78CD9 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6C5D37B41D56F58600B78CD9 /* Main.storyboard */; };\n\t\t6C5D37B81D56F58600B78CD9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6C5D37B71D56F58600B78CD9 /* Assets.xcassets */; };\n\t\t6C5D37BB1D56F58600B78CD9 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6C5D37B91D56F58600B78CD9 /* LaunchScreen.storyboard */; };\n\t\t6C5D387B1D57237200B78CD9 /* JPRootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C5D387A1D57237200B78CD9 /* JPRootViewController.m */; };\n\t\t6CC772261D575D400001B951 /* demo.js in Resources */ = {isa = PBXBuildFile; fileRef = 6CC772241D575D400001B951 /* demo.js */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXFileReference section */\n\t\t6C0910761D5829C6006CB65E /* JPCFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCFunction.h; sourceTree = \"<group>\"; };\n\t\t6C0910771D5829C6006CB65E /* JPCFunction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCFunction.m; sourceTree = \"<group>\"; };\n\t\t6C0910781D5829C6006CB65E /* JPMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPMemory.h; sourceTree = \"<group>\"; };\n\t\t6C0910791D5829C6006CB65E /* JPMemory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPMemory.m; sourceTree = \"<group>\"; };\n\t\t6C09107A1D5829C6006CB65E /* JPStructPointer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPStructPointer.h; sourceTree = \"<group>\"; };\n\t\t6C09107B1D5829C6006CB65E /* JPStructPointer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPStructPointer.m; sourceTree = \"<group>\"; };\n\t\t6C09107E1D5829C6006CB65E /* ffi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi.h; sourceTree = \"<group>\"; };\n\t\t6C09107F1D5829C6006CB65E /* ffi_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_arm64.h; sourceTree = \"<group>\"; };\n\t\t6C0910801D5829C6006CB65E /* ffi_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_armv7.h; sourceTree = \"<group>\"; };\n\t\t6C0910811D5829C6006CB65E /* ffi_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_common.h; sourceTree = \"<group>\"; };\n\t\t6C0910821D5829C6006CB65E /* ffi_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_i386.h; sourceTree = \"<group>\"; };\n\t\t6C0910831D5829C6006CB65E /* ffi_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_x86_64.h; sourceTree = \"<group>\"; };\n\t\t6C0910841D5829C6006CB65E /* fficonfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig.h; sourceTree = \"<group>\"; };\n\t\t6C0910851D5829C6006CB65E /* fficonfig_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_arm64.h; sourceTree = \"<group>\"; };\n\t\t6C0910861D5829C6006CB65E /* fficonfig_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_armv7.h; sourceTree = \"<group>\"; };\n\t\t6C0910871D5829C6006CB65E /* fficonfig_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_i386.h; sourceTree = \"<group>\"; };\n\t\t6C0910881D5829C6006CB65E /* fficonfig_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_x86_64.h; sourceTree = \"<group>\"; };\n\t\t6C0910891D5829C6006CB65E /* ffitarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget.h; sourceTree = \"<group>\"; };\n\t\t6C09108A1D5829C6006CB65E /* ffitarget_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_arm64.h; sourceTree = \"<group>\"; };\n\t\t6C09108B1D5829C6006CB65E /* ffitarget_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_armv7.h; sourceTree = \"<group>\"; };\n\t\t6C09108C1D5829C6006CB65E /* ffitarget_i386.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_i386.h; sourceTree = \"<group>\"; };\n\t\t6C09108D1D5829C6006CB65E /* ffitarget_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_x86_64.h; sourceTree = \"<group>\"; };\n\t\t6C0910901D5829C6006CB65E /* ffi_arm64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi_arm64.c; sourceTree = \"<group>\"; };\n\t\t6C0910911D5829C6006CB65E /* sysv_arm64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = sysv_arm64.S; sourceTree = \"<group>\"; };\n\t\t6C0910931D5829C6006CB65E /* ffi_armv7.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi_armv7.c; sourceTree = \"<group>\"; };\n\t\t6C0910941D5829C6006CB65E /* sysv_armv7.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = sysv_armv7.S; sourceTree = \"<group>\"; };\n\t\t6C0910951D5829C6006CB65E /* trampoline_armv7.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = trampoline_armv7.S; sourceTree = \"<group>\"; };\n\t\t6C0910971D5829C6006CB65E /* prep_cif.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = prep_cif.c; sourceTree = \"<group>\"; };\n\t\t6C0910981D5829C6006CB65E /* raw_api.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = raw_api.c; sourceTree = \"<group>\"; };\n\t\t6C0910991D5829C6006CB65E /* types.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = types.c; sourceTree = \"<group>\"; };\n\t\t6C09109B1D5829C6006CB65E /* darwin64_x86_64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin64_x86_64.S; sourceTree = \"<group>\"; };\n\t\t6C09109C1D5829C6006CB65E /* darwin_i386.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = darwin_i386.S; sourceTree = \"<group>\"; };\n\t\t6C09109D1D5829C6006CB65E /* ffi64_x86_64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi64_x86_64.c; sourceTree = \"<group>\"; };\n\t\t6C09109E1D5829C6006CB65E /* ffi_i386.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi_i386.c; sourceTree = \"<group>\"; };\n\t\t6C09109F1D5829C6006CB65E /* win32_i386.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = win32_i386.S; sourceTree = \"<group>\"; };\n\t\t6C0910A21D5829C6006CB65E /* JPCGBitmapContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGBitmapContext.h; sourceTree = \"<group>\"; };\n\t\t6C0910A31D5829C6006CB65E /* JPCGBitmapContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGBitmapContext.m; sourceTree = \"<group>\"; };\n\t\t6C0910A41D5829C6006CB65E /* JPCGColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGColor.h; sourceTree = \"<group>\"; };\n\t\t6C0910A51D5829C6006CB65E /* JPCGColor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGColor.m; sourceTree = \"<group>\"; };\n\t\t6C0910A61D5829C6006CB65E /* JPCGContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGContext.h; sourceTree = \"<group>\"; };\n\t\t6C0910A71D5829C6006CB65E /* JPCGContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGContext.m; sourceTree = \"<group>\"; };\n\t\t6C0910A81D5829C6006CB65E /* JPCGGeometry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGGeometry.h; sourceTree = \"<group>\"; };\n\t\t6C0910A91D5829C6006CB65E /* JPCGGeometry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGGeometry.m; sourceTree = \"<group>\"; };\n\t\t6C0910AA1D5829C6006CB65E /* JPCGImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGImage.h; sourceTree = \"<group>\"; };\n\t\t6C0910AB1D5829C6006CB65E /* JPCGImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGImage.m; sourceTree = \"<group>\"; };\n\t\t6C0910AC1D5829C6006CB65E /* JPCGPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGPath.h; sourceTree = \"<group>\"; };\n\t\t6C0910AD1D5829C6006CB65E /* JPCGPath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGPath.m; sourceTree = \"<group>\"; };\n\t\t6C0910AE1D5829C6006CB65E /* JPCGTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGTransform.h; sourceTree = \"<group>\"; };\n\t\t6C0910AF1D5829C6006CB65E /* JPCGTransform.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGTransform.m; sourceTree = \"<group>\"; };\n\t\t6C0910B01D5829C6006CB65E /* JPCoreGraphics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCoreGraphics.h; sourceTree = \"<group>\"; };\n\t\t6C0910B11D5829C6006CB65E /* JPCoreGraphics.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCoreGraphics.m; sourceTree = \"<group>\"; };\n\t\t6C0910B31D5829C6006CB65E /* JPUIGeometry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPUIGeometry.h; sourceTree = \"<group>\"; };\n\t\t6C0910B41D5829C6006CB65E /* JPUIGeometry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPUIGeometry.m; sourceTree = \"<group>\"; };\n\t\t6C0910B51D5829C6006CB65E /* JPUIGraphics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPUIGraphics.h; sourceTree = \"<group>\"; };\n\t\t6C0910B61D5829C6006CB65E /* JPUIGraphics.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPUIGraphics.m; sourceTree = \"<group>\"; };\n\t\t6C0910B71D5829C6006CB65E /* JPUIImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPUIImage.h; sourceTree = \"<group>\"; };\n\t\t6C0910B81D5829C6006CB65E /* JPUIImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPUIImage.m; sourceTree = \"<group>\"; };\n\t\t6C0910B91D5829C6006CB65E /* JPUIKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPUIKit.h; sourceTree = \"<group>\"; };\n\t\t6C0910BA1D5829C6006CB65E /* JPUIKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPUIKit.m; sourceTree = \"<group>\"; };\n\t\t6C0910BB1D5829C6006CB65E /* JPCleaner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCleaner.h; sourceTree = \"<group>\"; };\n\t\t6C0910BC1D5829C6006CB65E /* JPCleaner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCleaner.m; sourceTree = \"<group>\"; };\n\t\t6C0910BD1D5829C6006CB65E /* JPLocker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPLocker.h; sourceTree = \"<group>\"; };\n\t\t6C0910BE1D5829C6006CB65E /* JPLocker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPLocker.m; sourceTree = \"<group>\"; };\n\t\t6C0910C01D5829C6006CB65E /* JPPlayground.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPPlayground.h; sourceTree = \"<group>\"; };\n\t\t6C0910C11D5829C6006CB65E /* JPPlayground.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPPlayground.m; sourceTree = \"<group>\"; };\n\t\t6C0910C31D5829C6006CB65E /* JPKeyCommands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPKeyCommands.h; sourceTree = \"<group>\"; };\n\t\t6C0910C41D5829C6006CB65E /* JPKeyCommands.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPKeyCommands.m; sourceTree = \"<group>\"; };\n\t\t6C0910C51D5829C6006CB65E /* SGDirWatchdog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SGDirWatchdog.h; sourceTree = \"<group>\"; };\n\t\t6C0910C61D5829C6006CB65E /* SGDirWatchdog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SGDirWatchdog.m; sourceTree = \"<group>\"; };\n\t\t6C0910C81D5829C6006CB65E /* JPDevErrorView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPDevErrorView.h; sourceTree = \"<group>\"; };\n\t\t6C0910C91D5829C6006CB65E /* JPDevErrorView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPDevErrorView.m; sourceTree = \"<group>\"; };\n\t\t6C0910CA1D5829C6006CB65E /* JPDevMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPDevMenu.h; sourceTree = \"<group>\"; };\n\t\t6C0910CB1D5829C6006CB65E /* JPDevMenu.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPDevMenu.m; sourceTree = \"<group>\"; };\n\t\t6C0910CC1D5829C6006CB65E /* JPDevTipView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPDevTipView.h; sourceTree = \"<group>\"; };\n\t\t6C0910CD1D5829C6006CB65E /* JPDevTipView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPDevTipView.m; sourceTree = \"<group>\"; };\n\t\t6C0910CE1D5829C6006CB65E /* JPSpecialInit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPSpecialInit.h; sourceTree = \"<group>\"; };\n\t\t6C0910CF1D5829C6006CB65E /* JPSpecialInit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPSpecialInit.m; sourceTree = \"<group>\"; };\n\t\t6C0910D11D5829C6006CB65E /* JPEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPEngine.h; sourceTree = \"<group>\"; };\n\t\t6C0910D21D5829C6006CB65E /* JPEngine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPEngine.m; sourceTree = \"<group>\"; };\n\t\t6C0910D31D5829C6006CB65E /* JSPatch.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = JSPatch.js; sourceTree = \"<group>\"; };\n\t\t6C5D37A81D56F58600B78CD9 /* JSPatchPlaygroundDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JSPatchPlaygroundDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t6C5D37AC1D56F58600B78CD9 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = \"<group>\"; };\n\t\t6C5D37AE1D56F58600B78CD9 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = \"<group>\"; };\n\t\t6C5D37AF1D56F58600B78CD9 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = \"<group>\"; };\n\t\t6C5D37B51D56F58600B78CD9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = \"<group>\"; };\n\t\t6C5D37B71D56F58600B78CD9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = \"<group>\"; };\n\t\t6C5D37BA1D56F58600B78CD9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = \"<group>\"; };\n\t\t6C5D37BC1D56F58600B78CD9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t6C5D38791D57237200B78CD9 /* JPRootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPRootViewController.h; sourceTree = \"<group>\"; };\n\t\t6C5D387A1D57237200B78CD9 /* JPRootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPRootViewController.m; sourceTree = \"<group>\"; };\n\t\t6CC772241D575D400001B951 /* demo.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = demo.js; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t6C5D37A51D56F58600B78CD9 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t6C0910741D5829C6006CB65E /* Extensions */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6C0910751D5829C6006CB65E /* JPCFunction */,\n\t\t\t\t6C0910A01D5829C6006CB65E /* JPCFunctionBinder */,\n\t\t\t\t6C0910BB1D5829C6006CB65E /* JPCleaner.h */,\n\t\t\t\t6C0910BC1D5829C6006CB65E /* JPCleaner.m */,\n\t\t\t\t6C0910BD1D5829C6006CB65E /* JPLocker.h */,\n\t\t\t\t6C0910BE1D5829C6006CB65E /* JPLocker.m */,\n\t\t\t\t6C0910BF1D5829C6006CB65E /* JPPlaygroundTool */,\n\t\t\t\t6C0910CE1D5829C6006CB65E /* JPSpecialInit.h */,\n\t\t\t\t6C0910CF1D5829C6006CB65E /* JPSpecialInit.m */,\n\t\t\t);\n\t\t\tname = Extensions;\n\t\t\tpath = ../../Extensions;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6C0910751D5829C6006CB65E /* JPCFunction */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6C0910761D5829C6006CB65E /* JPCFunction.h */,\n\t\t\t\t6C0910771D5829C6006CB65E /* JPCFunction.m */,\n\t\t\t\t6C0910781D5829C6006CB65E /* JPMemory.h */,\n\t\t\t\t6C0910791D5829C6006CB65E /* JPMemory.m */,\n\t\t\t\t6C09107A1D5829C6006CB65E /* JPStructPointer.h */,\n\t\t\t\t6C09107B1D5829C6006CB65E /* JPStructPointer.m */,\n\t\t\t\t6C09107C1D5829C6006CB65E /* libffi */,\n\t\t\t);\n\t\t\tpath = JPCFunction;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6C09107C1D5829C6006CB65E /* libffi */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6C09107D1D5829C6006CB65E /* headers */,\n\t\t\t\t6C09108E1D5829C6006CB65E /* src */,\n\t\t\t);\n\t\t\tpath = libffi;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6C09107D1D5829C6006CB65E /* headers */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6C09107E1D5829C6006CB65E /* ffi.h */,\n\t\t\t\t6C09107F1D5829C6006CB65E /* ffi_arm64.h */,\n\t\t\t\t6C0910801D5829C6006CB65E /* ffi_armv7.h */,\n\t\t\t\t6C0910811D5829C6006CB65E /* ffi_common.h */,\n\t\t\t\t6C0910821D5829C6006CB65E /* ffi_i386.h */,\n\t\t\t\t6C0910831D5829C6006CB65E /* ffi_x86_64.h */,\n\t\t\t\t6C0910841D5829C6006CB65E /* fficonfig.h */,\n\t\t\t\t6C0910851D5829C6006CB65E /* fficonfig_arm64.h */,\n\t\t\t\t6C0910861D5829C6006CB65E /* fficonfig_armv7.h */,\n\t\t\t\t6C0910871D5829C6006CB65E /* fficonfig_i386.h */,\n\t\t\t\t6C0910881D5829C6006CB65E /* fficonfig_x86_64.h */,\n\t\t\t\t6C0910891D5829C6006CB65E /* ffitarget.h */,\n\t\t\t\t6C09108A1D5829C6006CB65E /* ffitarget_arm64.h */,\n\t\t\t\t6C09108B1D5829C6006CB65E /* ffitarget_armv7.h */,\n\t\t\t\t6C09108C1D5829C6006CB65E /* ffitarget_i386.h */,\n\t\t\t\t6C09108D1D5829C6006CB65E /* ffitarget_x86_64.h */,\n\t\t\t);\n\t\t\tpath = headers;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6C09108E1D5829C6006CB65E /* src */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6C09108F1D5829C6006CB65E /* aarch64 */,\n\t\t\t\t6C0910921D5829C6006CB65E /* arm */,\n\t\t\t\t6C0910961D5829C6006CB65E /* common */,\n\t\t\t\t6C09109A1D5829C6006CB65E /* x86 */,\n\t\t\t);\n\t\t\tpath = src;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6C09108F1D5829C6006CB65E /* aarch64 */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6C0910901D5829C6006CB65E /* ffi_arm64.c */,\n\t\t\t\t6C0910911D5829C6006CB65E /* sysv_arm64.S */,\n\t\t\t);\n\t\t\tpath = aarch64;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6C0910921D5829C6006CB65E /* arm */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6C0910931D5829C6006CB65E /* ffi_armv7.c */,\n\t\t\t\t6C0910941D5829C6006CB65E /* sysv_armv7.S */,\n\t\t\t\t6C0910951D5829C6006CB65E /* trampoline_armv7.S */,\n\t\t\t);\n\t\t\tpath = arm;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6C0910961D5829C6006CB65E /* common */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6C0910971D5829C6006CB65E /* prep_cif.c */,\n\t\t\t\t6C0910981D5829C6006CB65E /* raw_api.c */,\n\t\t\t\t6C0910991D5829C6006CB65E /* types.c */,\n\t\t\t);\n\t\t\tpath = common;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6C09109A1D5829C6006CB65E /* x86 */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6C09109B1D5829C6006CB65E /* darwin64_x86_64.S */,\n\t\t\t\t6C09109C1D5829C6006CB65E /* darwin_i386.S */,\n\t\t\t\t6C09109D1D5829C6006CB65E /* ffi64_x86_64.c */,\n\t\t\t\t6C09109E1D5829C6006CB65E /* ffi_i386.c */,\n\t\t\t\t6C09109F1D5829C6006CB65E /* win32_i386.S */,\n\t\t\t);\n\t\t\tpath = x86;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6C0910A01D5829C6006CB65E /* JPCFunctionBinder */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6C0910A11D5829C6006CB65E /* CoreGraphics */,\n\t\t\t\t6C0910B21D5829C6006CB65E /* UIKit */,\n\t\t\t);\n\t\t\tpath = JPCFunctionBinder;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6C0910A11D5829C6006CB65E /* CoreGraphics */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6C0910A21D5829C6006CB65E /* JPCGBitmapContext.h */,\n\t\t\t\t6C0910A31D5829C6006CB65E /* JPCGBitmapContext.m */,\n\t\t\t\t6C0910A41D5829C6006CB65E /* JPCGColor.h */,\n\t\t\t\t6C0910A51D5829C6006CB65E /* JPCGColor.m */,\n\t\t\t\t6C0910A61D5829C6006CB65E /* JPCGContext.h */,\n\t\t\t\t6C0910A71D5829C6006CB65E /* JPCGContext.m */,\n\t\t\t\t6C0910A81D5829C6006CB65E /* JPCGGeometry.h */,\n\t\t\t\t6C0910A91D5829C6006CB65E /* JPCGGeometry.m */,\n\t\t\t\t6C0910AA1D5829C6006CB65E /* JPCGImage.h */,\n\t\t\t\t6C0910AB1D5829C6006CB65E /* JPCGImage.m */,\n\t\t\t\t6C0910AC1D5829C6006CB65E /* JPCGPath.h */,\n\t\t\t\t6C0910AD1D5829C6006CB65E /* JPCGPath.m */,\n\t\t\t\t6C0910AE1D5829C6006CB65E /* JPCGTransform.h */,\n\t\t\t\t6C0910AF1D5829C6006CB65E /* JPCGTransform.m */,\n\t\t\t\t6C0910B01D5829C6006CB65E /* JPCoreGraphics.h */,\n\t\t\t\t6C0910B11D5829C6006CB65E /* JPCoreGraphics.m */,\n\t\t\t);\n\t\t\tpath = CoreGraphics;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6C0910B21D5829C6006CB65E /* UIKit */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6C0910B31D5829C6006CB65E /* JPUIGeometry.h */,\n\t\t\t\t6C0910B41D5829C6006CB65E /* JPUIGeometry.m */,\n\t\t\t\t6C0910B51D5829C6006CB65E /* JPUIGraphics.h */,\n\t\t\t\t6C0910B61D5829C6006CB65E /* JPUIGraphics.m */,\n\t\t\t\t6C0910B71D5829C6006CB65E /* JPUIImage.h */,\n\t\t\t\t6C0910B81D5829C6006CB65E /* JPUIImage.m */,\n\t\t\t\t6C0910B91D5829C6006CB65E /* JPUIKit.h */,\n\t\t\t\t6C0910BA1D5829C6006CB65E /* JPUIKit.m */,\n\t\t\t);\n\t\t\tpath = UIKit;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6C0910BF1D5829C6006CB65E /* JPPlaygroundTool */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6C0910C01D5829C6006CB65E /* JPPlayground.h */,\n\t\t\t\t6C0910C11D5829C6006CB65E /* JPPlayground.m */,\n\t\t\t\t6C0910C21D5829C6006CB65E /* JPPlaygroundModule */,\n\t\t\t\t6C0910C71D5829C6006CB65E /* JPPlaygroundView */,\n\t\t\t);\n\t\t\tpath = JPPlaygroundTool;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6C0910C21D5829C6006CB65E /* JPPlaygroundModule */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6C0910C31D5829C6006CB65E /* JPKeyCommands.h */,\n\t\t\t\t6C0910C41D5829C6006CB65E /* JPKeyCommands.m */,\n\t\t\t\t6C0910C51D5829C6006CB65E /* SGDirWatchdog.h */,\n\t\t\t\t6C0910C61D5829C6006CB65E /* SGDirWatchdog.m */,\n\t\t\t);\n\t\t\tpath = JPPlaygroundModule;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6C0910C71D5829C6006CB65E /* JPPlaygroundView */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6C0910C81D5829C6006CB65E /* JPDevErrorView.h */,\n\t\t\t\t6C0910C91D5829C6006CB65E /* JPDevErrorView.m */,\n\t\t\t\t6C0910CA1D5829C6006CB65E /* JPDevMenu.h */,\n\t\t\t\t6C0910CB1D5829C6006CB65E /* JPDevMenu.m */,\n\t\t\t\t6C0910CC1D5829C6006CB65E /* JPDevTipView.h */,\n\t\t\t\t6C0910CD1D5829C6006CB65E /* JPDevTipView.m */,\n\t\t\t);\n\t\t\tpath = JPPlaygroundView;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6C0910D01D5829C6006CB65E /* JSPatch */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6C0910D11D5829C6006CB65E /* JPEngine.h */,\n\t\t\t\t6C0910D21D5829C6006CB65E /* JPEngine.m */,\n\t\t\t\t6C0910D31D5829C6006CB65E /* JSPatch.js */,\n\t\t\t);\n\t\t\tname = JSPatch;\n\t\t\tpath = ../../JSPatch;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6C5D379F1D56F58600B78CD9 = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6C0910741D5829C6006CB65E /* Extensions */,\n\t\t\t\t6C0910D01D5829C6006CB65E /* JSPatch */,\n\t\t\t\t6CC772231D575D400001B951 /* js */,\n\t\t\t\t6C5D37AA1D56F58600B78CD9 /* JSPatchPlaygroundDemo */,\n\t\t\t\t6C5D37A91D56F58600B78CD9 /* Products */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6C5D37A91D56F58600B78CD9 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6C5D37A81D56F58600B78CD9 /* JSPatchPlaygroundDemo.app */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6C5D37AA1D56F58600B78CD9 /* JSPatchPlaygroundDemo */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6C5D38791D57237200B78CD9 /* JPRootViewController.h */,\n\t\t\t\t6C5D387A1D57237200B78CD9 /* JPRootViewController.m */,\n\t\t\t\t6C5D37AE1D56F58600B78CD9 /* AppDelegate.h */,\n\t\t\t\t6C5D37AF1D56F58600B78CD9 /* AppDelegate.m */,\n\t\t\t\t6C5D37B41D56F58600B78CD9 /* Main.storyboard */,\n\t\t\t\t6C5D37B71D56F58600B78CD9 /* Assets.xcassets */,\n\t\t\t\t6C5D37B91D56F58600B78CD9 /* LaunchScreen.storyboard */,\n\t\t\t\t6C5D37BC1D56F58600B78CD9 /* Info.plist */,\n\t\t\t\t6C5D37AB1D56F58600B78CD9 /* Supporting Files */,\n\t\t\t);\n\t\t\tpath = JSPatchPlaygroundDemo;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6C5D37AB1D56F58600B78CD9 /* Supporting Files */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6C5D37AC1D56F58600B78CD9 /* main.m */,\n\t\t\t);\n\t\t\tname = \"Supporting Files\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6CC772231D575D400001B951 /* js */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t6CC772241D575D400001B951 /* demo.js */,\n\t\t\t);\n\t\t\tname = js;\n\t\t\tpath = JSPatchPlaygroundDemo/js;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t6C5D37A71D56F58600B78CD9 /* JSPatchPlaygroundDemo */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 6C5D37BF1D56F58600B78CD9 /* Build configuration list for PBXNativeTarget \"JSPatchPlaygroundDemo\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t6C5D37A41D56F58600B78CD9 /* Sources */,\n\t\t\t\t6C5D37A51D56F58600B78CD9 /* Frameworks */,\n\t\t\t\t6C5D37A61D56F58600B78CD9 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = JSPatchPlaygroundDemo;\n\t\t\tproductName = JSPatchPlaygroundDemo;\n\t\t\tproductReference = 6C5D37A81D56F58600B78CD9 /* JSPatchPlaygroundDemo.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t6C5D37A01D56F58600B78CD9 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 0720;\n\t\t\t\tORGANIZATIONNAME = baidu;\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t6C5D37A71D56F58600B78CD9 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.2.1;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 6C5D37A31D56F58600B78CD9 /* Build configuration list for PBXProject \"JSPatchPlaygroundDemo\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 6C5D379F1D56F58600B78CD9;\n\t\t\tproductRefGroup = 6C5D37A91D56F58600B78CD9 /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t6C5D37A71D56F58600B78CD9 /* JSPatchPlaygroundDemo */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t6C5D37A61D56F58600B78CD9 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t6C0910FA1D5829C6006CB65E /* JSPatch.js in Resources */,\n\t\t\t\t6CC772261D575D400001B951 /* demo.js in Resources */,\n\t\t\t\t6C5D37BB1D56F58600B78CD9 /* LaunchScreen.storyboard in Resources */,\n\t\t\t\t6C5D37B81D56F58600B78CD9 /* Assets.xcassets in Resources */,\n\t\t\t\t6C5D37B61D56F58600B78CD9 /* Main.storyboard in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t6C5D37A41D56F58600B78CD9 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t6C0910F41D5829C6006CB65E /* SGDirWatchdog.m in Sources */,\n\t\t\t\t6C0910D51D5829C6006CB65E /* JPMemory.m in Sources */,\n\t\t\t\t6C0910DE1D5829C6006CB65E /* types.c in Sources */,\n\t\t\t\t6C5D37B01D56F58600B78CD9 /* AppDelegate.m in Sources */,\n\t\t\t\t6C0910D61D5829C6006CB65E /* JPStructPointer.m in Sources */,\n\t\t\t\t6C0910E41D5829C6006CB65E /* JPCGBitmapContext.m in Sources */,\n\t\t\t\t6C0910E81D5829C6006CB65E /* JPCGImage.m in Sources */,\n\t\t\t\t6C0910E91D5829C6006CB65E /* JPCGPath.m in Sources */,\n\t\t\t\t6C0910D81D5829C6006CB65E /* sysv_arm64.S in Sources */,\n\t\t\t\t6C0910DA1D5829C6006CB65E /* sysv_armv7.S in Sources */,\n\t\t\t\t6C0910F51D5829C6006CB65E /* JPDevErrorView.m in Sources */,\n\t\t\t\t6C0910DF1D5829C6006CB65E /* darwin64_x86_64.S in Sources */,\n\t\t\t\t6C0910F11D5829C6006CB65E /* JPLocker.m in Sources */,\n\t\t\t\t6C5D37AD1D56F58600B78CD9 /* main.m in Sources */,\n\t\t\t\t6C0910DD1D5829C6006CB65E /* raw_api.c in Sources */,\n\t\t\t\t6C0910EF1D5829C6006CB65E /* JPUIKit.m in Sources */,\n\t\t\t\t6C5D387B1D57237200B78CD9 /* JPRootViewController.m in Sources */,\n\t\t\t\t6C0910EE1D5829C6006CB65E /* JPUIImage.m in Sources */,\n\t\t\t\t6C0910E11D5829C6006CB65E /* ffi64_x86_64.c in Sources */,\n\t\t\t\t6C0910D71D5829C6006CB65E /* ffi_arm64.c in Sources */,\n\t\t\t\t6C0910D91D5829C6006CB65E /* ffi_armv7.c in Sources */,\n\t\t\t\t6C0910E01D5829C6006CB65E /* darwin_i386.S in Sources */,\n\t\t\t\t6C0910D41D5829C6006CB65E /* JPCFunction.m in Sources */,\n\t\t\t\t6C0910DB1D5829C6006CB65E /* trampoline_armv7.S in Sources */,\n\t\t\t\t6C0910F61D5829C6006CB65E /* JPDevMenu.m in Sources */,\n\t\t\t\t6C0910E51D5829C6006CB65E /* JPCGColor.m in Sources */,\n\t\t\t\t6C0910DC1D5829C6006CB65E /* prep_cif.c in Sources */,\n\t\t\t\t6C0910EB1D5829C6006CB65E /* JPCoreGraphics.m in Sources */,\n\t\t\t\t6C0910E61D5829C6006CB65E /* JPCGContext.m in Sources */,\n\t\t\t\t6C0910E31D5829C6006CB65E /* win32_i386.S in Sources */,\n\t\t\t\t6C0910F91D5829C6006CB65E /* JPEngine.m in Sources */,\n\t\t\t\t6C0910F01D5829C6006CB65E /* JPCleaner.m in Sources */,\n\t\t\t\t6C0910ED1D5829C6006CB65E /* JPUIGraphics.m in Sources */,\n\t\t\t\t6C0910E21D5829C6006CB65E /* ffi_i386.c in Sources */,\n\t\t\t\t6C0910F81D5829C6006CB65E /* JPSpecialInit.m in Sources */,\n\t\t\t\t6C0910F21D5829C6006CB65E /* JPPlayground.m in Sources */,\n\t\t\t\t6C0910F71D5829C6006CB65E /* JPDevTipView.m in Sources */,\n\t\t\t\t6C0910EC1D5829C6006CB65E /* JPUIGeometry.m in Sources */,\n\t\t\t\t6C0910EA1D5829C6006CB65E /* JPCGTransform.m in Sources */,\n\t\t\t\t6C0910E71D5829C6006CB65E /* JPCGGeometry.m in Sources */,\n\t\t\t\t6C0910F31D5829C6006CB65E /* JPKeyCommands.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXVariantGroup section */\n\t\t6C5D37B41D56F58600B78CD9 /* Main.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t6C5D37B51D56F58600B78CD9 /* Base */,\n\t\t\t);\n\t\t\tname = Main.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t6C5D37B91D56F58600B78CD9 /* LaunchScreen.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t6C5D37BA1D56F58600B78CD9 /* Base */,\n\t\t\t);\n\t\t\tname = LaunchScreen.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\t6C5D37BD1D56F58600B78CD9 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 9.2;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t6C5D37BE1D56F58600B78CD9 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 9.2;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t6C5D37C01D56F58600B78CD9 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tINFOPLIST_FILE = JSPatchPlaygroundDemo/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.baidu.JSPatchPlaygroundDemo;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t6C5D37C11D56F58600B78CD9 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tINFOPLIST_FILE = JSPatchPlaygroundDemo/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.baidu.JSPatchPlaygroundDemo;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t6C5D37A31D56F58600B78CD9 /* Build configuration list for PBXProject \"JSPatchPlaygroundDemo\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t6C5D37BD1D56F58600B78CD9 /* Debug */,\n\t\t\t\t6C5D37BE1D56F58600B78CD9 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t6C5D37BF1D56F58600B78CD9 /* Build configuration list for PBXNativeTarget \"JSPatchPlaygroundDemo\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t6C5D37C01D56F58600B78CD9 /* Debug */,\n\t\t\t\t6C5D37C11D56F58600B78CD9 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 6C5D37A01D56F58600B78CD9 /* Project object */;\n}\n"
  },
  {
    "path": "Demo/iOSPlaygroundToolDemo/JSPatchPlaygroundDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:JSPatchPlaygroundDemo.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "Demo/iOSPlaygroundToolDemo/README.md",
    "content": "# JSPatchPlaygroundTool\n\nJSPatch天然能实现playground黑科技一样的效果，什么样的黑科技呢？我们改的每一行代码，每一个语句，完全无需重新运行app，直接能立刻看到效果。\n\n并且bang哥已经给出了如何操作和说明\n\n# JSPatch Playground\n\n[JSPatch Playground Github](https://github.com/bang590/JSPatch/tree/master/Demo/iOSPlayground)\n\n\n![Screenshot](https://raw.github.com/bang590/JSPatch/master/Demo/iOSPlayground/Screenshot.gif)\n\n## 介绍\n\nJSPatch Playground 可以让你快速看到 JSPatch 代码执行效果，APP在模拟器运行后，每次修改脚本保存模拟器都会自动刷新，无需重启模拟器，即时看到效果。\n\n你也可以仿照 JSPatch Playground 在你的项目里添加 JSPatch 脚本即时刷新功能，帮助你快速使用 JSPatch 开发功能模块。\n\nTips: 如果运行过程中脚本执行错误，会在状态栏里显示错误原因，点击状态栏可以看到更详细的错误提示。\n\n\n\n# JSPatchPlaygroundTool\n\nbang哥的Playground工程下面，可以看到想要配置这样一个如此酷炫的黑科技，[JSPatch Playground Github](https://github.com/bang590/JSPatch/tree/master/Demo/iOSPlayground) 项目下的`JPRootViewController.m`文件里面的代码还是挺多的\n\n由于前些日子搞了一阵子ReactNative，发现ReactNative下面的Debug，Reload工具很是方便，心想也给JSPatch弄一套，于是就有了这个`JSPatchPlaygroundTool`\n\n初衷是，把一整套playground的思路以及环境代码配置，封装成工具，以简洁的API就能轻松运行。\n\n<!--more-->\n\n## JSPatchPlaygroundTool的使用\n\n这段代码分成两部分，上半部分就是配置`JSPatchPlaygroundTool`，让JSPatch以Playground的模式进行工作。下半部分则是正常代码，正常的按既有方案加载JSPatch\n\n```objectivec\n#if TARGET_IPHONE_SIMULATOR\n    //playground调试\n    //JS测试包的本地绝对路径\n    NSString *rootPath = @\"/Users/Awhisper/Desktop/Github/JSPatchPlaygroundTool/JSPatchPlaygroundDemo/JSPatchPlaygroundDemo\";\n    \n    NSString *scriptRootPath = [rootPath stringByAppendingPathComponent:@\"js\"];\n    NSString *mainScriptPath = [NSString stringWithFormat:@\"%@/%@\", scriptRootPath, @\"demo.js\"];\n    [JPPlayground setReloadCompleteHandler:^{\n        [self showController];\n    }];\n    [JPPlayground startPlaygroundWithJSPath:mainScriptPath];\n    \n#else\n    //正常执行JSPatch\n    //JS测试包的本地绝对路径\n    NSString *rootPath = [[NSBundle mainBundle] bundlePath];\n    \n    NSString *scriptPath = [rootPath stringByAppendingPathComponent:@\"demo.js\"];\n    NSString *script = [NSString stringWithContentsOfFile:scriptPath encoding:NSUTF8StringEncoding error:nil];\n    [JPEngine evaluateScript:script];\n#endif\n    \n```\n\n这里只讲解上半部分的API，`rootPath`此处切记输入Mac电脑的mainJS文件所在的路径，我的目录里在工程文件`JSPatchPlaygroundDemo`下专门放了个名字为JS的文件夹，里面放着核心的JS代码逻辑，所以我又补充了`\\js\\demo.js`作为后缀\n\n- [JPPlayground setReloadCompleteHandler:block]\n\n这个API的意义在于，每次重新刷新JS后，如果有一些额外的想要操作的东西就可以在此时执行，如果没有，这个API完全可以不使用\n\n- [JPPlayground startPlaygroundWithJSPath:path]\n\n\n这个API是核心API，输入mainJS的路径后，整个JSPatch将会以playground的模式进行运行\n\n## JSPatchPlaygroundTool的效果\n\n__command + X__:可以打开操作菜单\n\n![menu](http://ww2.sinaimg.cn/mw690/678c3e91jw1f6lkzh8zwdj208n0fyaam.jpg)\n\n\n__command + R__:可以ReloadJS\n\n当APP在保持运行的时候，我们可以任意修改main.js文件然后进行保存，然后按command+R的组合键，就可以立刻刷新\n\n__JS Error__:当JS文件有错误，app并不会崩溃，保持持续运行，并且弹出红色界面，详细描述错误信息，当把js文件修改正确后，重新reload，自然就会顺利运行。\n\n![error](http://ww2.sinaimg.cn/mw690/678c3e91jw1f6lkzglfruj208n0fyq3t.jpg)\n\n__AutoReload JS__:Tool可以开启监听JS文件的变化，当你把menu中的这个开关打开，每一次修改js文件进行保存，都会自动触发reload。再次点击这个按钮，会关闭监听，（AutoReload默认不开启）\n\n__Todo List__:我还想尝试在菜单里面多做2个功能，但并未能找到办法\n\n- 自动打开Finder，打开JS文件所在的目录，从而能快速找到要修改的JS文件，轻轻松松的开始畅快的JS代码之旅，从此告别编译，运行，重启app的烦躁过程\n\n- 自动打开Safari的开发者模式，打开正在run的JSContext，从而能对js代码进行断点调试，就好像ReactNative能自动打开chrome一样\n\n我没有找到很好的办法，能在iOS框架里面，在模拟器里面，打开Mac上的Mac app，太多的方法都是OSX开发才能使用的库，比如`NSWorkSpace`，这玩意没法在iOS项目里用。发愁\n\n## JSPatchPlaygroundTool的目标\n\n当使用JSPatch进行一整个功能模块的开发，而不仅仅是只用来修改bug，能像ReactNative一样，run起app后，告别反锁的编译，运行，写出来的代码立刻就生效，代码出错也立刻报出来，丝毫不影响运行，重新修改好后，自然完美运作。\n\n# JSPatchPlayground的原理\n\n之前提到过JSPatch是天然支持这种playground的黑科技玩法的~\n\n原因就在于JSPatch的一个Extension`JPCleaner`，他可以让所有被JSPatch的hook的函数都恢复原样，这样将修改过最新的JS，重新执行以下，就实现了Reload的效果"
  },
  {
    "path": "Demo/tvOSDemo/JSPatchDemo/AppDelegate.h",
    "content": "//\n//  AppDelegate.h\n//  JSPatch\n//\n//  Created by bang on 15/4/30.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface AppDelegate : UIResponder <UIApplicationDelegate>\n\n@property (strong, nonatomic) UIWindow *window;\n\n@end\n\n"
  },
  {
    "path": "Demo/tvOSDemo/JSPatchDemo/AppDelegate.m",
    "content": "//\n//  AppDelegate.m\n//  JSPatch\n//\n//  Created by bang on 15/4/30.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import \"AppDelegate.h\"\n#import \"JPEngine.h\"\n#import \"JPViewController.h\"\n\n@implementation AppDelegate\n\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {\n    \n    [JPEngine startEngine];\n    NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@\"demo\" ofType:@\"js\"];\n    NSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil];\n    [JPEngine evaluateScript:script];\n    \n    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];\n    JPViewController *rootViewController = [[JPViewController alloc] init];\n    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];\n    self.window.rootViewController = navigationController;\n    [self.window makeKeyAndVisible];\n    \n    [[UINavigationBar appearance] setBackgroundImage:nil forBarMetrics:UIBarMetricsCompact];\n    return YES;\n}\n@end\n"
  },
  {
    "path": "Demo/tvOSDemo/JSPatchDemo/JPViewController.h",
    "content": "//\n//  JPViewController.h\n//  JSPatch\n//\n//  Created by bang on 15/5/2.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface JPViewController : UIViewController\n@end\n"
  },
  {
    "path": "Demo/tvOSDemo/JSPatchDemo/JPViewController.m",
    "content": "//\n//  JPViewController.m\n//  JSPatch\n//\n//  Created by bang on 15/5/2.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import \"JPViewController.h\"\n\n@implementation JPViewController\n\n- (void)viewDidLoad {\n    [super viewDidLoad];\n    UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 100, [UIScreen mainScreen].bounds.size.width, 50)];\n    [btn setTitle:@\"Push JPTableViewController\" forState:UIControlStateNormal];\n    [btn addTarget:self action:@selector(handleBtn:) forControlEvents:UIControlEventPrimaryActionTriggered];\n    [btn setBackgroundColor:[UIColor grayColor]];\n    [self.view addSubview:btn];\n}\n\n- (void)handleBtn:(id)sender\n{\n}\n\n@end\n\n\n"
  },
  {
    "path": "Demo/tvOSDemo/JSPatchDemo/Supporting Files/Images.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"60x60\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"60x60\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"76x76\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"76x76\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"83.5x83.5\",\n      \"scale\" : \"2x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Demo/tvOSDemo/JSPatchDemo/Supporting Files/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>net.cnbang.$(PRODUCT_NAME:rfc1034identifier)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n\t<key>LSRequiresIPhoneOS</key>\n\t<true/>\n\t<key>NSAppTransportSecurity</key>\n\t<dict>\n\t\t<key>NSAllowsArbitraryLoads</key>\n\t\t<true/>\n\t</dict>\n\t<key>UIRequiredDeviceCapabilities</key>\n\t<array>\n\t\t<string>armv7</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations~ipad</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationPortraitUpsideDown</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "Demo/tvOSDemo/JSPatchDemo/Supporting Files/main.m",
    "content": "//\n//  main.m\n//  JSPatch\n//\n//  Created by bang on 15/4/30.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n#import \"AppDelegate.h\"\n\nint main(int argc, char * argv[]) {\n    @autoreleasepool {\n        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));\n    }\n}\n"
  },
  {
    "path": "Demo/tvOSDemo/JSPatchDemo/demo.js",
    "content": "defineClass('JPViewController', {\n  handleBtn: function(sender) {\n    var tableViewCtrl = JPTableViewController.alloc().init()\n    self.navigationController().pushViewController_animated(tableViewCtrl, YES)\n  }\n})\n\ndefineClass('JPTableViewController : UITableViewController <UIAlertViewDelegate>', ['data'], {\n  dataSource: function() {\n    var data = self.data();\n    if (data) return data;\n    var data = [];\n    for (var i = 0; i < 20; i ++) {\n      data.push(\"cell from js \" + i);\n    }\n    self.setData(data)\n    return data;\n  },\n  numberOfSectionsInTableView: function(tableView) {\n    return 1;\n  },\n  tableView_numberOfRowsInSection: function(tableView, section) {\n    return self.dataSource().length;\n  },\n  tableView_cellForRowAtIndexPath: function(tableView, indexPath) {\n    var cell = tableView.dequeueReusableCellWithIdentifier(\"cell\") \n    if (!cell) {\n      cell = require('UITableViewCell').alloc().initWithStyle_reuseIdentifier(0, \"cell\")\n    }\n    cell.textLabel().setText(self.dataSource()[indexPath.row()])\n    return cell\n  },\n  tableView_heightForRowAtIndexPath: function(tableView, indexPath) {\n    return 60\n  },\n  tableView_didSelectRowAtIndexPath: function(tableView, indexPath) {\n     var alertController = require('UIAlertController').alertControllerWithTitle_message_preferredStyle(\"Alert\", self.dataSource()[indexPath.row()], 1);\n     alertController.addAction(require('UIAlertAction').actionWithTitle_style_handler(\"OK\", 0, null));\n     self.presentViewController_animated_completion(alertController, YES, null);\n  },\n  alertView_willDismissWithButtonIndex: function(alertView, idx) {\n    console.log('click btn ' + alertView.buttonTitleAtIndex(idx).toJS())\n  }\n})"
  },
  {
    "path": "Demo/tvOSDemo/JSPatchDemo.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t40D88CF81CCB7D2A00A8837D /* JPUIGeometry.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3581C6329F300E915CB /* JPUIGeometry.m */; };\n\t\t40D88CF91CCB7D2A00A8837D /* JPUIGraphics.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C35A1C6329F300E915CB /* JPUIGraphics.m */; };\n\t\t40D88CFA1CCB7D2A00A8837D /* JPUIImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C35C1C6329F300E915CB /* JPUIImage.m */; };\n\t\t40D88CFB1CCB7D2A00A8837D /* JPUIKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C35E1C6329F300E915CB /* JPUIKit.m */; };\n\t\t40D88CFC1CCB7D2A00A8837D /* JPCGBitmapContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3411C6329F300E915CB /* JPCGBitmapContext.m */; };\n\t\t40D88CFD1CCB7D2A00A8837D /* JPCGColor.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3431C6329F300E915CB /* JPCGColor.m */; };\n\t\t40D88CFE1CCB7D2A00A8837D /* JPCGContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3451C6329F300E915CB /* JPCGContext.m */; };\n\t\t40D88CFF1CCB7D2A00A8837D /* JPCGGeometry.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3471C6329F300E915CB /* JPCGGeometry.m */; };\n\t\t40D88D001CCB7D2A00A8837D /* JPCGImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3491C6329F300E915CB /* JPCGImage.m */; };\n\t\t40D88D011CCB7D2A00A8837D /* JPCGPath.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C34B1C6329F300E915CB /* JPCGPath.m */; };\n\t\t40D88D021CCB7D2A00A8837D /* JPCGTransform.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C34D1C6329F300E915CB /* JPCGTransform.m */; };\n\t\t40D88D031CCB7D2A00A8837D /* JPCoreGraphics.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C34F1C6329F300E915CB /* JPCoreGraphics.m */; };\n\t\t40D88D041CCB7D2A00A8837D /* JPMemory.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3531C6329F300E915CB /* JPMemory.m */; };\n\t\t40D88D051CCB7D2A00A8837D /* JPStructPointer.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3551C6329F300E915CB /* JPStructPointer.m */; };\n\t\t40D88D061CCB7D2A00A8837D /* JPSpecialInit.m in Sources */ = {isa = PBXBuildFile; fileRef = 369EC2961C9925A400334A64 /* JPSpecialInit.m */; };\n\t\t40D88D071CCB7D2A00A8837D /* JPCleaner.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3AE1C6346F500E915CB /* JPCleaner.m */; };\n\t\t40D88D081CCB7D2A00A8837D /* JPLocker.m in Sources */ = {isa = PBXBuildFile; fileRef = 3646F8B31CA0F89C00E10774 /* JPLocker.m */; };\n\t\t40D88D091CCB7D2A00A8837D /* JPEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3611C6329F300E915CB /* JPEngine.m */; };\n\t\t40D88D0A1CCB7D2A00A8837D /* JPLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3651C6329F300E915CB /* JPLoader.m */; };\n\t\t40D88D0B1CCB7D2A00A8837D /* RSA.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3721C6329F300E915CB /* RSA.m */; };\n\t\t40D88D0C1CCB7D2A00A8837D /* ZipArchive.m in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3741C6329F300E915CB /* ZipArchive.m */; };\n\t\t40D88D0D1CCB7D2A00A8837D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D6D12FC1B0B8CF20095A435 /* main.m */; };\n\t\t40D88D0E1CCB7D2A00A8837D /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D5D89181B0B8BFF009382EC /* AppDelegate.m */; };\n\t\t40D88D0F1CCB7D2A00A8837D /* JPViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D5D891E1B0B8BFF009382EC /* JPViewController.m */; };\n\t\t40D88D161CCB7EBE00A8837D /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 40D88D151CCB7EBE00A8837D /* libz.tbd */; };\n\t\t40D88D181CCB800200A8837D /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 40D88D171CCB800200A8837D /* Foundation.framework */; };\n\t\t40D88D191CCB802A00A8837D /* ioapi.c in Sources */ = {isa = PBXBuildFile; fileRef = 3613C3691C6329F300E915CB /* ioapi.c */; };\n\t\t40D88D1A1CCB802A00A8837D /* mztools.c in Sources */ = {isa = PBXBuildFile; fileRef = 3613C36B1C6329F300E915CB /* mztools.c */; };\n\t\t40D88D1B1CCB802A00A8837D /* unzip.c in Sources */ = {isa = PBXBuildFile; fileRef = 3613C36D1C6329F300E915CB /* unzip.c */; };\n\t\t40D88D1C1CCB802A00A8837D /* zip.c in Sources */ = {isa = PBXBuildFile; fileRef = 3613C36F1C6329F300E915CB /* zip.c */; };\n\t\t40D88D1D1CCBB00400A8837D /* JSPatch.js in Resources */ = {isa = PBXBuildFile; fileRef = 3613C3621C6329F300E915CB /* JSPatch.js */; };\n\t\t40D88D1E1CCBB00400A8837D /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2D6D12FA1B0B8CF20095A435 /* Images.xcassets */; };\n\t\t40D88D1F1CCBB00400A8837D /* demo.js in Resources */ = {isa = PBXBuildFile; fileRef = 2D6D13001B0B8CFF0095A435 /* demo.js */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXFileReference section */\n\t\t2D5D89171B0B8BFF009382EC /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = \"<group>\"; };\n\t\t2D5D89181B0B8BFF009382EC /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = \"<group>\"; };\n\t\t2D5D891D1B0B8BFF009382EC /* JPViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPViewController.h; sourceTree = \"<group>\"; };\n\t\t2D5D891E1B0B8BFF009382EC /* JPViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPViewController.m; sourceTree = \"<group>\"; };\n\t\t2D6D12FA1B0B8CF20095A435 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = \"<group>\"; };\n\t\t2D6D12FB1B0B8CF20095A435 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t2D6D12FC1B0B8CF20095A435 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = \"<group>\"; };\n\t\t2D6D13001B0B8CFF0095A435 /* demo.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = demo.js; sourceTree = \"<group>\"; };\n\t\t3613C3401C6329F300E915CB /* JPCGBitmapContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGBitmapContext.h; sourceTree = \"<group>\"; };\n\t\t3613C3411C6329F300E915CB /* JPCGBitmapContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGBitmapContext.m; sourceTree = \"<group>\"; };\n\t\t3613C3421C6329F300E915CB /* JPCGColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGColor.h; sourceTree = \"<group>\"; };\n\t\t3613C3431C6329F300E915CB /* JPCGColor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGColor.m; sourceTree = \"<group>\"; };\n\t\t3613C3441C6329F300E915CB /* JPCGContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGContext.h; sourceTree = \"<group>\"; };\n\t\t3613C3451C6329F300E915CB /* JPCGContext.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGContext.m; sourceTree = \"<group>\"; };\n\t\t3613C3461C6329F300E915CB /* JPCGGeometry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGGeometry.h; sourceTree = \"<group>\"; };\n\t\t3613C3471C6329F300E915CB /* JPCGGeometry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGGeometry.m; sourceTree = \"<group>\"; };\n\t\t3613C3481C6329F300E915CB /* JPCGImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGImage.h; sourceTree = \"<group>\"; };\n\t\t3613C3491C6329F300E915CB /* JPCGImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGImage.m; sourceTree = \"<group>\"; };\n\t\t3613C34A1C6329F300E915CB /* JPCGPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGPath.h; sourceTree = \"<group>\"; };\n\t\t3613C34B1C6329F300E915CB /* JPCGPath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGPath.m; sourceTree = \"<group>\"; };\n\t\t3613C34C1C6329F300E915CB /* JPCGTransform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCGTransform.h; sourceTree = \"<group>\"; };\n\t\t3613C34D1C6329F300E915CB /* JPCGTransform.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCGTransform.m; sourceTree = \"<group>\"; };\n\t\t3613C34E1C6329F300E915CB /* JPCoreGraphics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCoreGraphics.h; sourceTree = \"<group>\"; };\n\t\t3613C34F1C6329F300E915CB /* JPCoreGraphics.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCoreGraphics.m; sourceTree = \"<group>\"; };\n\t\t3613C3521C6329F300E915CB /* JPMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPMemory.h; sourceTree = \"<group>\"; };\n\t\t3613C3531C6329F300E915CB /* JPMemory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPMemory.m; sourceTree = \"<group>\"; };\n\t\t3613C3541C6329F300E915CB /* JPStructPointer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPStructPointer.h; sourceTree = \"<group>\"; };\n\t\t3613C3551C6329F300E915CB /* JPStructPointer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPStructPointer.m; sourceTree = \"<group>\"; };\n\t\t3613C3571C6329F300E915CB /* JPUIGeometry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPUIGeometry.h; sourceTree = \"<group>\"; };\n\t\t3613C3581C6329F300E915CB /* JPUIGeometry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPUIGeometry.m; sourceTree = \"<group>\"; };\n\t\t3613C3591C6329F300E915CB /* JPUIGraphics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPUIGraphics.h; sourceTree = \"<group>\"; };\n\t\t3613C35A1C6329F300E915CB /* JPUIGraphics.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPUIGraphics.m; sourceTree = \"<group>\"; };\n\t\t3613C35B1C6329F300E915CB /* JPUIImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPUIImage.h; sourceTree = \"<group>\"; };\n\t\t3613C35C1C6329F300E915CB /* JPUIImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPUIImage.m; sourceTree = \"<group>\"; };\n\t\t3613C35D1C6329F300E915CB /* JPUIKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPUIKit.h; sourceTree = \"<group>\"; };\n\t\t3613C35E1C6329F300E915CB /* JPUIKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPUIKit.m; sourceTree = \"<group>\"; };\n\t\t3613C3601C6329F300E915CB /* JPEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPEngine.h; sourceTree = \"<group>\"; };\n\t\t3613C3611C6329F300E915CB /* JPEngine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPEngine.m; sourceTree = \"<group>\"; };\n\t\t3613C3621C6329F300E915CB /* JSPatch.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = JSPatch.js; sourceTree = \"<group>\"; };\n\t\t3613C3641C6329F300E915CB /* JPLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPLoader.h; sourceTree = \"<group>\"; };\n\t\t3613C3651C6329F300E915CB /* JPLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPLoader.m; sourceTree = \"<group>\"; };\n\t\t3613C3681C6329F300E915CB /* crypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypt.h; sourceTree = \"<group>\"; };\n\t\t3613C3691C6329F300E915CB /* ioapi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioapi.c; sourceTree = \"<group>\"; };\n\t\t3613C36A1C6329F300E915CB /* ioapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ioapi.h; sourceTree = \"<group>\"; };\n\t\t3613C36B1C6329F300E915CB /* mztools.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mztools.c; sourceTree = \"<group>\"; };\n\t\t3613C36C1C6329F300E915CB /* mztools.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mztools.h; sourceTree = \"<group>\"; };\n\t\t3613C36D1C6329F300E915CB /* unzip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = unzip.c; sourceTree = \"<group>\"; };\n\t\t3613C36E1C6329F300E915CB /* unzip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unzip.h; sourceTree = \"<group>\"; };\n\t\t3613C36F1C6329F300E915CB /* zip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zip.c; sourceTree = \"<group>\"; };\n\t\t3613C3701C6329F300E915CB /* zip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zip.h; sourceTree = \"<group>\"; };\n\t\t3613C3711C6329F300E915CB /* RSA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RSA.h; sourceTree = \"<group>\"; };\n\t\t3613C3721C6329F300E915CB /* RSA.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RSA.m; sourceTree = \"<group>\"; };\n\t\t3613C3731C6329F300E915CB /* ZipArchive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZipArchive.h; sourceTree = \"<group>\"; };\n\t\t3613C3741C6329F300E915CB /* ZipArchive.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZipArchive.m; sourceTree = \"<group>\"; };\n\t\t3613C3761C6329F300E915CB /* packer.php */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.php; path = packer.php; sourceTree = \"<group>\"; };\n\t\t3613C3AD1C6346F500E915CB /* JPCleaner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPCleaner.h; sourceTree = \"<group>\"; };\n\t\t3613C3AE1C6346F500E915CB /* JPCleaner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPCleaner.m; sourceTree = \"<group>\"; };\n\t\t3646F8B21CA0F89C00E10774 /* JPLocker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPLocker.h; sourceTree = \"<group>\"; };\n\t\t3646F8B31CA0F89C00E10774 /* JPLocker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPLocker.m; sourceTree = \"<group>\"; };\n\t\t369EC2951C9925A400334A64 /* JPSpecialInit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JPSpecialInit.h; sourceTree = \"<group>\"; };\n\t\t369EC2961C9925A400334A64 /* JPSpecialInit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JPSpecialInit.m; sourceTree = \"<group>\"; };\n\t\t40D88CE41CCB7D0100A8837D /* JSPatchDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JSPatchDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t40D88D101CCB7DB800A8837D /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.2.sdk/System/Library/Frameworks/JavaScriptCore.framework; sourceTree = DEVELOPER_DIR; };\n\t\t40D88D121CCB7DBF00A8837D /* libz.1.tbd */ = {isa = PBXFileReference; lastKnownFileType = \"sourcecode.text-based-dylib-definition\"; name = libz.1.tbd; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.2.sdk/usr/lib/libz.1.tbd; sourceTree = DEVELOPER_DIR; };\n\t\t40D88D151CCB7EBE00A8837D /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = \"sourcecode.text-based-dylib-definition\"; name = libz.tbd; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.2.sdk/usr/lib/libz.tbd; sourceTree = DEVELOPER_DIR; };\n\t\t40D88D171CCB800200A8837D /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS9.2.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t40D88CE11CCB7D0100A8837D /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t40D88D181CCB800200A8837D /* Foundation.framework in Frameworks */,\n\t\t\t\t40D88D161CCB7EBE00A8837D /* libz.tbd in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t2D5D89161B0B8BFF009382EC /* JSPatchDemo */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3613C33E1C6329F300E915CB /* Extensions */,\n\t\t\t\t3613C35F1C6329F300E915CB /* JSPatch */,\n\t\t\t\t3613C3631C6329F300E915CB /* Loader */,\n\t\t\t\t2D6D12F91B0B8CF20095A435 /* Supporting Files */,\n\t\t\t\t2D5D89171B0B8BFF009382EC /* AppDelegate.h */,\n\t\t\t\t2D5D89181B0B8BFF009382EC /* AppDelegate.m */,\n\t\t\t\t2D5D891D1B0B8BFF009382EC /* JPViewController.h */,\n\t\t\t\t2D5D891E1B0B8BFF009382EC /* JPViewController.m */,\n\t\t\t\t2D6D13001B0B8CFF0095A435 /* demo.js */,\n\t\t\t);\n\t\t\tpath = JSPatchDemo;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t2D6D12F91B0B8CF20095A435 /* Supporting Files */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t2D6D12FA1B0B8CF20095A435 /* Images.xcassets */,\n\t\t\t\t2D6D12FB1B0B8CF20095A435 /* Info.plist */,\n\t\t\t\t2D6D12FC1B0B8CF20095A435 /* main.m */,\n\t\t\t);\n\t\t\tpath = \"Supporting Files\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t3613C33E1C6329F300E915CB /* Extensions */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3613C3561C6329F300E915CB /* UIKit */,\n\t\t\t\t3613C33F1C6329F300E915CB /* CoreGraphics */,\n\t\t\t\t3613C3521C6329F300E915CB /* JPMemory.h */,\n\t\t\t\t3613C3531C6329F300E915CB /* JPMemory.m */,\n\t\t\t\t3613C3541C6329F300E915CB /* JPStructPointer.h */,\n\t\t\t\t3613C3551C6329F300E915CB /* JPStructPointer.m */,\n\t\t\t\t369EC2951C9925A400334A64 /* JPSpecialInit.h */,\n\t\t\t\t369EC2961C9925A400334A64 /* JPSpecialInit.m */,\n\t\t\t\t3613C3AD1C6346F500E915CB /* JPCleaner.h */,\n\t\t\t\t3613C3AE1C6346F500E915CB /* JPCleaner.m */,\n\t\t\t\t3646F8B21CA0F89C00E10774 /* JPLocker.h */,\n\t\t\t\t3646F8B31CA0F89C00E10774 /* JPLocker.m */,\n\t\t\t);\n\t\t\tname = Extensions;\n\t\t\tpath = ../../../Extensions;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t3613C33F1C6329F300E915CB /* CoreGraphics */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3613C3401C6329F300E915CB /* JPCGBitmapContext.h */,\n\t\t\t\t3613C3411C6329F300E915CB /* JPCGBitmapContext.m */,\n\t\t\t\t3613C3421C6329F300E915CB /* JPCGColor.h */,\n\t\t\t\t3613C3431C6329F300E915CB /* JPCGColor.m */,\n\t\t\t\t3613C3441C6329F300E915CB /* JPCGContext.h */,\n\t\t\t\t3613C3451C6329F300E915CB /* JPCGContext.m */,\n\t\t\t\t3613C3461C6329F300E915CB /* JPCGGeometry.h */,\n\t\t\t\t3613C3471C6329F300E915CB /* JPCGGeometry.m */,\n\t\t\t\t3613C3481C6329F300E915CB /* JPCGImage.h */,\n\t\t\t\t3613C3491C6329F300E915CB /* JPCGImage.m */,\n\t\t\t\t3613C34A1C6329F300E915CB /* JPCGPath.h */,\n\t\t\t\t3613C34B1C6329F300E915CB /* JPCGPath.m */,\n\t\t\t\t3613C34C1C6329F300E915CB /* JPCGTransform.h */,\n\t\t\t\t3613C34D1C6329F300E915CB /* JPCGTransform.m */,\n\t\t\t\t3613C34E1C6329F300E915CB /* JPCoreGraphics.h */,\n\t\t\t\t3613C34F1C6329F300E915CB /* JPCoreGraphics.m */,\n\t\t\t);\n\t\t\tpath = CoreGraphics;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t3613C3561C6329F300E915CB /* UIKit */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3613C3571C6329F300E915CB /* JPUIGeometry.h */,\n\t\t\t\t3613C3581C6329F300E915CB /* JPUIGeometry.m */,\n\t\t\t\t3613C3591C6329F300E915CB /* JPUIGraphics.h */,\n\t\t\t\t3613C35A1C6329F300E915CB /* JPUIGraphics.m */,\n\t\t\t\t3613C35B1C6329F300E915CB /* JPUIImage.h */,\n\t\t\t\t3613C35C1C6329F300E915CB /* JPUIImage.m */,\n\t\t\t\t3613C35D1C6329F300E915CB /* JPUIKit.h */,\n\t\t\t\t3613C35E1C6329F300E915CB /* JPUIKit.m */,\n\t\t\t);\n\t\t\tpath = UIKit;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t3613C35F1C6329F300E915CB /* JSPatch */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3613C3601C6329F300E915CB /* JPEngine.h */,\n\t\t\t\t3613C3611C6329F300E915CB /* JPEngine.m */,\n\t\t\t\t3613C3621C6329F300E915CB /* JSPatch.js */,\n\t\t\t);\n\t\t\tname = JSPatch;\n\t\t\tpath = ../../../JSPatch;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t3613C3631C6329F300E915CB /* Loader */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3613C3641C6329F300E915CB /* JPLoader.h */,\n\t\t\t\t3613C3651C6329F300E915CB /* JPLoader.m */,\n\t\t\t\t3613C3661C6329F300E915CB /* libs */,\n\t\t\t\t3613C3751C6329F300E915CB /* tools */,\n\t\t\t);\n\t\t\tname = Loader;\n\t\t\tpath = ../../../Loader;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t3613C3661C6329F300E915CB /* libs */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3613C3671C6329F300E915CB /* minizip */,\n\t\t\t\t3613C3711C6329F300E915CB /* RSA.h */,\n\t\t\t\t3613C3721C6329F300E915CB /* RSA.m */,\n\t\t\t\t3613C3731C6329F300E915CB /* ZipArchive.h */,\n\t\t\t\t3613C3741C6329F300E915CB /* ZipArchive.m */,\n\t\t\t);\n\t\t\tpath = libs;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t3613C3671C6329F300E915CB /* minizip */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3613C3681C6329F300E915CB /* crypt.h */,\n\t\t\t\t3613C3691C6329F300E915CB /* ioapi.c */,\n\t\t\t\t3613C36A1C6329F300E915CB /* ioapi.h */,\n\t\t\t\t3613C36B1C6329F300E915CB /* mztools.c */,\n\t\t\t\t3613C36C1C6329F300E915CB /* mztools.h */,\n\t\t\t\t3613C36D1C6329F300E915CB /* unzip.c */,\n\t\t\t\t3613C36E1C6329F300E915CB /* unzip.h */,\n\t\t\t\t3613C36F1C6329F300E915CB /* zip.c */,\n\t\t\t\t3613C3701C6329F300E915CB /* zip.h */,\n\t\t\t);\n\t\t\tpath = minizip;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t3613C3751C6329F300E915CB /* tools */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t3613C3761C6329F300E915CB /* packer.php */,\n\t\t\t);\n\t\t\tpath = tools;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDE94AE021AF246BE00E461D4 = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t40D88D171CCB800200A8837D /* Foundation.framework */,\n\t\t\t\t40D88D151CCB7EBE00A8837D /* libz.tbd */,\n\t\t\t\t40D88D121CCB7DBF00A8837D /* libz.1.tbd */,\n\t\t\t\t40D88D101CCB7DB800A8837D /* JavaScriptCore.framework */,\n\t\t\t\t2D5D89161B0B8BFF009382EC /* JSPatchDemo */,\n\t\t\t\tDE94AE0C1AF246BF00E461D4 /* Products */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\tDE94AE0C1AF246BF00E461D4 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t40D88CE41CCB7D0100A8837D /* JSPatchDemo.app */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t40D88CE31CCB7D0100A8837D /* JSPatchDemo */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 40D88CF51CCB7D0100A8837D /* Build configuration list for PBXNativeTarget \"JSPatchDemo\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t40D88CE01CCB7D0100A8837D /* Sources */,\n\t\t\t\t40D88CE11CCB7D0100A8837D /* Frameworks */,\n\t\t\t\t40D88CE21CCB7D0100A8837D /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = JSPatchDemo;\n\t\t\tproductName = \"JSPatchDemo-tvOS\";\n\t\t\tproductReference = 40D88CE41CCB7D0100A8837D /* JSPatchDemo.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\tDE94AE031AF246BF00E461D4 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 0620;\n\t\t\t\tORGANIZATIONNAME = bang;\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t40D88CE31CCB7D0100A8837D = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.3.1;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = DE94AE061AF246BF00E461D4 /* Build configuration list for PBXProject \"JSPatchDemo\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = DE94AE021AF246BE00E461D4;\n\t\t\tproductRefGroup = DE94AE0C1AF246BF00E461D4 /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t40D88CE31CCB7D0100A8837D /* JSPatchDemo */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t40D88CE21CCB7D0100A8837D /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t40D88D1D1CCBB00400A8837D /* JSPatch.js in Resources */,\n\t\t\t\t40D88D1E1CCBB00400A8837D /* Images.xcassets in Resources */,\n\t\t\t\t40D88D1F1CCBB00400A8837D /* demo.js in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t40D88CE01CCB7D0100A8837D /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t40D88D191CCB802A00A8837D /* ioapi.c in Sources */,\n\t\t\t\t40D88D1A1CCB802A00A8837D /* mztools.c in Sources */,\n\t\t\t\t40D88D1B1CCB802A00A8837D /* unzip.c in Sources */,\n\t\t\t\t40D88D1C1CCB802A00A8837D /* zip.c in Sources */,\n\t\t\t\t40D88CF81CCB7D2A00A8837D /* JPUIGeometry.m in Sources */,\n\t\t\t\t40D88CF91CCB7D2A00A8837D /* JPUIGraphics.m in Sources */,\n\t\t\t\t40D88CFA1CCB7D2A00A8837D /* JPUIImage.m in Sources */,\n\t\t\t\t40D88CFB1CCB7D2A00A8837D /* JPUIKit.m in Sources */,\n\t\t\t\t40D88CFC1CCB7D2A00A8837D /* JPCGBitmapContext.m in Sources */,\n\t\t\t\t40D88CFD1CCB7D2A00A8837D /* JPCGColor.m in Sources */,\n\t\t\t\t40D88CFE1CCB7D2A00A8837D /* JPCGContext.m in Sources */,\n\t\t\t\t40D88CFF1CCB7D2A00A8837D /* JPCGGeometry.m in Sources */,\n\t\t\t\t40D88D001CCB7D2A00A8837D /* JPCGImage.m in Sources */,\n\t\t\t\t40D88D011CCB7D2A00A8837D /* JPCGPath.m in Sources */,\n\t\t\t\t40D88D021CCB7D2A00A8837D /* JPCGTransform.m in Sources */,\n\t\t\t\t40D88D031CCB7D2A00A8837D /* JPCoreGraphics.m in Sources */,\n\t\t\t\t40D88D041CCB7D2A00A8837D /* JPMemory.m in Sources */,\n\t\t\t\t40D88D051CCB7D2A00A8837D /* JPStructPointer.m in Sources */,\n\t\t\t\t40D88D061CCB7D2A00A8837D /* JPSpecialInit.m in Sources */,\n\t\t\t\t40D88D071CCB7D2A00A8837D /* JPCleaner.m in Sources */,\n\t\t\t\t40D88D081CCB7D2A00A8837D /* JPLocker.m in Sources */,\n\t\t\t\t40D88D091CCB7D2A00A8837D /* JPEngine.m in Sources */,\n\t\t\t\t40D88D0A1CCB7D2A00A8837D /* JPLoader.m in Sources */,\n\t\t\t\t40D88D0B1CCB7D2A00A8837D /* RSA.m in Sources */,\n\t\t\t\t40D88D0C1CCB7D2A00A8837D /* ZipArchive.m in Sources */,\n\t\t\t\t40D88D0D1CCB7D2A00A8837D /* main.m in Sources */,\n\t\t\t\t40D88D0E1CCB7D2A00A8837D /* AppDelegate.m in Sources */,\n\t\t\t\t40D88D0F1CCB7D2A00A8837D /* JPViewController.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin XCBuildConfiguration section */\n\t\t40D88CF61CCB7D0100A8837D /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = \"App Icon & Top Shelf Image\";\n\t\t\t\tASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tINFOPLIST_FILE = \"$(SRCROOT)/JSPatchDemo/Supporting Files/Info.plist\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSDKROOT = appletvos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = 3;\n\t\t\t\tTVOS_DEPLOYMENT_TARGET = 9.2;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t40D88CF71CCB7D0100A8837D /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = \"App Icon & Top Shelf Image\";\n\t\t\t\tASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tINFOPLIST_FILE = \"$(SRCROOT)/JSPatchDemo/Supporting Files/Info.plist\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSDKROOT = appletvos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = 3;\n\t\t\t\tTVOS_DEPLOYMENT_TARGET = 9.2;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\tDE94AE2C1AF246C000E461D4 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_SYMBOLS_PRIVATE_EXTERN = NO;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 7.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\tDE94AE2D1AF246C000E461D4 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = YES;\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 7.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t40D88CF51CCB7D0100A8837D /* Build configuration list for PBXNativeTarget \"JSPatchDemo\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t40D88CF61CCB7D0100A8837D /* Debug */,\n\t\t\t\t40D88CF71CCB7D0100A8837D /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t};\n\t\tDE94AE061AF246BF00E461D4 /* Build configuration list for PBXProject \"JSPatchDemo\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\tDE94AE2C1AF246C000E461D4 /* Debug */,\n\t\t\t\tDE94AE2D1AF246C000E461D4 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = DE94AE031AF246BF00E461D4 /* Project object */;\n}\n"
  },
  {
    "path": "Demo/tvOSDemo/JSPatchDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "Extensions/JPBlock/JPBlock.h",
    "content": "//\n//  JPBlock.h\n//  JSPatch\n//\n//  Created by bang on 1/19/17.\n//  Copyright © 2017 bang. All rights reserved.\n//\n\n#import \"JPEngine.h\"\n\n@interface JPBlock : JPExtension\n+ (id)blockWithBlockObj:(id)blockObj;\n@end\n"
  },
  {
    "path": "Extensions/JPBlock/JPBlock.m",
    "content": "//\n//  JPBlock.m\n//  JSPatch\n//\n//  Created by bang on 1/19/17.\n//  Copyright © 2017 bang. All rights reserved.\n//\n\n#import \"JPBlock.h\"\n#import \"JPBlockWrapper.h\"\n#import <objc/runtime.h>\n\n@implementation JPBlock\n+ (void)main:(JSContext *)context\n{\n    context[@\"__genBlock\"] = ^id(NSString *typeString, JSValue *cb) {\n        JPBlockWrapper *blockWrapper = [[JPBlockWrapper alloc] initWithTypeString:typeString callbackFunction:cb];\n        return blockWrapper;\n    };\n}\n\n+ (id)blockWithBlockObj:(JPBlockWrapper *)blockObj\n{\n    return [blockObj blockPtr];\n}\n@end\n"
  },
  {
    "path": "Extensions/JPBlock/JPBlockWrapper.h",
    "content": "//\n//  JPBlockWrapper.h\n//  JSPatch\n//\n//  Created by bang on 1/19/17.\n//  Copyright © 2017 bang. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import <JavaScriptCore/JavaScriptCore.h>\n\n@interface JPBlockWrapper : NSObject;\n- (void *)blockPtr;\n- (id)initWithTypeString:(NSString *)typeString callbackFunction:(JSValue *)jsFunction;\n@end\n"
  },
  {
    "path": "Extensions/JPBlock/JPBlockWrapper.m",
    "content": "//\n//  JPBlockWrapper.m\n//  JSPatch\n//\n//  Created by bang on 1/19/17.\n//  Copyright © 2017 bang. All rights reserved.\n//\n\n#import \"JPBlockWrapper.h\"\n#import \"ffi.h\"\n#import \"JPEngine.h\"\n#import \"JPMethodSignature.h\"\n\nenum {\n    BLOCK_DEALLOCATING =      (0x0001),\n    BLOCK_REFCOUNT_MASK =     (0xfffe),\n    BLOCK_NEEDS_FREE =        (1 << 24),\n    BLOCK_HAS_COPY_DISPOSE =  (1 << 25),\n    BLOCK_HAS_CTOR =          (1 << 26),\n    BLOCK_IS_GC =             (1 << 27),\n    BLOCK_IS_GLOBAL =         (1 << 28),\n    BLOCK_USE_STRET =         (1 << 29),\n    BLOCK_HAS_SIGNATURE  =    (1 << 30)\n};\n\nstruct JPSimulateBlock {\n    void *isa;\n    int flags;\n    int reserved;\n    void *invoke;\n    struct JPSimulateBlockDescriptor *descriptor;\n    void *wrapper;\n};\n\nstruct JPSimulateBlockDescriptor {\n    //Block_descriptor_1\n    struct {\n        unsigned long int reserved;\n        unsigned long int size;\n    };\n\n    //Block_descriptor_2\n    struct {\n        // requires BLOCK_HAS_COPY_DISPOSE\n        void (*copy)(void *dst, const void *src);\n        void (*dispose)(const void *);\n    };\n\n    //Block_descriptor_3\n    struct {\n        // requires BLOCK_HAS_SIGNATURE\n        const char *signature;\n    };\n};\n\nvoid copy_helper(struct JPSimulateBlock *dst, struct JPSimulateBlock *src)\n{\n    // do not copy anything is this funcion! just retain if need.\n    CFRetain(dst->wrapper);\n}\n\nvoid dispose_helper(struct JPSimulateBlock *src)\n{\n    CFRelease(src->wrapper);\n}\n\n\n@interface JPBlockWrapper ()\n{\n    ffi_cif *_cifPtr;\n    ffi_type **_args;\n    ffi_closure *_closure;\n    BOOL _generatedPtr;\n    void *_blockPtr;\n    struct JPSimulateBlockDescriptor *_descriptor;\n}\n\n@property (nonatomic,strong) JPMethodSignature *signature;\n@property (nonatomic,strong) JSValue *jsFunction;\n\n@end\n\nvoid JPBlockInterpreter(ffi_cif *cif, void *ret, void **args, void *userdata)\n{\n    JPBlockWrapper *blockObj = (__bridge JPBlockWrapper*)userdata;\n\n    NSMutableArray *params = [[NSMutableArray alloc] init];\n    for (int i = 1; i < blockObj.signature.argumentTypes.count; i ++) {\n        id param;\n        void *argumentPtr = args[i];\n        const char *typeEncoding = [blockObj.signature.argumentTypes[i] UTF8String];\n        switch (typeEncoding[0]) {\n                \n        #define JP_BLOCK_PARAM_CASE(_typeString, _type, _selector) \\\n            case _typeString: {                              \\\n                _type returnValue = *(_type *)argumentPtr;                     \\\n                param = [NSNumber _selector:returnValue];\\\n                break; \\\n            }\n            JP_BLOCK_PARAM_CASE('c', char, numberWithChar)\n            JP_BLOCK_PARAM_CASE('C', unsigned char, numberWithUnsignedChar)\n            JP_BLOCK_PARAM_CASE('s', short, numberWithShort)\n            JP_BLOCK_PARAM_CASE('S', unsigned short, numberWithUnsignedShort)\n            JP_BLOCK_PARAM_CASE('i', int, numberWithInt)\n            JP_BLOCK_PARAM_CASE('I', unsigned int, numberWithUnsignedInt)\n            JP_BLOCK_PARAM_CASE('l', long, numberWithLong)\n            JP_BLOCK_PARAM_CASE('L', unsigned long, numberWithUnsignedLong)\n            JP_BLOCK_PARAM_CASE('q', long long, numberWithLongLong)\n            JP_BLOCK_PARAM_CASE('Q', unsigned long long, numberWithUnsignedLongLong)\n            JP_BLOCK_PARAM_CASE('f', float, numberWithFloat)\n            JP_BLOCK_PARAM_CASE('d', double, numberWithDouble)\n            JP_BLOCK_PARAM_CASE('B', BOOL, numberWithBool)\n                \n            case '@': {\n                param = (__bridge id)(*(void**)argumentPtr);\n                break;\n            }\n        }\n        [params addObject:[JPExtension formatOCToJS:param]];\n    }\n    \n    JSValue *jsResult = [blockObj.jsFunction callWithArguments:params];\n\n    switch ([blockObj.signature.returnType UTF8String][0]) {\n            \n    #define JP_BLOCK_RET_CASE(_typeString, _type, _selector) \\\n        case _typeString: {                              \\\n            _type *retPtr = ret; \\\n            *retPtr = [((NSNumber *)[jsResult toObject]) _selector];   \\\n            break; \\\n        }\n        \n        JP_BLOCK_RET_CASE('c', char, charValue)\n        JP_BLOCK_RET_CASE('C', unsigned char, unsignedCharValue)\n        JP_BLOCK_RET_CASE('s', short, shortValue)\n        JP_BLOCK_RET_CASE('S', unsigned short, unsignedShortValue)\n        JP_BLOCK_RET_CASE('i', int, intValue)\n        JP_BLOCK_RET_CASE('I', unsigned int, unsignedIntValue)\n        JP_BLOCK_RET_CASE('l', long, longValue)\n        JP_BLOCK_RET_CASE('L', unsigned long, unsignedLongValue)\n        JP_BLOCK_RET_CASE('q', long long, longLongValue)\n        JP_BLOCK_RET_CASE('Q', unsigned long long, unsignedLongLongValue)\n        JP_BLOCK_RET_CASE('f', float, floatValue)\n        JP_BLOCK_RET_CASE('d', double, doubleValue)\n        JP_BLOCK_RET_CASE('B', BOOL, boolValue)\n            \n        case '@':\n        case '#': {\n            id retObj = [JPExtension formatJSToOC:jsResult];\n            void **retPtrPtr = ret;\n            *retPtrPtr = (__bridge void *)retObj;\n            break;\n        }\n        case '^': {\n            JPBoxing *box = [JPExtension formatJSToOC:jsResult];\n            void *pointer = [box unboxPointer];\n            void **retPtrPtr = ret;\n            *retPtrPtr = pointer;\n            break;\n        }\n    }\n    \n}\n\n@implementation JPBlockWrapper\n\n- (id)initWithTypeString:(NSString *)typeString callbackFunction:(JSValue *)jsFunction\n{\n    self = [super init];\n    if(self) {\n        _generatedPtr = NO;\n        self.jsFunction = jsFunction;\n        self.signature = [[JPMethodSignature alloc] initWithBlockTypeNames:typeString];\n    }\n    return self;\n}\n\n- (void *)blockPtr\n{\n    if (_generatedPtr) {\n        return _blockPtr;\n    }\n    \n    _generatedPtr = YES;\n    \n    ffi_type *returnType = [JPMethodSignature ffiTypeWithEncodingChar:[self.signature.returnType UTF8String]];\n    \n    NSUInteger argumentCount = self.signature.argumentTypes.count;\n    \n    _cifPtr = malloc(sizeof(ffi_cif));\n    \n    void *blockImp = NULL;\n    \n    _args = malloc(sizeof(ffi_type *) *argumentCount) ;\n    \n    for (int i = 0; i < argumentCount; i++){\n        ffi_type* current_ffi_type = [JPMethodSignature ffiTypeWithEncodingChar:[self.signature.argumentTypes[i] UTF8String]];\n        _args[i] = current_ffi_type;\n    }\n    \n    _closure = ffi_closure_alloc(sizeof(ffi_closure), (void **)&blockImp);\n    \n    if(ffi_prep_cif(_cifPtr, FFI_DEFAULT_ABI, (unsigned int)argumentCount, returnType, _args) == FFI_OK) {\n        if (ffi_prep_closure_loc(_closure, _cifPtr, JPBlockInterpreter, (__bridge void *)self, blockImp) != FFI_OK) {\n            NSAssert(NO, @\"generate block error\");\n        }\n    }\n\n    struct JPSimulateBlockDescriptor descriptor = {\n        0,\n        sizeof(struct JPSimulateBlock),\n        (void (*)(void *dst, const void *src))copy_helper,\n        (void (*)(const void *src))dispose_helper,\n        [self.signature.types cStringUsingEncoding:NSASCIIStringEncoding]\n    };\n    \n    _descriptor = malloc(sizeof(struct JPSimulateBlockDescriptor));\n    memcpy(_descriptor, &descriptor, sizeof(struct JPSimulateBlockDescriptor));\n\n    struct JPSimulateBlock simulateBlock = {\n        &_NSConcreteStackBlock,\n        (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_SIGNATURE),\n        0,\n        blockImp,\n        _descriptor,\n        (__bridge void*)self\n    };\n\n    _blockPtr = Block_copy(&simulateBlock);\n    return _blockPtr;\n}\n\n- (void)dealloc\n{\n    ffi_closure_free(_closure);\n    free(_args);\n    free(_cifPtr);\n    free(_descriptor);\n    return;\n}\n\n@end\n"
  },
  {
    "path": "Extensions/JPCFunction/JPCFunction.h",
    "content": "//\n//  JPCFunction.h\n//  JSPatch\n//\n//  Created by bang on 5/30/16.\n//  Copyright © 2016 bang. All rights reserved.\n//\n\n#import \"JPEngine.h\"\n\n@interface JPCFunction : JPExtension\n\n@end\n"
  },
  {
    "path": "Extensions/JPCFunction/JPCFunction.m",
    "content": "//\n//  JPCFunction.m\n//  JSPatch\n//\n//  Created by bang on 5/30/16.\n//  Copyright © 2016 bang. All rights reserved.\n//\n\n#import \"JPCFunction.h\"\n#import \"ffi.h\"\n#import <dlfcn.h>\n#import \"JPMethodSignature.h\"\n\n#if CGFLOAT_IS_DOUBLE\n#define CGFloatValue doubleValue\n#define numberWithCGFloat numberWithDouble\n#else\n#define CGFloatValue floatValue\n#define numberWithCGFloat numberWithFloat\n#endif\n\n@implementation JPCFunction\n\nstatic NSMutableDictionary *_funcDefines;\n\n+ (void)main:(JSContext *)context\n{\n    if (!_funcDefines) {\n        _funcDefines = [[NSMutableDictionary alloc] init];\n    }\n    \n    [context evaluateScript:@\"  \\\n     global.defineCFunction = function(funcName, paramsStr) {   \\\n         _OC_defineCFunction(funcName, paramsStr);   \\\n         global[funcName] = function() {    \\\n             var args = Array.prototype.slice.call(arguments);   \\\n             return _OC_callCFunc.apply(global, [funcName, args]);   \\\n         }  \\\n     }  \\\n     \"];\n    \n    context[@\"_OC_defineCFunction\"] = ^void(NSString *funcName, NSString *types) {\n        [self defineCFunction:funcName types:types];\n    };\n    \n    context[@\"_OC_callCFunc\"] = ^id(NSString *funcName, JSValue *args) {\n        id ret = [self callCFunction:funcName arguments:[self formatJSToOC:args]];\n        return [self formatOCToJS:ret];\n    };\n}\n\n+ (void)defineCFunction:(NSString *)funcName types:(NSString *)types\n{\n    NSMutableString *encodeStr = [[NSMutableString alloc] init];\n    NSArray *typeArr = [types componentsSeparatedByString:@\",\"];\n    for (NSInteger i = 0; i < typeArr.count; i++) {\n        NSString *typeStr = trim([typeArr objectAtIndex:i]);\n        NSString *encode = [JPMethodSignature typeEncodeWithTypeName:typeStr];\n        if (!encode) {\n            if ([typeStr hasPrefix:@\"{\"] && [typeStr hasSuffix:@\"}\"]) {\n                encode = typeStr;\n            } else {\n                NSString *argClassName = trim([typeStr stringByReplacingOccurrencesOfString:@\"*\" withString:@\"\"]);\n                if (NSClassFromString(argClassName) != NULL) {\n                    encode = @\"@\";\n                } else {\n                    NSCAssert(NO, @\"unreconized type %@\", typeStr);\n                    return;\n                }\n            }\n        }\n        [encodeStr appendString:encode];\n    }\n    [_funcDefines setObject:encodeStr forKey:funcName];\n}\n\n+ (id)objectWithCValue:(void *)src forType:(const char *)typeString\n{\n    switch (typeString[0]) {\n    #define JP_FFI_RETURN_CASE(_typeString, _type, _selector)\\\n        case _typeString:{\\\n            _type v = *(_type *)src;\\\n            return [NSNumber _selector:v];\\\n        }\n        JP_FFI_RETURN_CASE('c', char, numberWithChar)\n        JP_FFI_RETURN_CASE('C', unsigned char, numberWithUnsignedChar)\n        JP_FFI_RETURN_CASE('s', short, numberWithShort)\n        JP_FFI_RETURN_CASE('S', unsigned short, numberWithUnsignedShort)\n        JP_FFI_RETURN_CASE('i', int, numberWithInt)\n        JP_FFI_RETURN_CASE('I', unsigned int, numberWithUnsignedInt)\n        JP_FFI_RETURN_CASE('l', long, numberWithLong)\n        JP_FFI_RETURN_CASE('L', unsigned long, numberWithUnsignedLong)\n        JP_FFI_RETURN_CASE('q', long long, numberWithLongLong)\n        JP_FFI_RETURN_CASE('Q', unsigned long long, numberWithUnsignedLongLong)\n        JP_FFI_RETURN_CASE('f', float, numberWithFloat)\n        JP_FFI_RETURN_CASE('F', CGFloat, numberWithCGFloat)\n        JP_FFI_RETURN_CASE('d', double, numberWithDouble)\n        JP_FFI_RETURN_CASE('B', BOOL, numberWithBool)\n        case '^': {\n            JPBoxing *box = [[JPBoxing alloc] init];\n            box.pointer = (*(void**)src);\n            return box;\n        }\n        case '@':\n        case '#': {\n            return (__bridge id)(*(void**)src);\n        }\n        case '{': {\n            NSString *structName = [NSString stringWithCString:typeString encoding:NSASCIIStringEncoding];\n            NSUInteger end = [structName rangeOfString:@\"}\"].location;\n            if (end != NSNotFound) {\n                structName = [structName substringWithRange:NSMakeRange(1, end - 1)];\n                NSDictionary *structDefine = [JPExtension registeredStruct][structName];\n                id dict = [JPExtension getDictOfStruct:src structDefine:structDefine];\n                id ret = [JSValue valueWithObject:dict inContext:[JPEngine context]];\n                return ret;\n            }\n        }\n        default:\n            return nil;\n    }\n}\n\n+ (void)convertObject:(id)object toCValue:(void *)dist forType:(const char *)typeString\n{\n#define JP_CALL_ARG_CASE(_typeString, _type, _selector)\\\n    case _typeString:{\\\n        *(_type *)dist = [(NSNumber *)object _selector];\\\n        break;\\\n    }\n    switch (typeString[0]) {\n        JP_CALL_ARG_CASE('c', char, charValue)\n        JP_CALL_ARG_CASE('C', unsigned char, unsignedCharValue)\n        JP_CALL_ARG_CASE('s', short, shortValue)\n        JP_CALL_ARG_CASE('S', unsigned short, unsignedShortValue)\n        JP_CALL_ARG_CASE('i', int, intValue)\n        JP_CALL_ARG_CASE('I', unsigned int, unsignedIntValue)\n        JP_CALL_ARG_CASE('l', long, longValue)\n        JP_CALL_ARG_CASE('L', unsigned long, unsignedLongValue)\n        JP_CALL_ARG_CASE('q', long long, longLongValue)\n        JP_CALL_ARG_CASE('Q', unsigned long long, unsignedLongLongValue)\n        JP_CALL_ARG_CASE('f', float, floatValue)\n        JP_CALL_ARG_CASE('F', CGFloat, CGFloatValue)\n        JP_CALL_ARG_CASE('d', double, doubleValue)\n        JP_CALL_ARG_CASE('B', BOOL, boolValue)\n        case '^': {\n            void *ptr = [((JPBoxing *)object) unboxPointer];\n            *(void **)dist = ptr;\n            break;\n        }\n        case '#':\n        case '@': {\n            id ptr = object;\n            *(void **)dist = (__bridge void *)(ptr);\n            break;\n        }\n        case '{': {\n            NSString *structName = [NSString stringWithCString:typeString encoding:NSASCIIStringEncoding];\n            NSUInteger end = [structName rangeOfString:@\"}\"].location;\n            if (end != NSNotFound) {\n                structName = [structName substringWithRange:NSMakeRange(1, end - 1)];\n                NSDictionary *structDefine = [JPExtension registeredStruct][structName];\n                [JPExtension getStructDataWidthDict:dist dict:object structDefine:structDefine];\n                break;\n            }\n        }\n        default:\n            break;\n    }\n}\n\n+ (id)callCFunction:(NSString *)funcName arguments:(NSArray *)arguments\n{\n    void* functionPtr = dlsym(RTLD_DEFAULT, [funcName UTF8String]);\n    if (!functionPtr) {\n        return nil;\n    }\n    \n    JPMethodSignature *funcSignature = [[JPMethodSignature alloc] initWithObjCTypes:[_funcDefines objectForKey:funcName]];\n    \n    NSUInteger argCount = funcSignature.argumentTypes.count;\n    if (argCount != [arguments count]){\n        return nil;\n    }\n    \n    ffi_type **ffiArgTypes = alloca(sizeof(ffi_type *) *argCount);\n    void **ffiArgs = alloca(sizeof(void *) *argCount);\n    for (int i = 0; i < argCount; i ++) {\n        const char *argumentType = [funcSignature.argumentTypes[i] UTF8String];\n        ffi_type *ffiType = [JPMethodSignature ffiTypeWithEncodingChar:argumentType];\n        ffiArgTypes[i] = ffiType;\n        void *ffiArgPtr = alloca(ffiType->size);\n        [self convertObject:arguments[i] toCValue:ffiArgPtr forType:argumentType];\n        ffiArgs[i] = ffiArgPtr;\n    }\n    \n    ffi_cif cif;\n    id ret = nil;\n    const char *returnTypeChar = [funcSignature.returnType UTF8String];\n    ffi_type *returnFfiType = [JPMethodSignature ffiTypeWithEncodingChar:returnTypeChar];\n    ffi_status ffiPrepStatus = ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, (unsigned int)0, (unsigned int)argCount, returnFfiType, ffiArgTypes);\n    \n    if (ffiPrepStatus == FFI_OK) {\n        void *returnPtr = NULL;\n        if (returnFfiType->size) {\n            returnPtr = alloca(returnFfiType->size);\n        }\n        ffi_call(&cif, functionPtr, returnPtr, ffiArgs);\n\n        if (returnFfiType->size) {\n            ret = [self objectWithCValue:returnPtr forType:returnTypeChar];\n        }\n    }\n    \n    return ret;\n}\n\nstatic NSString *trim(NSString *string)\n{\n    return [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];\n}\n@end\n"
  },
  {
    "path": "Extensions/JPCFunction/JPMemory.h",
    "content": "//\n//  JPMemory.h\n//  JSPatchDemo\n//\n//  Created by Albert438 on 15/7/6.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import \"JPEngine.h\"\n\n@interface JPMemory : JPExtension\n\n@end\n"
  },
  {
    "path": "Extensions/JPCFunction/JPMemory.m",
    "content": "//\n//  JPMemory.m\n//  JSPatchDemo\n//\n//  Created by Albert438 on 15/7/6.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import \"JPMemory.h\"\n\n@implementation JPMemory\n\n+ (void)main:(JSContext *)context\n{\n    context[@\"memset\"] = ^void(JSValue *jsVal, int ch,size_t n) {\n        memset([self formatPointerJSToOC:jsVal], ch, n);\n    };\n    \n    context[@\"memmove\"] = ^id(JSValue *des, JSValue *src, size_t n) {\n        void *ret = memmove([self formatPointerJSToOC:des], [self formatPointerJSToOC:src], n);\n        return [self formatPointerOCToJS:ret];\n    };\n    \n    context[@\"memcpy\"] = ^id(JSValue *des, JSValue *src, size_t n) {\n        void *ret = memcpy([self formatPointerJSToOC:des], [self formatPointerJSToOC:src], n);\n        return [self formatPointerOCToJS:ret];\n    };\n    \n    context[@\"malloc\"] = ^id(size_t size) {\n        void *m = malloc(size);\n        return [self formatPointerOCToJS:m];\n    };\n    \n    context[@\"free\"] = ^void(JSValue *jsVal) {\n        void *m = [self formatPointerJSToOC:jsVal];\n        free(m);\n    };\n    \n    context[@\"pval\"] = ^id(JSValue *jsVal) {\n        void *m = [self formatPointerJSToOC:jsVal];\n        id obj = *((__unsafe_unretained id *)m);\n        return [self formatOCToJS:obj];\n    };\n    \n    context[@\"getPointer\"] = ^id(JSValue *jsVal) {\n        void **p = malloc(sizeof(void *));\n        void *pointer = [self formatPointerJSToOC:jsVal];\n        if (pointer != NULL) {\n            *p = pointer;\n        } else {\n            id obj = [self formatJSToOC:jsVal];\n            *p = (__bridge void*)obj;\n        }\n        return [self formatPointerOCToJS:p];\n    };\n    \n    context[@\"pvalBool\"] = ^id(JSValue *jsVal) {\n        void *m = [self formatPointerJSToOC:jsVal];\n        BOOL b = *((BOOL *)m);\n        return [self formatOCToJS:[NSNumber numberWithBool:b]];\n    };\n    \n    __weak JSContext *weakCtx = context;\n    context[@\"sizeof\"] = ^size_t(JSValue *jsVal) {\n        NSString *typeName = [jsVal toString];\n        \n        if ([typeName isEqualToString:@\"id\"]) return sizeof(id);\n        if ([typeName isEqualToString:@\"CGRect\"]) return sizeof(CGRect);\n        if ([typeName isEqualToString:@\"CGPoint\"]) return sizeof(CGPoint);\n        if ([typeName isEqualToString:@\"CGSize\"]) return sizeof(CGSize);\n        if ([typeName isEqualToString:@\"NSRange\"]) return sizeof(NSRange);\n        \n        @synchronized (weakCtx) {\n            NSDictionary *structDefine = [JPExtension registeredStruct][typeName];\n            if (structDefine) {\n                return [self sizeOfStructTypes:structDefine[@\"types\"]];\n            }\n        }\n        return 0;\n    };\n    \n    context[@\"__bridge_id\"] = ^id(JSValue *jsVal) {\n        void *p = [self formatPointerJSToOC:jsVal];\n        id obj = (__bridge id)p;\n        return [self formatOCToJS:obj];\n    };\n    \n    context[@\"CFRelease\"] = ^void(JSValue *jsVal) {\n        CFRelease([self formatPointerJSToOC:jsVal]);\n    };\n    \n    context[@\"CFRetain\"] = ^void(JSValue *jsVal) {\n        CFRetain([self formatPointerJSToOC:jsVal]);\n    };\n    \n    context[@\"assignPointer\"] = ^void(JSValue *jsVal, JSValue *value) {\n        void *m = [self formatPointerJSToOC:jsVal];\n        id obj = [self formatJSToOC:value];\n        *((__unsafe_unretained id *)m) = obj;\n    };\n    \n    context[@\"assignScalarTypePointer\"] = ^void(JSValue *jsVal, JSValue *value, NSString *type) {\n        void *pointer = [self formatPointerJSToOC:jsVal];\n        char *typeChar = (char*)[type UTF8String];\n        \n        switch (typeChar[0]) {\n            #define JP_ASSIGN_SCALAR_CASE(_typeChar, _type, _method) \\\n            case _typeChar: {   \\\n                NSNumber *num = [value toNumber]; \\\n                (*(_type *)pointer) = [num _method]; \\\n                break;  \\\n            }\n                \n            JP_ASSIGN_SCALAR_CASE('s', short, shortValue)\n            JP_ASSIGN_SCALAR_CASE('S', unsigned short, unsignedShortValue)\n            JP_ASSIGN_SCALAR_CASE('i', int, intValue)\n            JP_ASSIGN_SCALAR_CASE('I', unsigned int, unsignedIntValue)\n            JP_ASSIGN_SCALAR_CASE('l', long, longValue)\n            JP_ASSIGN_SCALAR_CASE('L', unsigned long, unsignedLongValue)\n            JP_ASSIGN_SCALAR_CASE('q', long long, longLongValue)\n            JP_ASSIGN_SCALAR_CASE('Q', unsigned long long, unsignedLongLongValue)\n            JP_ASSIGN_SCALAR_CASE('f', float, floatValue)\n            JP_ASSIGN_SCALAR_CASE('d', double, doubleValue)\n            JP_ASSIGN_SCALAR_CASE('B', BOOL, boolValue)\n            case 'c': \n            case 'C': {\n                NSString *str = [value toString];\n                (*(char *)pointer) = *[str cStringUsingEncoding:NSUTF8StringEncoding];\n                break;\n            }\n            default: {\n                break;\n            }\n        }\n    };\n    \n    context[@\"autoreleasepool\"] = ^void(JSValue *cb) {\n        @autoreleasepool {\n            [cb callWithArguments:nil];\n        }\n    };\n}\n\n\n\n@end\n"
  },
  {
    "path": "Extensions/JPCFunction/JPStructPointer.h",
    "content": "//\n//  JPStructPointer.h\n//  JSPatchDemo\n//\n//  Created by bang on 15/8/13.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import \"JPEngine.h\"\n\n@interface JPStructPointer : JPExtension\n\n@end\n"
  },
  {
    "path": "Extensions/JPCFunction/JPStructPointer.m",
    "content": "//\n//  JPStructPointer.m\n//  JSPatchDemo\n//\n//  Created by bang on 15/8/13.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import \"JPStructPointer.h\"\n\n@implementation JPStructPointer\n+ (void)main:(JSContext *)context\n{\n    __weak JSContext *weakCtx = context;\n    context[@\"newStruct\"] = ^id(NSString *structName, JSValue *structDict) {\n        #define JP_NEW_STRUCT(_type, _method) \\\n            if ([structName isEqualToString:@#_type]) {   \\\n                void *ret = malloc(sizeof(_type)); \\\n                _type rect = [structDict _method];  \\\n                ret = memcpy(ret, &rect, sizeof(_type));   \\\n                return [self formatPointerOCToJS:ret];  \\\n            }\n        JP_NEW_STRUCT(CGRect, toRect)\n        JP_NEW_STRUCT(CGPoint, toPoint)\n        JP_NEW_STRUCT(CGSize, toSize)\n        JP_NEW_STRUCT(NSRange, toRange)\n        \n        @synchronized (weakCtx) {\n            NSDictionary *structDefine = [JPExtension registeredStruct][structName];\n            if (structDefine) {\n                int size = [self sizeOfStructTypes:structDefine[@\"types\"]];\n                void *ret = malloc(size);\n                memset(ret, 0, size);\n                [self getStructDataWidthDict:ret dict:[structDict toObject] structDefine:structDefine];\n                return [self formatPointerOCToJS:ret];\n            }\n        }\n        return nil;\n    };\n    \n    context[@\"pvalStruct\"] = ^id(NSString *structName, JSValue *structPointer) {\n        if ([structName isEqualToString:@\"CGRect\"]) {\n            CGRect *rect = [self formatPointerJSToOC:structPointer];\n            return @{@\"x\": @(rect->origin.x), @\"y\": @(rect->origin.y), @\"width\": @(rect->size.width), @\"height\": @(rect->size.height)};\n        }\n        if ([structName isEqualToString:@\"CGPoint\"]) {\n            CGPoint *point = [self formatPointerJSToOC:structPointer];\n            return @{@\"x\": @(point->x), @\"y\": @(point->y)};\n        }\n        if ([structName isEqualToString:@\"CGSize\"]) {\n            CGSize *size = [self formatPointerJSToOC:structPointer];\n            return @{@\"width\": @(size->width), @\"height\": @(size->height)};\n        }\n        if ([structName isEqualToString:@\"NSRange\"]) {\n            NSRange *range = [self formatPointerJSToOC:structPointer];\n            return @{@\"location\": @(range->location), @\"length\": @(range->length)};\n        }\n        @synchronized (weakCtx) {\n            \n            JSContext *context = [JPEngine context];\n            @synchronized (context) {\n                NSDictionary *structDefine = [JPExtension registeredStruct][structName];\n                if (structDefine) {\n                    return [self getDictOfStruct:[self formatPointerJSToOC:structPointer] structDefine:structDefine];\n                }\n            }\n        }\n        return nil;\n    };\n}\n@end\n"
  },
  {
    "path": "Extensions/JPCFunctionBinder/CoreGraphics/JPCGBitmapContext.h",
    "content": "//\n//  JPCGBitmapContext.h\n//  JSPatchDemo\n//\n//  Created by Albert438 on 15/7/3.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import \"JPEngine.h\"\n\n@interface JPCGBitmapContext : JPExtension\n\n@end\n"
  },
  {
    "path": "Extensions/JPCFunctionBinder/CoreGraphics/JPCGBitmapContext.m",
    "content": "//\n//  JPCGBitmapContext.m\n//  JSPatchDemo\n//\n//  Created by Albert438 on 15/7/3.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import \"JPCGBitmapContext.h\"\n#import <CoreGraphics/CoreGraphics.h>\n\n@implementation JPCGBitmapContext\n\n+ (void)main:(JSContext *)context\n{\n    context[@\"CGBitmapContextCreate\"]         = ^id(JSValue *data, size_t width,\n                                                    size_t height, size_t bitsPerComponent, size_t bytesPerRow,\n                                                    JSValue *space, uint32_t bitmapInfo) {\n        CGContextRef bitmapContext = CGBitmapContextCreate([self formatPointerJSToOC:data], width, height, bitsPerComponent, bytesPerRow, [self formatPointerJSToOC:space], bitmapInfo);\n        return [self formatRetainedCFTypeOCToJS:bitmapContext];\n    };\n    \n    context[@\"CGBitmapContextCreateImage\"]    = ^id(JSValue *c) {\n        CGImageRef image = CGBitmapContextCreateImage([self formatPointerJSToOC:c]);\n        return [self formatRetainedCFTypeOCToJS:image];\n    };\n    \n    context[@\"CGBitmapContextGetBytesPerRow\"] = ^size_t(JSValue *c) {\n        return CGBitmapContextGetBytesPerRow([self formatPointerJSToOC:c]);\n    };\n    \n    context[@\"CGBitmapContextGetData\"]        = ^id(JSValue *c) {\n        return [self formatPointerJSToOC:CGBitmapContextGetData([self formatPointerJSToOC:c])];\n    };\n    \n    context[@\"CGBitmapContextGetHeight\"]      = ^size_t(JSValue *c) {\n        return CGBitmapContextGetHeight([self formatPointerJSToOC:c]);\n    };\n    \n    context[@\"CGBitmapContextGetWidth\"]       = ^size_t(JSValue *c) {\n        return CGBitmapContextGetWidth([self formatPointerJSToOC:c]);\n    };\n    \n    context[@\"CGImageRelease\"]                = ^void(JSValue *image) {\n        CGImageRelease([self formatPointerJSToOC:image]);\n    };\n}\n\n@end\n"
  },
  {
    "path": "Extensions/JPCFunctionBinder/CoreGraphics/JPCGColor.h",
    "content": "//\n//  JPCGColor.h\n//  JSPatchDemo\n//\n//  Created by Albert438 on 15/7/3.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import \"JPEngine.h\"\n\n@interface JPCGColor : JPExtension\n\n@end\n"
  },
  {
    "path": "Extensions/JPCFunctionBinder/CoreGraphics/JPCGColor.m",
    "content": "//\n//  JPCGColor.m\n//  JSPatchDemo\n//\n//  Created by Albert438 on 15/7/3.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import \"JPCGColor.h\"\n#import <CoreGraphics/CoreGraphics.h>\n\n@implementation JPCGColor\n\n+ (void)main:(JSContext *)context\n{\n    context[@\"CGColorCreate\"]                = ^id(JSValue *space,\n                                    NSArray *componentsArray) {\n        CGFloat *components = malloc(componentsArray.count * sizeof(CGFloat));\n        for (int i = 0; i < componentsArray.count; i++) {\n            components[i] = [componentsArray[i] doubleValue];\n        }\n        CGColorRef color =  CGColorCreate([self formatPointerJSToOC:space], components);\n        free(components);\n        return [self formatRetainedCFTypeOCToJS:color];\n    };\n    \n    context[@\"CGColorEqualToColor\"]          = ^BOOL(JSValue *color1, JSValue *color2) {\n        return CGColorEqualToColor([self formatPointerJSToOC:color1], [self formatPointerJSToOC:color2]);\n    };\n    \n    context[@\"CGColorGetColorSpace\"]         = ^id(JSValue *color) {\n        CGColorSpaceRef space = CGColorGetColorSpace([self formatPointerJSToOC:color]);\n        return [self formatPointerOCToJS:space];\n    };\n    \n    context[@\"CGColorGetComponents\"]         = ^NSArray *(JSValue *color) {\n        size_t numberOfComponents = CGColorGetNumberOfComponents([self formatPointerJSToOC:color]);\n        const CGFloat *componets = CGColorGetComponents([self formatPointerJSToOC:color]);\n        NSMutableArray *componentsArray = [NSMutableArray array];\n        for (int i = 0 ; i < numberOfComponents ; i++) {\n            [componentsArray addObject:[NSNumber numberWithDouble:componets[i]]];\n        }\n        return componentsArray;\n    };\n    \n    context[@\"CGColorGetNumberOfComponents\"] = ^size_t(JSValue *color) {\n        return CGColorGetNumberOfComponents([self formatPointerJSToOC:color]);\n    };\n    \n    context[@\"CGColorRelease\"]               = ^void(JSValue *color){\n        CGColorRelease([self formatPointerJSToOC:color]);\n    };\n    \n    context[@\"CGColorSpaceCreateDeviceGray\"] = ^id() {\n        return [self formatRetainedCFTypeOCToJS:CGColorSpaceCreateDeviceGray()];\n    };\n    \n    context[@\"CGColorSpaceCreateDeviceRGB\"]  = ^id() {\n        return [self formatRetainedCFTypeOCToJS:CGColorSpaceCreateDeviceRGB()];\n    };\n    \n    context[@\"CGColorSpaceCreateDeviceCMYK\"] = ^id() {\n        return [self formatRetainedCFTypeOCToJS:CGColorSpaceCreateDeviceCMYK()];\n    };\n    \n    context[@\"CGColorSpaceCreatePattern\"]    = ^id(JSValue *baseSpace) {\n        return [self formatRetainedCFTypeOCToJS:CGColorSpaceCreatePattern([self formatPointerJSToOC:baseSpace])];\n    };\n    \n    context[@\"CGColorSpaceGetModel\"]         = ^NSInteger(JSValue *space) {\n        NSInteger model = CGColorSpaceGetModel([self formatPointerJSToOC:space]);\n        return model;\n    };\n    \n    context[@\"CGColorSpaceRelease\"]          = ^void(JSValue *space) {\n        CGColorSpaceRelease([self formatPointerJSToOC:space]);\n    };\n}\n\n@end\n"
  },
  {
    "path": "Extensions/JPCFunctionBinder/CoreGraphics/JPCGContext.h",
    "content": "//\n//  JPCGContext.h\n//  \n//\n//  Created by Albert438 on 15/7/2.\n//  Copyright © 2015年 bang. All rights reserved.\n//\n\n#import \"JPEngine.h\"\n\n@interface JPCGContext : JPExtension\n\n@end\n"
  },
  {
    "path": "Extensions/JPCFunctionBinder/CoreGraphics/JPCGContext.m",
    "content": "//\n//  JPCGContext.m\n//\n//\n//  Created by Albert438 on 15/7/2.\n//  Copyright © 2015年 bang. All rights reserved.\n//\n\n#import \"JPCGContext.h\"\n#import \"JPCGTransform.h\"\n#import \"JPCGGeometry.h\"\n#import <UIKit/UIKit.h>\n\n@implementation JPCGContext\n\n+ (void)main:(JSContext *)context\n{\n    context[@\"CGContextSetLineCap\"]            = ^void(JSValue *c, int cap) {\n        CGContextSetLineCap([self formatPointerJSToOC:c], cap);\n    };\n    \n    context[@\"CGContextSetFillColorWithColor\"] = ^void(JSValue *c, JSValue *color) {\n        CGContextSetFillColorWithColor([self formatPointerJSToOC:c], [self formatPointerJSToOC:color]);\n    };\n    \n    context[@\"CGContextSetLineWidth\"]          = ^void(JSValue *c, CGFloat lineWidthValue) {\n        CGContextSetLineWidth([self formatPointerJSToOC:c], lineWidthValue);\n    };\n    \n    context[@\"CGContextBeginPath\"]             = ^void(JSValue *c) {\n        CGContextBeginPath([self formatPointerJSToOC:c]);\n    };\n    \n    context[@\"CGContextMoveToPoint\"]           = ^void(JSValue *c, CGFloat x, CGFloat y) {\n        CGContextMoveToPoint([self formatPointerJSToOC:c], x, y);\n    };\n    \n    context[@\"CGContextAddLineToPoint\"]        = ^void(JSValue *c, CGFloat x, CGFloat y) {\n        CGContextAddLineToPoint([self formatPointerJSToOC:c], x, y);\n    };\n    \n    context[@\"CGContextStrokePath\"]            = ^void(JSValue *c) {\n        CGContextStrokePath([self formatPointerJSToOC:c]);\n    };\n    \n    context[@\"CGContextSetRGBStrokeColor\"]     = ^void(JSValue *c,CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha){\n        CGContextSetRGBStrokeColor([self formatPointerJSToOC:c], red, green, blue, alpha);\n    };\n    \n    context[@\"CGContextSetRGBFillColor\"]       = ^void(JSValue *c,CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha){\n        CGContextSetRGBFillColor([self formatPointerJSToOC:c], red, green, blue, alpha);\n    };\n    \n    context[@\"CGContextClosePath\"]             = ^void(JSValue *c) {\n        CGContextClosePath([self formatPointerJSToOC:c]);\n    };\n    \n    context[@\"CGContextStrokeRect\"]            = ^void(JSValue *c, NSDictionary *cgRectDict) {\n        CGRect rect;\n        [JPCGGeometry rectStruct:&rect ofDict:cgRectDict];\n        CGContextStrokeRect([self formatPointerJSToOC:c], rect);\n    };\n    \n    context[@\"CGContextAddArc\"]                = ^void(JSValue *c, CGFloat x, CGFloat y,\n                                                       CGFloat radius, CGFloat startAngle, CGFloat endAngle, int clockwise) {\n        CGContextAddArc([self formatPointerJSToOC:c], x, y, radius, startAngle, endAngle, clockwise);\n    };\n    \n    context[@\"CGContextAddArcToPoint\"]         = ^void(JSValue *c, CGFloat x1, CGFloat y1, CGFloat x2, CGFloat y2, CGFloat radius) {\n        CGContextAddArcToPoint([self formatPointerJSToOC:c], x1, y1, x2, y2, radius);\n    };\n    \n    context[@\"CGContextAddRect\"]               = ^void(JSValue *c, NSDictionary *cgRectDict) {\n        CGRect rect;\n        [JPCGGeometry rectStruct:&rect ofDict:cgRectDict];\n        CGContextAddRect([self formatPointerJSToOC:c], rect);\n    };\n    \n    context[@\"CGContextAddPath\"]               = ^void(JSValue *c, JSValue *path) {\n        CGContextAddPath([self formatPointerJSToOC:c], [self formatPointerJSToOC:path]);\n    };\n    \n    context[@\"CGContextAddLines\"]              = ^void(JSValue *c, NSArray *points, NSUInteger count){\n        CGPoint *pointsArray = malloc(count * sizeof(CGPoint));\n        for (int i = 0; i < count; i++) {\n            CGPoint point;\n            [JPCGGeometry pointStruct:&point ofDict:points[i]];\n            pointsArray[i]   = point;\n        }\n        CGContextAddLines([self formatPointerJSToOC:c], pointsArray, count);\n        free(pointsArray);\n    };\n    \n    context[@\"CGContextAddEllipseInRect\"]      = ^void(JSValue *c, NSDictionary *rectDict){\n        CGRect rect;\n        [JPCGGeometry rectStruct:&rect ofDict:rectDict];\n        CGContextAddEllipseInRect([self formatPointerJSToOC:c], rect);\n    };\n    \n    context[@\"CGContextDrawImage\"]             = ^void(JSValue *c, NSDictionary *rectDict, JSValue *image) {\n        CGRect rect;\n        [JPCGGeometry rectStruct:&rect ofDict:rectDict];\n        CGContextDrawImage([self formatPointerJSToOC:c], rect, [self formatPointerJSToOC:image]);\n    };\n    \n    context[@\"CGContextDrawPath\"]              = ^void(JSValue *c, int mode) {\n        CGContextDrawPath([self formatPointerJSToOC:c], mode);\n    };\n    \n    context[@\"CGContextRestoreGState\"]         = ^void(JSValue *c) {\n        CGContextRestoreGState([self formatPointerJSToOC:c]);\n    };\n    \n    context[@\"CGContextSaveGState\"]            = ^void(JSValue *c) {\n        CGContextSaveGState([self formatPointerJSToOC:c]);\n    };\n    \n    context[@\"CGContextRetain\"]                = ^id(JSValue *c) {\n        CGContextRef retainContext = CGContextRetain([self formatPointerJSToOC:c]);\n        return [self formatPointerOCToJS:retainContext];\n    };\n    \n    context[@\"CGContextRelease\"]               = ^void(JSValue *c) {\n        CGContextRelease([self formatPointerJSToOC:c]);\n    };\n    \n    context[@\"CGContextTranslateCTM\"]          = ^void(JSValue *c, CGFloat tx, CGFloat ty) {\n        CGContextTranslateCTM([self formatPointerJSToOC:c], tx, ty);\n    };\n    \n    context[@\"CGContextScaleCTM\"]              = ^void(JSValue *c, CGFloat sx, CGFloat sy) {\n        CGContextScaleCTM([self formatPointerJSToOC:c], sx, sy);\n    };\n    \n    context[@\"CGContextFillPath\"]              = ^void(JSValue *c) {\n        CGContextFillPath([self formatPointerJSToOC:c]);\n    };\n    \n    context[@\"CGContextFillRect\"]              = ^void(JSValue *c, NSDictionary *cgRectDict) {\n        CGRect rect;\n        [JPCGGeometry rectStruct:&rect ofDict:cgRectDict];\n        CGContextFillRect([self formatPointerJSToOC:c], rect);\n    };\n    \n    context[@\"CGContextSetShadowWithColor\"]    = ^void(JSValue *c, CGSize offset, CGFloat blur, JSValue *color) {\n        CGContextSetShadowWithColor([self formatPointerJSToOC:c], offset, blur, [self formatPointerJSToOC:color]);\n    };\n    \n    context[@\"CGContextClip\"]                  = ^void(JSValue *c) {\n        CGContextClip([self formatPointerJSToOC:c]);\n    };\n    \n    context[@\"CGContextConcatCTM\"]             = ^void(JSValue *c, NSDictionary *transfromDict) {\n        CGAffineTransform transform;\n        [JPCGTransform transStruct:&transform ofDict:transfromDict];\n        CGContextConcatCTM([self formatPointerJSToOC:c], transform);\n    };\n    \n    context[@\"CGContextGetClipBoundingBox\"]    = ^void(JSValue *c) {\n        CGContextGetClipBoundingBox([self formatPointerJSToOC:c]);\n    };\n    \n    context[@\"CGContextClearRect\"]             = ^void(JSValue *c, NSDictionary *rectDict) {\n        CGRect rect;\n        [JPCGGeometry rectStruct:&rect ofDict:rectDict];\n        CGContextClearRect([self formatPointerJSToOC:c], rect);\n    };\n    \n    context[@\"CGContextFillEllipseInRect\"]     = ^void(JSValue *c, NSDictionary *rectDict) {\n        CGRect rect;\n        [JPCGGeometry rectStruct:&rect ofDict:rectDict];\n        CGContextFillEllipseInRect([self formatPointerJSToOC:c], rect);\n    };\n    \n    context[@\"CGContextDrawLinearGradient\"]    = ^void(JSValue *c,JSValue *gradient, NSDictionary *startPointDict, NSDictionary *endPointDict,int options) {\n        CGPoint startPoint;\n        CGPoint endPoint;\n        [JPCGGeometry pointStruct:&startPoint ofDict:startPointDict];\n        [JPCGGeometry pointStruct:&endPoint ofDict:endPointDict];\n        CGContextDrawLinearGradient([self formatPointerJSToOC:c], [self formatPointerJSToOC:gradient], startPoint, endPoint, options);\n    };\n    \n    context[@\"CGContextSetAlpha\"]              = ^void(JSValue *c, CGFloat a) {\n        CGContextSetAlpha([self formatPointerJSToOC:c], a);\n    };\n    \n    context[@\"CGContextClipToRect\"]            = ^void(JSValue *c, NSDictionary *rectDict) {\n        CGRect rect;\n        [JPCGGeometry rectStruct:&rect ofDict:rectDict];\n        CGContextClipToRect([self formatPointerJSToOC:c], rect);\n    };\n    \n    context[@\"CGContextSetInterpolationQuality\"] = ^void(JSValue *c, int quality) {\n        CGContextSetInterpolationQuality([self formatPointerJSToOC:c], quality);\n    };\n    \n    context[@\"CGContextClipToMask\"]              = ^void(JSValue *c, NSDictionary *rectDict, JSValue *mask) {\n        CGRect rect;\n        [JPCGGeometry rectStruct:&rect ofDict:rectDict];\n        CGContextClipToMask([self formatPointerJSToOC:c], rect, [self formatPointerJSToOC:mask]);\n    };\n    \n    context[@\"CGContextSetTextDrawingMode\"]      = ^void(JSValue *c, int mode) {\n        CGContextSetTextDrawingMode([self formatPointerJSToOC:c], mode);\n    };\n    \n    context[@\"CGContextGetCTM\"]                  = ^void(JSValue *c) {\n        CGContextGetCTM([self formatPointerJSToOC:c]);\n    };\n    \n    context[@\"CGContextStrokeEllipseInRect\"]     = ^void(JSValue *c, NSDictionary *rectDict) {\n        CGRect rect;\n        [JPCGGeometry rectStruct:&rect ofDict:rectDict];\n        CGContextStrokeEllipseInRect([self formatPointerJSToOC:c], rect);\n    };\n    \n    context[@\"CGContextSetLineDash\"]             = ^void(JSValue *c, CGFloat phase,\n                                                         NSArray *lengths, size_t count) {\n        CGFloat *lengthsArray = malloc(count * sizeof(CGFloat));\n        for (int i = 0 ; i < count; i++) {\n            lengthsArray[i] = [lengths[i] doubleValue];\n        }\n        CGContextSetLineDash([self formatPointerJSToOC:c], phase, lengthsArray, count);\n        free(lengthsArray);\n    };\n    \n    context[@\"CGContextRotateCTM\"]               = ^void(JSValue *c, CGFloat angle) {\n        CGContextRotateCTM([self formatPointerJSToOC:c], angle);\n    };\n    \n    context[@\"CGContextSetLineJoin\"]             = ^void(JSValue *c, int join) {\n        CGContextSetLineJoin([self formatPointerJSToOC:c], join);\n    };\n    \n    context[@\"CGContextSetGrayFillColor\"]        = ^void(JSValue *c, CGFloat gray,\n                                                         CGFloat alpha) {\n        CGContextSetGrayFillColor([self formatPointerJSToOC:c], gray, alpha);\n    };\n    \n    context[@\"CGContextBeginTransparencyLayer\"]  = ^void(JSValue *c,JSValue *auxiliaryInfo) {\n        CGContextBeginTransparencyLayer([self formatPointerJSToOC:c], [self formatPointerJSToOC:auxiliaryInfo]);\n    };\n    \n    context[@\"CGContextSetBlendMode\"]            = ^void(JSValue *context, int mode) {\n        CGContextSetBlendMode([self formatPointerJSToOC:context], mode);\n    };\n    \n    context[@\"CGContextEndTransparencyLayer\"]    = ^void(JSValue *c) {\n        CGContextEndTransparencyLayer([self formatPointerJSToOC:c]);\n    };\n    \n    context[@\"CGContextSetShadow\"]               = ^void(JSValue *c, NSDictionary *offsetDict,\n                                                         CGFloat blur) {\n        CGSize size;\n        [JPCGGeometry sizeStruct:&size ofDict:offsetDict];\n        CGContextSetShadow([self formatPointerJSToOC:c], size, blur);\n    };\n    \n    context[@\"CGContextSetTextMatrix\"]           = ^void(JSValue *c, NSDictionary *transformDict) {\n        CGAffineTransform transform;\n        [JPCGTransform transStruct:&transform ofDict:transformDict];\n        CGContextSetTextMatrix([self formatPointerJSToOC:c], transform);\n    };\n    \n    context[@\"CGContextSetTextPosition\"]         = ^(JSValue *c, CGFloat x, CGFloat y) {\n        CGContextSetTextPosition([self formatPointerJSToOC:c], x, y);\n    };\n    \n    context[@\"CGContextSetMiterLimit\"]           = ^(JSValue *c, CGFloat limit) {\n        CGContextSetMiterLimit([self formatPointerJSToOC:c], limit);\n    };\n    \n    context[@\"CGContextStrokeRect\"]              = ^(JSValue *c, NSDictionary *rectDict) {\n        CGRect rect;\n        [JPCGGeometry rectStruct:&rect ofDict:rectDict];\n        CGContextStrokeRect([self formatPointerJSToOC:c], rect);\n    };\n    \n    context[@\"CGContextSetFillColorSpace\"]       = ^(JSValue *c, JSValue *space) {\n        CGContextSetFillColorSpace([self formatPointerJSToOC:c], [self formatPointerJSToOC:space]);\n    };\n    \n    context[@\"CGContextSetFlatness\"]             = ^(JSValue *c, CGFloat flatness) {\n        CGContextSetFlatness([self formatPointerJSToOC:c], flatness);\n    };\n}\n\n@end\n"
  },
  {
    "path": "Extensions/JPCFunctionBinder/CoreGraphics/JPCGGeometry.h",
    "content": "//\n//  JPCGGeometryHelper.h\n//  JSPatchDemo\n//\n//  Created by Albert438 on 15/7/2.\n//  Copyright © 2015年 bang. All rights reserved.\n//\n\n#import \"JPEngine.h\"\n\n@interface JPCGGeometry : JPExtension\n\n+ (void)rectStruct:(CGRect *)rect ofDict:(NSDictionary *)dict;\n\n+ (void)pointStruct:(CGPoint *)point ofDict:(NSDictionary *)dict;\n\n+ (void)sizeStruct:(CGSize *)size ofDict:(NSDictionary *)dict;\n\n+ (void)vectorStruct:(CGVector *)vector ofDict:(NSDictionary *)dict;\n\n+ (NSDictionary *)rectDictOfStruct:(CGRect *)rect;\n\n+ (NSDictionary *)sizeDictOfStruct:(CGSize *)size;\n\n+ (NSDictionary *)pointDictOfStruct:(CGPoint *)point;\n\n+ (NSDictionary *)vectorDictOfStruct:(CGVector *)vector;\n@end\n"
  },
  {
    "path": "Extensions/JPCFunctionBinder/CoreGraphics/JPCGGeometry.m",
    "content": "//\n//  JPCGGeometryHelper.m\n//  JSPatchDemo\n//\n//  Created by Albert438  on 15/7/2.\n//  Copyright © 2015年 bang. All rights reserved.\n//\n\n#import \"JPCGGeometry.h\"\n#import <CoreGraphics/CGGeometry.h>\n\n@implementation JPCGGeometry\n\n+ (void)main:(JSContext *)context\n{\n    [JPEngine defineStruct:@{\n                             @\"name\": @\"CGVector\",\n                             @\"types\": @\"FF\",\n                             @\"keys\": @[@\"dx\", @\"dy\"]\n                             }];\n    \n    [JPEngine defineStruct:@{\n                             @\"name\": @\"CGAffineTransform\",\n                             @\"types\": @\"FFFFFF\",\n                             @\"keys\": @[@\"a\", @\"b\", @\"c\", @\"d\", @\"tx\", @\"ty\"]\n                             }];\n    \n    context[@\"CGRectContainsPoint\"]  = ^BOOL(NSDictionary *rectDict, NSDictionary *pointDict) {\n        CGRect rect;\n        CGPoint point;\n        [JPCGGeometry rectStruct:&rect ofDict:rectDict];\n        [JPCGGeometry pointStruct:&point ofDict:pointDict];\n        return CGRectContainsPoint(rect, point);\n    };\n\n    context[@\"CGRectEqualToRect\"]    = ^BOOL(NSDictionary *rectDict1, NSDictionary *rectDict2) {\n        CGRect rect1,rect2;\n        [JPCGGeometry rectStruct:&rect1 ofDict:rectDict1];\n        [JPCGGeometry rectStruct:&rect2 ofDict:rectDict2];\n        return CGRectEqualToRect(rect1, rect2);\n    };\n\n    context[@\"CGRectGetMaxX\"]        = ^CGFloat(NSDictionary *rectDict) {\n        CGRect rect;\n        [JPCGGeometry rectStruct:&rect ofDict:rectDict];\n        return CGRectGetMaxX(rect);\n    };\n\n    context[@\"CGRectGetMaxY\"]        = ^CGFloat(NSDictionary *rectDict) {\n        CGRect rect;\n        [JPCGGeometry rectStruct:&rect ofDict:rectDict];\n        return CGRectGetMaxY(rect);\n    };\n\n    context[@\"CGRectGetMidX\"]        = ^CGFloat(NSDictionary *rectDict) {\n        CGRect rect;\n        [JPCGGeometry rectStruct:&rect ofDict:rectDict];\n        return CGRectGetMidX(rect);\n    };\n\n    context[@\"CGRectGetMidY\"]        = ^CGFloat(NSDictionary *rectDict) {\n        CGRect rect;\n        [JPCGGeometry rectStruct:&rect ofDict:rectDict];\n        return CGRectGetMidY(rect);\n    };\n\n    context[@\"CGRectGetMinX\"]        = ^CGFloat(NSDictionary *rectDict) {\n        CGRect rect;\n        [JPCGGeometry rectStruct:&rect ofDict:rectDict];\n        return CGRectGetMinX(rect);\n    };\n\n    context[@\"CGRectGetMinY\"]        = ^CGFloat(NSDictionary *rectDict) {\n        CGRect rect;\n        [JPCGGeometry rectStruct:&rect ofDict:rectDict];\n        return CGRectGetMinY(rect);\n    };\n\n    context[@\"CGRectInset\"]          = ^CGRect(NSDictionary *rectDict, CGFloat dx, CGFloat dy) {\n        CGRect rect;\n        [JPCGGeometry rectStruct:&rect ofDict:rectDict];\n        CGRect rectInset = CGRectInset(rect, dx, dy);\n        return rectInset;\n    };\n\n    context[@\"CGRectIntegral\"]       = ^CGRect(NSDictionary *rectDict) {\n        CGRect rect;\n        [JPCGGeometry rectStruct:&rect ofDict:rectDict];\n        CGRect rectIntegral = CGRectIntegral(rect);\n        return rectIntegral;\n    };\n\n    context[@\"CGRectIntersection\"]   = ^CGRect(NSDictionary *rectDict1, NSDictionary *rectDict2) {\n        CGRect rect1,rect2;\n        [JPCGGeometry rectStruct:&rect1 ofDict:rectDict1];\n        [JPCGGeometry rectStruct:&rect2 ofDict:rectDict2];\n\n        CGRect rectIntersection = CGRectIntersection(rect1, rect2);\n        return rectIntersection;\n    };\n\n    context[@\"CGRectOffset\"]         = ^CGRect(NSDictionary *rectDict, CGFloat dx, CGFloat dy) {\n        CGRect rect;\n        [JPCGGeometry rectStruct:&rect ofDict:rectDict];\n        CGRect rectOffset = CGRectOffset(rect, dx, dy);\n        return rectOffset;\n    };\n\n    context[@\"CGRectIntersectsRect\"] = ^BOOL(NSDictionary *rectDict1, NSDictionary *rectDict2) {\n        CGRect rect1,rect2;\n        [JPCGGeometry rectStruct:&rect1 ofDict:rectDict1];\n        [JPCGGeometry rectStruct:&rect2 ofDict:rectDict2];\n        return CGRectIntersectsRect(rect1, rect2);\n    };\n}\n\n#if CGFLOAT_IS_DOUBLE\n#define CGFloatValue doubleValue\n#else\n#define CGFloatValue floatValue\n#endif\n\n+ (void)rectStruct:(CGRect *)rect ofDict:(NSDictionary *)dict\n{\n    CGPoint point;\n    CGSize size;\n    point.x      = [dict[@\"x\"] CGFloatValue];\n    point.y      = [dict[@\"y\"] CGFloatValue];\n    size.width   = [dict[@\"width\"] CGFloatValue];\n    size.height  = [dict[@\"height\"] CGFloatValue];\n    rect->origin = point;\n    rect->size   = size;\n    \n}\n\n+ (void)pointStruct:(CGPoint *)point ofDict:(NSDictionary *)dict\n{\n    point->x = [dict[@\"x\"] CGFloatValue];\n    point->y = [dict[@\"y\"] CGFloatValue];\n}\n\n+ (void)sizeStruct:(CGSize *)size ofDict:(NSDictionary *)dict\n{\n    size->width  = [dict[@\"width\"] CGFloatValue];\n    size->height = [dict[@\"height\"] CGFloatValue];\n}\n\n+ (void)vectorStruct:(CGVector *)vector ofDict:(NSDictionary *)dict\n{\n    vector->dx = [dict[@\"dx\"] CGFloatValue];\n    vector->dy = [dict[@\"dy\"] CGFloatValue];\n}\n\n#undef CGFloatValue\n\n+ (NSDictionary *)rectDictOfStruct:(CGRect *)rect\n{\n    return @{@\"x\": @(rect->origin.x), @\"y\": @(rect->origin.y), @\"width\": @(rect->size.width), @\"height\": @(rect->size.height)};\n}\n\n+ (NSDictionary *)sizeDictOfStruct:(CGSize *)size\n{\n    return @{@\"width\": @(size->width), @\"height\": @(size->height)};\n}\n\n+ (NSDictionary *)pointDictOfStruct:(CGPoint *)point\n{\n    return @{@\"x\": @(point->x), @\"y\": @(point->y)};\n}\n\n+ (NSDictionary *)vectorDictOfStruct:(CGVector *)vector\n{\n    return @{@\"dx\": @(vector->dx), @\"dy\": @(vector->dy)};\n}\n@end\n"
  },
  {
    "path": "Extensions/JPCFunctionBinder/CoreGraphics/JPCGImage.h",
    "content": "//\n//  JPCGImage.h\n//  JSPatchDemo\n//\n//  Created by Albert438 on 15/7/3.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import \"JPEngine.h\"\n\n@interface JPCGImage : JPExtension\n\n@end\n"
  },
  {
    "path": "Extensions/JPCFunctionBinder/CoreGraphics/JPCGImage.m",
    "content": "//\n//  JPCGImage.m\n//  JSPatchDemo\n//\n//  Created by Albert438 on 15/7/3.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import \"JPCGImage.h\"\n#import <CoreGraphics/CoreGraphics.h>\n#import \"JPCGGeometry.h\"\n\n@implementation JPCGImage\n\n+ (void)main:(JSContext *)context\n{\n    context[@\"CGImageCreate\"]                = ^id(size_t width, size_t height,\n                                                   size_t bitsPerComponent, size_t bitsPerPixel, size_t bytesPerRow,\n                                                   JSValue *space, int bitmapInfo, JSValue *provider,\n                                                   NSArray *decodeArray, bool shouldInterpolate,\n                                                   int intent) {\n        if (decodeArray == nil) {\n            CGImageRef  createdImage = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel,bytesPerRow, [self formatPointerJSToOC:space], bitmapInfo, [self formatPointerJSToOC:provider], NULL, shouldInterpolate, intent);\n            return [self formatRetainedCFTypeOCToJS:createdImage];\n        }else {\n            CGFloat *decode = malloc(decodeArray.count * sizeof(CGFloat));\n            for (int i = 0; i < decodeArray.count; i++) {\n                decode[i] = [decodeArray[i] doubleValue];\n            }\n            CGImageRef  createdImage = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel,bytesPerRow, [self formatPointerJSToOC:space], bitmapInfo, [self formatPointerJSToOC:provider], decode, shouldInterpolate, intent);\n            free(decode);\n            return [self formatRetainedCFTypeOCToJS:createdImage];\n        }\n    };\n    \n    context[@\"CGImageCreateWithImageInRect\"] = ^id(JSValue *image, NSDictionary *rectDict) {\n        CGRect rect;\n        [JPCGGeometry rectStruct:&rect ofDict:rectDict];\n        CGImageRef retImage = CGImageCreateWithImageInRect([self formatPointerJSToOC:image], rect);\n        return [self formatRetainedCFTypeOCToJS:retImage];\n    };\n    \n    context[@\"CGImageCreateWithMask\"]        = ^id(JSValue *image, JSValue *mask) {\n        CGImageRef createdImage = CGImageCreateWithMask([self formatPointerJSToOC:image], [self formatPointerJSToOC:mask]);\n        return [self formatRetainedCFTypeOCToJS:createdImage];\n    };\n    \n    context[@\"CGImageGetAlphaInfo\"]          = ^CGImageAlphaInfo(JSValue *image) {\n        return CGImageGetAlphaInfo([self formatPointerJSToOC:image]);\n    };\n    \n    context[@\"CGImageGetBitmapInfo\"]         = ^CGBitmapInfo(JSValue *image) {\n        CGBitmapInfo ret =  CGImageGetBitmapInfo([self formatPointerJSToOC:image]);\n        return ret;\n    };\n    \n    context[@\"CGImageGetBitsPerComponent\"]   = ^size_t(JSValue *image) {\n        return CGImageGetBitsPerComponent([self formatPointerJSToOC:image]);\n    };\n    \n    context[@\"CGImageGetColorSpace\"]         = ^id(JSValue *image) {\n        CGColorSpaceRef space = CGImageGetColorSpace([self formatPointerJSToOC:image]);\n        return [self formatPointerOCToJS:space];\n    };\n    \n    context[@\"CGImageGetDataProvider\"]       = ^id(JSValue *image) {\n        CGDataProviderRef provider = CGImageGetDataProvider([self formatPointerJSToOC:image]);\n        return [self formatPointerOCToJS:provider];\n    };\n    \n    context[@\"CGImageGetHeight\"]             = ^size_t(JSValue *image) {\n        return CGImageGetHeight([self formatPointerJSToOC:image]);\n    };\n    \n    context[@\"CGImageGetWidth\"]              = ^size_t(JSValue *image) {\n        return CGImageGetWidth([self formatPointerJSToOC:image]);\n    };\n    \n    context[@\"CGImageRelease\"]               = ^void(JSValue *image) {\n        CGImageRelease([self formatPointerJSToOC:image]);\n    };\n}\n\n\n@end\n"
  },
  {
    "path": "Extensions/JPCFunctionBinder/CoreGraphics/JPCGPath.h",
    "content": "//\n//  JPCGPath.h\n//  JSPatchDemo\n//\n//  Created by Albert438 on 15/7/6.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import \"JPEngine.h\"\n\n@interface JPCGPath : JPExtension\n\n@end\n"
  },
  {
    "path": "Extensions/JPCFunctionBinder/CoreGraphics/JPCGPath.m",
    "content": "//\n//  JPCGPath.m\n//  JSPatchDemo\n//\n//  Created by Albert438 on 15/7/6.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import \"JPCGPath.h\"\n#import \"JPCGTransform.h\"\n#import \"JPCGGeometry.h\"\n#import <CoreGraphics/CoreGraphics.h>\n\n@implementation JPCGPath\n\n+ (void)main:(JSContext *)context\n{\n    context[@\"CGPathAddArc\"]                  = ^void(JSValue *path, NSDictionary *m,\n                                       CGFloat x, CGFloat y, CGFloat radius, CGFloat startAngle, CGFloat endAngle,\n                                       bool clockwise) {\n        CGAffineTransform transform;\n        [JPCGTransform transStruct:&transform ofDict:m];\n        CGPathAddArc([self formatPointerJSToOC:path], &transform, x, y, radius, startAngle, endAngle, clockwise);\n    };\n\n    context[@\"CGPathAddArcToPoint\"]           = ^void(JSValue *path,\n                                            NSDictionary *m, CGFloat x1, CGFloat y1, CGFloat x2, CGFloat y2,\n                                            CGFloat radius) {\n        CGAffineTransform transform;\n        [JPCGTransform transStruct:&transform ofDict:m];\n        CGPathAddArcToPoint([self formatPointerJSToOC:path], &transform, x1, y1, x2, y2, radius);\n    };\n    context[@\"CGPathAddCurveToPoint\"]         = ^void(JSValue *path,\n                                              NSDictionary *m, CGFloat cp1x, CGFloat cp1y,\n                                              CGFloat cp2x, CGFloat cp2y, CGFloat x, CGFloat y) {\n        CGAffineTransform transform;\n        [JPCGTransform transStruct:&transform ofDict:m];\n        CGPathAddCurveToPoint([self formatPointerJSToOC:path], &transform, cp1x, cp1y, cp2x, cp2y, x, y);\n    };\n\n    context[@\"CGPathAddEllipseInRect\"]        = ^void(JSValue *path,\n                                               NSDictionary *m, NSDictionary *rectDict) {\n        CGAffineTransform transform;\n        [JPCGTransform transStruct:&transform ofDict:m];\n        CGRect rect;\n        [JPCGGeometry rectStruct:&rect ofDict:rectDict];\n        CGPathAddEllipseInRect([self formatPointerJSToOC:path], &transform, rect);\n    };\n\n    context[@\"CGPathAddLineToPoint\"]          = ^void(JSValue *path,\n                                             NSDictionary *m, CGFloat x, CGFloat y) {\n        CGAffineTransform transform;\n        [JPCGTransform transStruct:&transform ofDict:m];\n        CGPathAddLineToPoint([self formatPointerJSToOC:path], &transform, x, y);\n    };\n\n\n    context[@\"CGPathAddLines\"]                = ^void(JSValue *path,\n                                      NSDictionary *m, NSArray *pointsArray, size_t count) {\n        CGPoint *points = malloc(sizeof(CGPoint) * count);\n        for (int i = 0; i < count; i++) {\n            CGPoint point;\n            [JPCGGeometry pointStruct:&point ofDict:pointsArray[i]];\n            points[i]   = point;\n        }\n        CGAffineTransform transform;\n        [JPCGTransform transStruct:&transform ofDict:m];\n        CGPathAddLines([self formatPointerJSToOC:path], &transform, points, count);\n        free(points);\n    };\n\n    context[@\"CGPathAddRect\"]                 = ^void(JSValue *path, NSDictionary *m,\n                                      NSDictionary *rectDict) {\n        CGRect rect;\n        CGAffineTransform transform;\n        [JPCGGeometry rectStruct:&rect ofDict:rectDict];\n        [JPCGTransform transStruct:&transform ofDict:m];\n        CGPathAddRect([self formatPointerJSToOC:path], &transform, rect);\n    };\n\n    context[@\"CGPathCreateMutable\"]           = ^id() {\n        CGMutablePathRef path = CGPathCreateMutable();\n        return [self formatRetainedCFTypeOCToJS:path];\n    };\n\n    context[@\"CGPathMoveToPoint\"]             = ^void(JSValue *path,\n                                               NSDictionary *m, CGFloat x, CGFloat y) {\n        CGAffineTransform transform;\n        [JPCGTransform transStruct:&transform ofDict:m];\n        CGPathMoveToPoint([self formatPointerJSToOC:path], &transform, x, y);\n    };\n\n    context[@\"CGPathCloseSubpath\"]            = ^void(JSValue *path) {\n        CGPathCloseSubpath([self formatPointerJSToOC:path]);\n    };\n\n    context[@\"CGPathContainsPoint\"]           = ^BOOL(JSValue *path,\n                                               NSDictionary *m, NSDictionary *pointDict, bool eoFill) {\n        CGAffineTransform transform;\n        [JPCGTransform transStruct:&transform ofDict:m];\n        CGPoint point;\n        [JPCGGeometry pointDictOfStruct:&point];\n        return CGPathContainsPoint([self formatPointerJSToOC:path], &transform, point, eoFill);\n    };\n\n    context[@\"CGPathCreateWithEllipseInRect\"] = ^id(NSDictionary *rectDict,\n                                                    NSDictionary *transformDict) {\n        CGRect rect;\n        CGAffineTransform transform;\n        [JPCGGeometry rectStruct:&rect ofDict:rectDict];\n        [JPCGTransform transStruct:&transform ofDict:transformDict];\n        CGPathRef path = CGPathCreateWithEllipseInRect(rect, &transform);\n        return [self formatRetainedCFTypeOCToJS:(void *)path];\n    };\n\n    context[@\"CGPathGetPathBoundingBox\"]      = ^NSDictionary *(JSValue *path) {\n        CGRect rect = CGPathGetPathBoundingBox([self formatPointerJSToOC:path]);\n        return [JPCGGeometry rectDictOfStruct:&rect];\n    };\n\n    context[@\"CGPathRelease\"]                 = ^void(JSValue *path) {\n        CGPathRelease([self formatPointerJSToOC:path]);\n    };\n}\n\n\n@end\n"
  },
  {
    "path": "Extensions/JPCFunctionBinder/CoreGraphics/JPCGTransform.h",
    "content": "//\n//  JPCGTransform.h\n//  JSPatchDemo\n//\n//  Created by bang on 15/6/30.\n//  Copyright (c) 2015 bang. All rights reserved.\n//\n\n#import \"JPEngine.h\"\n#import <CoreGraphics/CoreGraphics.h>\n\n@interface JPCGTransform : JPExtension\n\n+ (NSDictionary *)transDictOfStruct:(CGAffineTransform *)trans;\n+ (void)transStruct:(CGAffineTransform *)trans ofDict:(NSDictionary *)dict;\n\n@end\n"
  },
  {
    "path": "Extensions/JPCFunctionBinder/CoreGraphics/JPCGTransform.m",
    "content": "//\n//  JPCGTransform.m\n//  JSPatchDemo\n//\n//  Created by bang on 15/6/30.\n//  Copyright (c) 2015 bang. All rights reserved.\n//\n\n#import \"JPCGTransform.h\"\n#import \"JPCGGeometry.h\"\n\n#define TRANSFORM_DEFINE @{ \\\n    @\"name\": @\"CGAffineTransform\",  \\\n    @\"types\": @\"FFFFFF\",    \\\n    @\"keys\": @[@\"a\", @\"b\", @\"c\", @\"d\", @\"tx\", @\"ty\"]    \\\n}\n\n@implementation JPCGTransform\nstatic NSDictionary *transformStructDefine;\n+ (void)main:(JSContext *)context\n{\n    transformStructDefine = TRANSFORM_DEFINE;\n    [JPEngine defineStruct:transformStructDefine];\n    \n    context[@\"CGAffineTransformMakeTranslation\"] = ^id(CGFloat tx, CGFloat ty) {\n    CGAffineTransform trans                      = CGAffineTransformMakeTranslation(tx, ty);\n        return [self getDictOfStruct:&trans structDefine:transformStructDefine];\n    };\n\n    context[@\"CGAffineTransformMakeRotation\"]    = ^id(CGFloat angle) {\n        CGAffineTransform trans = CGAffineTransformMakeRotation(angle);\n        return [self getDictOfStruct:&trans structDefine:transformStructDefine];\n    };\n\n    context[@\"CGAffineTransformMakeScale\"]       = ^id(CGFloat sx, CGFloat sy) {\n        CGAffineTransform trans = CGAffineTransformMakeScale(sx, sy);\n        return [self getDictOfStruct:&trans structDefine:transformStructDefine];\n    };\n    \n    context[@\"CGAffineTransformTranslate\"]       = ^id(NSDictionary *transformDict, CGFloat tx, CGFloat ty) {\n        CGAffineTransform trans;\n        [self getStructDataWidthDict:&trans dict:transformDict structDefine:transformStructDefine];\n        CGAffineTransform translatedTransform = CGAffineTransformTranslate(trans, tx, ty);\n        return [self getDictOfStruct:&translatedTransform structDefine:transformStructDefine];\n    };\n\n    context[@\"CGAffineTransformScale\"]           = ^id(NSDictionary *transformDict, CGFloat sx, CGFloat sy) {\n        CGAffineTransform trans;\n        [self getStructDataWidthDict:&trans dict:transformDict structDefine:transformStructDefine];\n        CGAffineTransform translatedTransform = CGAffineTransformScale(trans, sx, sy);\n        return [self getDictOfStruct:&translatedTransform structDefine:transformStructDefine];\n    };\n\n    context[@\"CGAffineTransformRotate\"]          = ^id(NSDictionary *transformDict, CGFloat angle) {\n        CGAffineTransform trans;\n        [self getStructDataWidthDict:&trans dict:transformDict structDefine:transformStructDefine];\n        CGAffineTransform translatedTransform = CGAffineTransformRotate(trans, angle);\n        return [self getDictOfStruct:&translatedTransform structDefine:transformStructDefine];\n    };\n    \n    context[@\"CGRectApplyAffineTransform\"]       = ^NSDictionary *(NSDictionary *rectDict, NSDictionary *transformDict) {\n        CGRect rect;\n        CGAffineTransform transform;\n        [self getStructDataWidthDict:&transform dict:transformDict structDefine:transformStructDefine];\n        [JPCGGeometry rectStruct:&rect ofDict:rectDict];\n        CGRect retRect = CGRectApplyAffineTransform(rect, transform);\n        return [JPCGGeometry rectDictOfStruct:&retRect];\n    };\n}\n\n+ (NSDictionary *)transDictOfStruct:(CGAffineTransform *)trans\n{\n    return [self getDictOfStruct:trans structDefine:transformStructDefine ? transformStructDefine : TRANSFORM_DEFINE];\n}\n+ (void)transStruct:(CGAffineTransform *)trans ofDict:(NSDictionary *)dict\n{\n    [self getStructDataWidthDict:trans dict:dict structDefine:transformStructDefine ? transformStructDefine : TRANSFORM_DEFINE];\n}\n\n@end\n"
  },
  {
    "path": "Extensions/JPCFunctionBinder/CoreGraphics/JPCoreGraphics.h",
    "content": "//\n//  JPCoreGraphics.h\n//  JSPatchDemo\n//\n//  Created by Albert438 on 15/7/3.\n//  Copyright © 2015年 bang. All rights reserved.\n//\n\n#import \"JPEngine.h\"\n\n@interface JPCoreGraphics : JPExtension\n\n@end\n"
  },
  {
    "path": "Extensions/JPCFunctionBinder/CoreGraphics/JPCoreGraphics.m",
    "content": "//\n//  JPCoreGraphics.m\n//  JSPatchDemo\n//\n//  Created by Albert438 on 15/7/3.\n//  Copyright © 2015年 bang. All rights reserved.\n//\n\n#import \"JPCoreGraphics.h\"\n#import \"JPEngine.h\"\n\n\n@implementation JPCoreGraphics\n\n+ (void)main:(JSContext *)context\n{\n    NSArray *extensionArray = @[@\"JPCGTransform\", @\"JPCGContext\", @\"JPCGGeometry\", @\"JPCGBitmapContext\",\n                                            @\"JPCGColor\", @\"JPCGImage\", @\"JPCGPath\"];\n    [JPEngine addExtensions:extensionArray];\n}\n\n@end\n"
  },
  {
    "path": "Extensions/JPCFunctionBinder/UIKit/JPUIGeometry.h",
    "content": "//\n//  JPUIGeometry.h\n//  JSPatchDemo\n//\n//  Created by Albert438 on 15/7/6.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import \"JPEngine.h\"\n\n@interface JPUIGeometry : JPExtension\n\n@end\n"
  },
  {
    "path": "Extensions/JPCFunctionBinder/UIKit/JPUIGeometry.m",
    "content": "//\n//  JPUIGeometry.m\n//  JSPatchDemo\n//\n//  Created by Albert438 on 15/7/6.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import \"JPUIGeometry.h\"\n#import \"JPCGGeometry.h\"\n#import <UIKit/UIKit.h>\n\n\n@implementation JPUIGeometry\n\n+ (void)main:(JSContext *)context\n{\n    [JPEngine defineStruct:@{@\"name\": @\"UIEdgeInsets\",\n                             @\"types\": @\"FFFF\",\n                             @\"keys\": @[@\"top\", @\"left\", @\"bottom\", @\"right\"]\n                             }];\n    \n    [JPEngine defineStruct:@{@\"name\": @\"UIOffset\",\n                             @\"types\": @\"FF\",\n                             @\"keys\": @[@\"horizontal\", @\"vertical\"]\n                             }];\n    \n    context[@\"CGRectFromString\"]   = ^NSDictionary *(NSString *string) {\n        CGRect rect = CGRectFromString(string);\n        return [JPCGGeometry rectDictOfStruct:&rect];\n    };\n    \n    context[@\"CGSizeFromString\"]   = ^NSDictionary *(NSString *string) {\n        CGSize size = CGSizeFromString(string);\n        return [JPCGGeometry sizeDictOfStruct:&size];\n    };\n    \n    context[@\"CGPointFromString\"]  = ^NSDictionary *(NSString *string) {\n        CGPoint point = CGPointFromString(string);\n        return [JPCGGeometry pointDictOfStruct:&point];\n    };\n    \n    context[@\"CGVectorFromString\"] = ^NSDictionary *(NSString *string) {\n        CGVector vector =  CGVectorFromString(string);\n        return [JPCGGeometry vectorDictOfStruct:&vector];\n    };\n}\n\n@end\n"
  },
  {
    "path": "Extensions/JPCFunctionBinder/UIKit/JPUIGraphics.h",
    "content": "//\n//  UIGraphics.h\n//  JSPatchDemo\n//\n//  Created by Albert438 on 15/7/6.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import \"JPEngine.h\"\n\n@interface JPUIGraphics : JPExtension\n\n@end\n"
  },
  {
    "path": "Extensions/JPCFunctionBinder/UIKit/JPUIGraphics.m",
    "content": "//\n//  UIGraphics.m\n//  JSPatchDemo\n//\n//  Created by Albert438 on 15/7/6.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n\n#import \"JPUIGraphics.h\"\n#import \"JPCGGeometry.h\"\n#import <UIKit/UIKit.h>\n\n@implementation JPUIGraphics\n\n+ (void)main:(JSContext *)context\n{\n    context[@\"UIGraphicsGetCurrentContext\"] = ^id() {\n        CGContextRef c = UIGraphicsGetCurrentContext();\n        return [self formatPointerOCToJS:c];\n    };\n    \n    context[@\"UIGraphicsBeginImageContext\"] = ^void(NSDictionary *sizeDict) {\n        CGSize size;\n        [JPCGGeometry sizeStruct:&size ofDict:sizeDict];\n        UIGraphicsBeginImageContext(size);\n    };\n    \n    context[@\"UIGraphicsBeginImageContextWithOptions\"] = ^void(NSDictionary *sizeDict, BOOL opaque, CGFloat scale) {\n        CGSize size;\n        [JPCGGeometry sizeStruct:&size ofDict:sizeDict];\n        UIGraphicsBeginImageContextWithOptions(size, opaque, scale);\n    };\n    \n    context[@\"UIGraphicsGetImageFromCurrentImageContext\"] = ^id() {\n        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();\n        return [self formatOCToJS:image];\n    };\n    \n    context[@\"UIGraphicsEndImageContext\"] = ^void() {\n        UIGraphicsEndImageContext();\n    };\n}\n\n@end\n"
  },
  {
    "path": "Extensions/JPCFunctionBinder/UIKit/JPUIImage.h",
    "content": "//\n//  JPUIImage.h\n//  JSPatchDemo\n//\n//  Created by Albert438 on 15/7/6.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import \"JPEngine.h\"\n\n@interface JPUIImage : JPExtension\n\n@end\n"
  },
  {
    "path": "Extensions/JPCFunctionBinder/UIKit/JPUIImage.m",
    "content": "//\n//  JPUIImage.m\n//  JSPatchDemo\n//\n//  Created by Albert438 on 15/7/6.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import \"JPUIImage.h\"\n#import <UIKit/UIKit.h>\n\n@implementation JPUIImage\n\n+ (void)main:(JSContext *)context\n{\n    context[@\"UIImageJPEGRepresentation\"] = ^id(JSValue *jsVal, CGFloat compressionQuality) {\n        UIImage *image = [self formatJSToOC:jsVal];\n        NSData *data = UIImageJPEGRepresentation(image, compressionQuality);\n        return [self formatOCToJS:data];\n    };\n    \n    context[@\"UIImagePNGRepresentation\"]  = ^id(JSValue *jsVal) {\n        UIImage *image = [self formatJSToOC:jsVal];\n        NSData *data   =  UIImagePNGRepresentation(image);\n        return [self formatOCToJS:data];\n    };\n    \n}\n\n@end\n"
  },
  {
    "path": "Extensions/JPCFunctionBinder/UIKit/JPUIKit.h",
    "content": "//\n//  JPUIKit.h\n//  JSPatchDemo\n//\n//  Created by Albert438 on 15/7/6.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import \"JPEngine.h\"\n\n@interface JPUIKit : JPExtension\n\n@end\n"
  },
  {
    "path": "Extensions/JPCFunctionBinder/UIKit/JPUIKit.m",
    "content": "//\n//  JPUIKit.m\n//  JSPatchDemo\n//\n//  Created by Albert438 on 15/7/6.\n//  Copyright (c) 2015年 bang. All rights reserved.\n//\n\n#import \"JPUIKit.h\"\n\n@implementation JPUIKit\n\n+ (void)main:(JSContext *)context\n{\n    NSArray *extensionArray = @[@\"JPUIGraphics\", @\"JPUIGeometry\", @\"JPUIImage\"];\n    [JPEngine addExtensions:extensionArray];\n}\n\n@end"
  },
  {
    "path": "Extensions/JPCleaner.h",
    "content": "//\n//  JPReverter.h\n//  JSPatchDemo\n//\n//  Created by bang on 2/4/16.\n//  Copyright © 2016 bang. All rights reserved.\n//\n\n#import \"JPEngine.h\"\n\n@interface JPCleaner : JPExtension\n+ (void)cleanAll;\n+ (void)cleanClass:(NSString *)className;\n@end\n"
  },
  {
    "path": "Extensions/JPCleaner.m",
    "content": "//\n//  JPReverter.m\n//  JSPatchDemo\n//\n//  Created by bang on 2/4/16.\n//  Copyright © 2016 bang. All rights reserved.\n//\n\n#import \"JPCleaner.h\"\n#import <objc/runtime.h>\n#import <objc/message.h>\n\n@implementation JPCleaner\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wundeclared-selector\"\n\n+ (void)cleanAll\n{\n    [self cleanClass:nil];\n    [[self includedScriptPaths] removeAllObjects];\n}\n\n+ (void)cleanClass:(NSString *)className\n{\n    NSDictionary *methodsDict = [JPExtension overideMethods];\n    for (Class cls in methodsDict.allKeys) {\n        if (className && ![className isEqualToString:NSStringFromClass(cls)]) {\n            continue;\n        }\n        for (NSString *jpSelectorName in [methodsDict[cls] allKeys]) {\n            NSString *selectorName = [jpSelectorName substringFromIndex:3];\n            NSString *originalSelectorName = [NSString stringWithFormat:@\"ORIG%@\", selectorName];\n            \n            SEL selector = NSSelectorFromString(selectorName);\n            SEL originalSelector = NSSelectorFromString(originalSelectorName);\n            IMP originalImp = class_respondsToSelector(cls, originalSelector) ? class_getMethodImplementation(cls, originalSelector) : NULL;\n            \n            Method method = class_getInstanceMethod(cls, originalSelector);\n            char *typeDescription = (char *)method_getTypeEncoding(method);\n            \n            class_replaceMethod(cls, selector, originalImp, typeDescription);\n        }\n        \n        char *typeDescription = (char *)method_getTypeEncoding(class_getInstanceMethod(cls, @selector(forwardInvocation:)));\n        IMP forwardInvocationIMP = class_getMethodImplementation(cls, @selector(ORIGforwardInvocation:));\n        \n        //forwardInvocationIMP will be _objc_msgForward if ORIGforwardInvocation: doesn't exist\n        if (forwardInvocationIMP == _objc_msgForward) {\n            class_replaceMethod(cls, @selector(forwardInvocation:), NULL, typeDescription);\n        } else {\n            class_replaceMethod(cls, @selector(forwardInvocation:), forwardInvocationIMP, typeDescription);\n        }\n    }\n}\n\n#pragma clang diagnostic pop\n@end\n"
  },
  {
    "path": "Extensions/JPDispatch.h",
    "content": "//\n//  JPDispatch.h\n//  JSPatchDemo\n//\n//  Created by bang on 10/9/16.\n//  Copyright © 2016 bang. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"JPEngine.h\"\n\n@interface JPDispatch : JPExtension\n\n@end\n"
  },
  {
    "path": "Extensions/JPDispatch.m",
    "content": "//\n//  JPDispatch.m\n//  JSPatchDemo\n//\n//  Created by bang on 10/9/16.\n//  Copyright © 2016 bang. All rights reserved.\n//\n\n#import \"JPDispatch.h\"\n\n@implementation JPDispatch\n+ (void)main:(JSContext *)context\n{\n    /* CONSTANT */\n    context[@\"_DISPATCH_QUEUE_PRIORITY_BACKGROUND\"] = ^id() {\n        return @(DISPATCH_QUEUE_PRIORITY_BACKGROUND);\n    };\n    \n    context[@\"_DISPATCH_TIME_FOREVER\"] = ^id() {\n        return @(DISPATCH_TIME_FOREVER);\n    };\n    context[@\"_DISPATCH_TIME_NOW\"] = ^id() {\n        return @(DISPATCH_TIME_NOW);\n    };\n    context[@\"_DISPATCH_QUEUE_CONCURRENT\"] = ^id() {\n        return [self formatPointerOCToJS:(__bridge void *)DISPATCH_QUEUE_CONCURRENT];\n    };\n    \n    context[@\"dispatch_time\"] = ^id(double second) {\n        return @(dispatch_time(DISPATCH_TIME_NOW, second * NSEC_PER_SEC));\n    };\n    \n    \n    /* queue */\n    context[@\"dispatch_get_global_queue\"] = ^id(long identifier, unsigned long flags) {\n        return dispatch_get_global_queue(identifier, flags);\n    };\n    \n    context[@\"dispatch_get_main_queue\"] = ^id(long identifier, unsigned long flags) {\n        return dispatch_get_main_queue();\n    };\n    \n    context[@\"dispatch_queue_create\"] = ^id(NSString *queueName, JSValue *attrJS) {\n        dispatch_queue_attr_t attr = [self formatPointerJSToOC:attrJS];\n        dispatch_queue_t queue = dispatch_queue_create([queueName cStringUsingEncoding:NSUTF8StringEncoding], attr);\n        return queue;\n    };\n    \n    \n    /* dispatch & dispatch_barrier */\n    context[@\"dispatch_async\"] = ^void(JSValue *queue, JSValue *cb) {\n        dispatch_async([self formatJSToOC:queue], ^{\n            [cb callWithArguments:nil];\n        });\n    };\n    \n    context[@\"dispatch_sync\"] = ^void(JSValue *queue, JSValue *cb) {\n        dispatch_sync([self formatJSToOC:queue], ^{\n            [cb callWithArguments:nil];\n        });\n    };\n    \n    context[@\"dispatch_barrier_async\"] = ^void(JSValue *queue, JSValue *cb) {\n        dispatch_barrier_async([self formatJSToOC:queue], ^{\n            [cb callWithArguments:nil];\n        });\n    };\n    \n    context[@\"dispatch_barrier_sync\"] = ^void(JSValue *queue, JSValue *cb) {\n        dispatch_barrier_sync([self formatJSToOC:queue], ^{\n            [cb callWithArguments:nil];\n        });\n    };\n    \n    context[@\"dispatch_apply\"] = ^void(size_t iterations, JSValue *queue, JSValue *cb) {\n        dispatch_apply(iterations, [self formatJSToOC:queue], ^(size_t index) {\n            [cb callWithArguments:@[@(index)]];\n        });\n    };\n    \n    \n    \n    /* dispatch_group */\n    context[@\"dispatch_group_create\"] = ^id() {\n        dispatch_group_t group = dispatch_group_create();\n        return group;\n    };\n    \n    context[@\"dispatch_group_async\"] = ^void(JSValue *group, JSValue *queue, JSValue *cb) {\n        dispatch_group_async([self formatJSToOC:group], [self formatJSToOC:queue], ^{\n            [cb callWithArguments:nil];\n        });\n    };\n    \n    context[@\"dispatch_group_wait\"] = ^void(JSValue *group, uint64_t dispatch_time) {\n        dispatch_group_wait([self formatJSToOC:group], dispatch_time);\n    };\n    \n    context[@\"dispatch_group_notify\"] = ^void(JSValue *group, JSValue *queue, JSValue *cb) {\n        dispatch_group_notify([self formatJSToOC:group], [self formatJSToOC:queue], ^{\n            [cb callWithArguments:nil];\n        });\n    };\n    \n    context[@\"dispatch_group_enter\"] = ^void(JSValue *group) {\n        dispatch_group_enter([self formatJSToOC:group]);\n    };\n    \n    context[@\"dispatch_group_leave\"] = ^void(JSValue *group) {\n        dispatch_group_leave([self formatJSToOC:group]);\n    };\n    \n    \n    [context evaluateScript:@\"  \\\n     global.DISPATCH_QUEUE_PRIORITY_HIGH = 2;   \\\n     global.DISPATCH_QUEUE_PRIORITY_DEFAULT = 0;    \\\n     global.DISPATCH_QUEUE_PRIORITY_LOW = -2;   \\\n     global.DISPATCH_QUEUE_PRIORITY_BACKGROUND = _DISPATCH_QUEUE_PRIORITY_BACKGROUND();  \\\n     global.DISPATCH_TIME_NOW = _DISPATCH_TIME_NOW();   \\\n     global.DISPATCH_TIME_FOREVER = _DISPATCH_TIME_FOREVER();   \\\n     global.DISPATCH_QUEUE_CONCURRENT = _DISPATCH_QUEUE_CONCURRENT();   \\\n     global.DISPATCH_QUEUE_SERIAL = 0;   \\\n     \"];\n}\n\n@end\n"
  },
  {
    "path": "Extensions/JPLibffi/JPMethodSignature.h",
    "content": "//\n//  JPMethodSignature.h\n//  JSPatch\n//\n//  Created by bang on 1/19/17.\n//  Copyright © 2017 bang. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"ffi.h\"\n\n@interface JPMethodSignature : NSObject\n\n@property (nonatomic, readonly) NSString *types;\n@property (nonatomic, readonly) NSArray *argumentTypes;\n@property (nonatomic, readonly) NSString *returnType;\n\n- (instancetype)initWithObjCTypes:(NSString *)objCTypes;\n- (instancetype)initWithBlockTypeNames:(NSString *)typeNames;\n\n+ (ffi_type *)ffiTypeWithEncodingChar:(const char *)c;\n+ (NSString *)typeEncodeWithTypeName:(NSString *)typeName;\n\n@end\n"
  },
  {
    "path": "Extensions/JPLibffi/JPMethodSignature.m",
    "content": "//\n//  JPMethodSignature.m\n//  JSPatch\n//\n//  Created by bang on 1/19/17.\n//  Copyright © 2017 bang. All rights reserved.\n//\n\n#import \"JPMethodSignature.h\"\n#import <UIKit/UIKit.h>\n#import \"JPEngine.h\"\n\n@implementation JPMethodSignature {\n    NSString *_typeNames;\n    NSMutableArray *_argumentTypes;\n    NSString *_returnType;\n    NSString *_types;\n    BOOL _isBlock;\n}\n\n\n- (instancetype)initWithBlockTypeNames:(NSString *)typeNames\n{\n    self = [super init];\n    if (self) {\n        _typeNames = typeNames;\n        _isBlock = YES;\n        [self _parseTypeNames];\n        [self _parse];\n    }\n    return self;\n}\n\n- (instancetype)initWithObjCTypes:(NSString *)objCTypes\n{\n    self = [super init];\n    if (self) {\n        _types = objCTypes;\n        [self _parse];\n    }\n    return self;\n}\n\n- (void)_parse\n{\n    _argumentTypes = [[NSMutableArray alloc] init];\n    for (int i = 0; i < _types.length; i ++) {\n        unichar c = [_types characterAtIndex:i];\n        NSString *arg;\n        \n        if (isdigit(c)) continue;\n        \n        BOOL skipNext = NO;\n        if (c == '^') {\n            skipNext = YES;\n            arg = [_types substringWithRange:NSMakeRange(i, 2)];\n            \n        } else if (c == '?') {\n            // @? is block\n            arg = [_types substringWithRange:NSMakeRange(i - 1, 2)];\n            [_argumentTypes removeLastObject];\n            \n        } else if (c == '{') {\n            NSUInteger end = [[_types substringFromIndex:i] rangeOfString:@\"}\"].location + i;\n            arg = [_types substringWithRange:NSMakeRange(i, end - i + 1)];\n            if (i == 0) {\n                _returnType = arg;\n            } else {\n                [_argumentTypes addObject:arg];\n            }\n            i = (int)end;\n            continue;\n        \n        } else {\n            \n            arg = [_types substringWithRange:NSMakeRange(i, 1)];\n        }\n        \n        if (i == 0) {\n            _returnType = arg;\n        } else {\n            [_argumentTypes addObject:arg];\n        }\n        if (skipNext) i++;\n    }\n}\n\n- (void)_parseTypeNames\n{\n    NSMutableString *encodeStr = [[NSMutableString alloc] init];\n    NSArray *typeArr = [_typeNames componentsSeparatedByString:@\",\"];\n    for (NSInteger i = 0; i < typeArr.count; i++) {\n        NSString *typeStr = trim([typeArr objectAtIndex:i]);\n        NSString *encode = [JPMethodSignature typeEncodeWithTypeName:typeStr];\n        if (!encode) {\n            NSString *argClassName = trim([typeStr stringByReplacingOccurrencesOfString:@\"*\" withString:@\"\"]);\n            if (NSClassFromString(argClassName) != NULL) {\n                encode = @\"@\";\n            } else {\n                NSCAssert(NO, @\"unreconized type %@\", typeStr);\n                return;\n            }\n        }\n        [encodeStr appendString:encode];\n        int length = [JPMethodSignature typeLengthWithTypeName:typeStr];\n        [encodeStr appendString:[NSString stringWithFormat:@\"%d\", length]];\n        \n        if (_isBlock && i == 0) {\n            // Blocks are passed one implicit argument - the block, of type \"@?\".\n            [encodeStr appendString:@\"@?0\"];\n        }\n    }\n    _types = encodeStr;\n}\n\n- (NSArray *)argumentTypes\n{\n    return _argumentTypes;\n}\n\n- (NSString *)types\n{\n    return _types;\n}\n\n- (NSString *)returnType\n{\n    return _returnType;\n}\n\n#pragma mark - class methods\n\n+ (ffi_type *)ffiTypeWithEncodingChar:(const char *)c\n{\n    switch (c[0]) {\n        case 'v':\n        return &ffi_type_void;\n        case 'c':\n        return &ffi_type_schar;\n        case 'C':\n        return &ffi_type_uchar;\n        case 's':\n        return &ffi_type_sshort;\n        case 'S':\n        return &ffi_type_ushort;\n        case 'i':\n        return &ffi_type_sint;\n        case 'I':\n        return &ffi_type_uint;\n        case 'l':\n        return &ffi_type_slong;\n        case 'L':\n        return &ffi_type_ulong;\n        case 'q':\n        return &ffi_type_sint64;\n        case 'Q':\n        return &ffi_type_uint64;\n        case 'f':\n        return &ffi_type_float;\n        case 'd':\n        return &ffi_type_double;\n        case 'F':\n#if CGFLOAT_IS_DOUBLE\n        return &ffi_type_double;\n#else\n        return &ffi_type_float;\n#endif\n        case 'B':\n        return &ffi_type_uint8;\n        case '^':\n        return &ffi_type_pointer;\n        case '@':\n        return &ffi_type_pointer;\n        case '#':\n        return &ffi_type_pointer;\n        case '{':\n        {\n            NSString *typeStr = [NSString stringWithCString:c encoding:NSASCIIStringEncoding];\n            NSUInteger end = [typeStr rangeOfString:@\"}\"].location;\n            if (end != NSNotFound) {\n                NSString *structName = [typeStr substringWithRange:NSMakeRange(1, end - 1)];\n                ffi_type *type = malloc(sizeof(ffi_type));\n                type->alignment = 0;\n                type->size = 0;\n                type->type = FFI_TYPE_STRUCT;\n                NSDictionary *structDefine = [JPExtension registeredStruct][structName];\n                NSUInteger subTypeCount = [structDefine[@\"keys\"] count];\n                NSString *subTypes = structDefine[@\"types\"];\n                ffi_type **sub_types = malloc(sizeof(ffi_type *) * (subTypeCount + 1));\n                for (NSUInteger i=0; i<subTypeCount; i++) {\n                    sub_types[i] = [self ffiTypeWithEncodingChar:[subTypes cStringUsingEncoding:NSASCIIStringEncoding]];\n                    type->size += sub_types[i]->size;\n                }\n                sub_types[subTypeCount] = NULL;\n                type->elements = sub_types;\n                return type;\n            }\n        }\n    }\n    return NULL;\n}\n\nstatic NSMutableDictionary *_typeEncodeDict;\nstatic NSMutableDictionary *_typeLengthDict;\n\n+ (int)typeLengthWithTypeName:(NSString *)typeName\n{\n    if (!typeName) return 0;\n    if (!_typeLengthDict) {\n        _typeLengthDict = [[NSMutableDictionary alloc] init];\n        \n        #define JP_DEFINE_TYPE_LENGTH(_type) \\\n        [_typeLengthDict setObject:@(sizeof(_type)) forKey:@#_type];\\\n\n        JP_DEFINE_TYPE_LENGTH(id);\n        JP_DEFINE_TYPE_LENGTH(BOOL);\n        JP_DEFINE_TYPE_LENGTH(int);\n        JP_DEFINE_TYPE_LENGTH(void);\n        JP_DEFINE_TYPE_LENGTH(char);\n        JP_DEFINE_TYPE_LENGTH(short);\n        JP_DEFINE_TYPE_LENGTH(unsigned short);\n        JP_DEFINE_TYPE_LENGTH(unsigned int);\n        JP_DEFINE_TYPE_LENGTH(long);\n        JP_DEFINE_TYPE_LENGTH(unsigned long);\n        JP_DEFINE_TYPE_LENGTH(long long);\n        JP_DEFINE_TYPE_LENGTH(unsigned long long);\n        JP_DEFINE_TYPE_LENGTH(float);\n        JP_DEFINE_TYPE_LENGTH(double);\n        JP_DEFINE_TYPE_LENGTH(bool);\n        JP_DEFINE_TYPE_LENGTH(size_t);\n        JP_DEFINE_TYPE_LENGTH(CGFloat);\n        JP_DEFINE_TYPE_LENGTH(CGSize);\n        JP_DEFINE_TYPE_LENGTH(CGRect);\n        JP_DEFINE_TYPE_LENGTH(CGPoint);\n        JP_DEFINE_TYPE_LENGTH(CGVector);\n        JP_DEFINE_TYPE_LENGTH(NSRange);\n        JP_DEFINE_TYPE_LENGTH(NSInteger);\n        JP_DEFINE_TYPE_LENGTH(Class);\n        JP_DEFINE_TYPE_LENGTH(SEL);\n        JP_DEFINE_TYPE_LENGTH(void*);\n        JP_DEFINE_TYPE_LENGTH(void *);\n        JP_DEFINE_TYPE_LENGTH(id *);\n    }\n    return [_typeLengthDict[typeName] intValue];\n}\n\n+ (NSString *)typeEncodeWithTypeName:(NSString *)typeName\n{\n    if (!typeName) return nil;\n    if (!_typeEncodeDict) {\n        _typeEncodeDict = [[NSMutableDictionary alloc] init];\n        #define JP_DEFINE_TYPE_ENCODE_CASE(_type) \\\n        [_typeEncodeDict setObject:[NSString stringWithUTF8String:@encode(_type)] forKey:@#_type];\\\n\n        JP_DEFINE_TYPE_ENCODE_CASE(id);\n        JP_DEFINE_TYPE_ENCODE_CASE(BOOL);\n        JP_DEFINE_TYPE_ENCODE_CASE(int);\n        JP_DEFINE_TYPE_ENCODE_CASE(void);\n        JP_DEFINE_TYPE_ENCODE_CASE(char);\n        JP_DEFINE_TYPE_ENCODE_CASE(short);\n        JP_DEFINE_TYPE_ENCODE_CASE(unsigned short);\n        JP_DEFINE_TYPE_ENCODE_CASE(unsigned int);\n        JP_DEFINE_TYPE_ENCODE_CASE(long);\n        JP_DEFINE_TYPE_ENCODE_CASE(unsigned long);\n        JP_DEFINE_TYPE_ENCODE_CASE(long long);\n        JP_DEFINE_TYPE_ENCODE_CASE(unsigned long long);\n        JP_DEFINE_TYPE_ENCODE_CASE(float);\n        JP_DEFINE_TYPE_ENCODE_CASE(double);\n        JP_DEFINE_TYPE_ENCODE_CASE(bool);\n        JP_DEFINE_TYPE_ENCODE_CASE(size_t);\n        JP_DEFINE_TYPE_ENCODE_CASE(CGFloat);\n        JP_DEFINE_TYPE_ENCODE_CASE(CGSize);\n        JP_DEFINE_TYPE_ENCODE_CASE(CGRect);\n        JP_DEFINE_TYPE_ENCODE_CASE(CGPoint);\n        JP_DEFINE_TYPE_ENCODE_CASE(CGVector);\n        JP_DEFINE_TYPE_ENCODE_CASE(NSRange);\n        JP_DEFINE_TYPE_ENCODE_CASE(NSInteger);\n        JP_DEFINE_TYPE_ENCODE_CASE(Class);\n        JP_DEFINE_TYPE_ENCODE_CASE(SEL);\n        JP_DEFINE_TYPE_ENCODE_CASE(void*);\n        JP_DEFINE_TYPE_ENCODE_CASE(void *);\n        [_typeEncodeDict setObject:@\"@?\" forKey:@\"block\"];\n        [_typeEncodeDict setObject:@\"^@\" forKey:@\"id*\"];\n    }\n    return _typeEncodeDict[typeName];\n}\n\nstatic NSString *trim(NSString *string)\n{\n    return [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];\n}\n\n@end\n"
  },
  {
    "path": "Extensions/JPLibffi/libffi/ffi.h",
    "content": "#ifdef __arm64__\n\n#include \"ffi_arm64.h\"\n\n\n#endif\n#ifdef __i386__\n\n#include \"ffi_i386.h\"\n\n\n#endif\n#ifdef __arm__\n\n#include \"ffi_arm.h\"\n\n\n#endif\n#ifdef __x86_64__\n\n#include \"ffi_x86_64.h\"\n\n\n#endif\n"
  },
  {
    "path": "Extensions/JPLibffi/libffi/ffi_arm.h",
    "content": "/* -----------------------------------------------------------------*-C-*-\n   libffi 3.99999 - Copyright (c) 2011, 2014 Anthony Green\n                    - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.\n\n   Permission is hereby granted, free of charge, to any person\n   obtaining a copy of this software and associated documentation\n   files (the ``Software''), to deal in the Software without\n   restriction, including without limitation the rights to use, copy,\n   modify, merge, publish, distribute, sublicense, and/or sell copies\n   of the Software, and to permit persons to whom the Software is\n   furnished to do so, subject to the following conditions:\n\n   The above copyright notice and this permission notice shall be\n   included in all copies or substantial portions of the Software.\n\n   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,\n   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n   DEALINGS IN THE SOFTWARE.\n\n   ----------------------------------------------------------------------- */\n\n/* -------------------------------------------------------------------\n   Most of the API is documented in doc/libffi.texi.\n\n   The raw API is designed to bypass some of the argument packing and\n   unpacking on architectures for which it can be avoided.  Routines\n   are provided to emulate the raw API if the underlying platform\n   doesn't allow faster implementation.\n\n   More details on the raw API can be found in:\n\n   http://gcc.gnu.org/ml/java/1999-q3/msg00138.html\n\n   and\n\n   http://gcc.gnu.org/ml/java/1999-q3/msg00174.html\n   -------------------------------------------------------------------- */\n\n#ifndef LIBFFI_H\n#define LIBFFI_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Specify which architecture libffi is configured for. */\n#ifndef ARM\n#define ARM\n#endif\n\n/* ---- System configuration information --------------------------------- */\n\n#include \"ffitarget.h\"\n\n#ifndef LIBFFI_ASM\n\n#if defined(_MSC_VER) && !defined(__clang__)\n#define __attribute__(X)\n#endif\n\n#include <stddef.h>\n#include <limits.h>\n\n/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).\n   But we can find it either under the correct ANSI name, or under GNU\n   C's internal name.  */\n\n#define FFI_64_BIT_MAX 9223372036854775807\n\n#ifdef LONG_LONG_MAX\n# define FFI_LONG_LONG_MAX LONG_LONG_MAX\n#else\n# ifdef LLONG_MAX\n#  define FFI_LONG_LONG_MAX LLONG_MAX\n#  ifdef _AIX52 /* or newer has C99 LLONG_MAX */\n#   undef FFI_64_BIT_MAX\n#   define FFI_64_BIT_MAX 9223372036854775807LL\n#  endif /* _AIX52 or newer */\n# else\n#  ifdef __GNUC__\n#   define FFI_LONG_LONG_MAX __LONG_LONG_MAX__\n#  endif\n#  ifdef _AIX /* AIX 5.1 and earlier have LONGLONG_MAX */\n#   ifndef __PPC64__\n#    if defined (__IBMC__) || defined (__IBMCPP__)\n#     define FFI_LONG_LONG_MAX LONGLONG_MAX\n#    endif\n#   endif /* __PPC64__ */\n#   undef  FFI_64_BIT_MAX\n#   define FFI_64_BIT_MAX 9223372036854775807LL\n#  endif\n# endif\n#endif\n\n/* The closure code assumes that this works on pointers, i.e. a size_t\n   can hold a pointer.  */\n\ntypedef struct _ffi_type\n{\n  size_t size;\n  unsigned short alignment;\n  unsigned short type;\n  struct _ffi_type **elements;\n} ffi_type;\n\n#ifndef LIBFFI_HIDE_BASIC_TYPES\n#if SCHAR_MAX == 127\n# define ffi_type_uchar                ffi_type_uint8\n# define ffi_type_schar                ffi_type_sint8\n#else\n #error \"char size not supported\"\n#endif\n\n#if SHRT_MAX == 32767\n# define ffi_type_ushort       ffi_type_uint16\n# define ffi_type_sshort       ffi_type_sint16\n#elif SHRT_MAX == 2147483647\n# define ffi_type_ushort       ffi_type_uint32\n# define ffi_type_sshort       ffi_type_sint32\n#else\n #error \"short size not supported\"\n#endif\n\n#if INT_MAX == 32767\n# define ffi_type_uint         ffi_type_uint16\n# define ffi_type_sint         ffi_type_sint16\n#elif INT_MAX == 2147483647\n# define ffi_type_uint         ffi_type_uint32\n# define ffi_type_sint         ffi_type_sint32\n#elif INT_MAX == 9223372036854775807\n# define ffi_type_uint         ffi_type_uint64\n# define ffi_type_sint         ffi_type_sint64\n#else\n #error \"int size not supported\"\n#endif\n\n#if LONG_MAX == 2147483647\n# if FFI_LONG_LONG_MAX != FFI_64_BIT_MAX\n #error \"no 64-bit data type supported\"\n# endif\n#elif LONG_MAX != FFI_64_BIT_MAX\n #error \"long size not supported\"\n#endif\n\n#if LONG_MAX == 2147483647\n# define ffi_type_ulong        ffi_type_uint32\n# define ffi_type_slong        ffi_type_sint32\n#elif LONG_MAX == FFI_64_BIT_MAX\n# define ffi_type_ulong        ffi_type_uint64\n# define ffi_type_slong        ffi_type_sint64\n#else\n #error \"long size not supported\"\n#endif\n\n/* Need minimal decorations for DLLs to works on Windows.  GCC has\n   autoimport and autoexport.  Rely on Libtool to help MSVC export\n   from a DLL, but always declare data to be imported for MSVC\n   clients.  This costs an extra indirection for MSVC clients using\n   the static version of the library, but don't worry about that.\n   Besides, as a workaround, they can define FFI_BUILDING if they\n   *know* they are going to link with the static library.  */\n#if defined _MSC_VER && !defined FFI_BUILDING\n#define FFI_EXTERN extern __declspec(dllimport)\n#else\n#define FFI_EXTERN extern\n#endif\n\n/* These are defined in types.c.  */\nFFI_EXTERN ffi_type ffi_type_void;\nFFI_EXTERN ffi_type ffi_type_uint8;\nFFI_EXTERN ffi_type ffi_type_sint8;\nFFI_EXTERN ffi_type ffi_type_uint16;\nFFI_EXTERN ffi_type ffi_type_sint16;\nFFI_EXTERN ffi_type ffi_type_uint32;\nFFI_EXTERN ffi_type ffi_type_sint32;\nFFI_EXTERN ffi_type ffi_type_uint64;\nFFI_EXTERN ffi_type ffi_type_sint64;\nFFI_EXTERN ffi_type ffi_type_float;\nFFI_EXTERN ffi_type ffi_type_double;\nFFI_EXTERN ffi_type ffi_type_pointer;\n\n#if 0\nFFI_EXTERN ffi_type ffi_type_longdouble;\n#else\n#define ffi_type_longdouble ffi_type_double\n#endif\n\n#ifdef FFI_TARGET_HAS_COMPLEX_TYPE\nFFI_EXTERN ffi_type ffi_type_complex_float;\nFFI_EXTERN ffi_type ffi_type_complex_double;\n#if 0\nFFI_EXTERN ffi_type ffi_type_complex_longdouble;\n#else\n#define ffi_type_complex_longdouble ffi_type_complex_double\n#endif\n#endif\n#endif /* LIBFFI_HIDE_BASIC_TYPES */\n\ntypedef enum {\n  FFI_OK = 0,\n  FFI_BAD_TYPEDEF,\n  FFI_BAD_ABI\n} ffi_status;\n\ntypedef struct {\n  ffi_abi abi;\n  unsigned nargs;\n  ffi_type **arg_types;\n  ffi_type *rtype;\n  unsigned bytes;\n  unsigned flags;\n#ifdef FFI_EXTRA_CIF_FIELDS\n  FFI_EXTRA_CIF_FIELDS;\n#endif\n} ffi_cif;\n\n/* ---- Definitions for the raw API -------------------------------------- */\n\n#ifndef FFI_SIZEOF_ARG\n# if LONG_MAX == 2147483647\n#  define FFI_SIZEOF_ARG        4\n# elif LONG_MAX == FFI_64_BIT_MAX\n#  define FFI_SIZEOF_ARG        8\n# endif\n#endif\n\n#ifndef FFI_SIZEOF_JAVA_RAW\n#  define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG\n#endif\n\ntypedef union {\n  ffi_sarg  sint;\n  ffi_arg   uint;\n  float\t    flt;\n  char      data[FFI_SIZEOF_ARG];\n  void*     ptr;\n} ffi_raw;\n\n#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8\n/* This is a special case for mips64/n32 ABI (and perhaps others) where\n   sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8.  */\ntypedef union {\n  signed int\tsint;\n  unsigned int\tuint;\n  float\t\tflt;\n  char\t\tdata[FFI_SIZEOF_JAVA_RAW];\n  void*\t\tptr;\n} ffi_java_raw;\n#else\ntypedef ffi_raw ffi_java_raw;\n#endif\n\n\nvoid ffi_raw_call (ffi_cif *cif,\n\t\t   void (*fn)(void),\n\t\t   void *rvalue,\n\t\t   ffi_raw *avalue);\n\nvoid ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);\nvoid ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);\nsize_t ffi_raw_size (ffi_cif *cif);\n\n/* This is analogous to the raw API, except it uses Java parameter\n   packing, even on 64-bit machines.  I.e. on 64-bit machines longs\n   and doubles are followed by an empty 64-bit word.  */\n\nvoid ffi_java_raw_call (ffi_cif *cif,\n\t\t\tvoid (*fn)(void),\n\t\t\tvoid *rvalue,\n\t\t\tffi_java_raw *avalue);\n\nvoid ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw);\nvoid ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args);\nsize_t ffi_java_raw_size (ffi_cif *cif);\n\n/* ---- Definitions for closures ----------------------------------------- */\n\n#if FFI_CLOSURES\n\n#ifdef _MSC_VER\n__declspec(align(8))\n#endif\ntypedef struct {\n#if 1\n  void *trampoline_table;\n  void *trampoline_table_entry;\n#else\n  char tramp[FFI_TRAMPOLINE_SIZE];\n#endif\n  ffi_cif   *cif;\n  void     (*fun)(ffi_cif*,void*,void**,void*);\n  void      *user_data;\n} ffi_closure\n#ifdef __GNUC__\n    __attribute__((aligned (8)))\n#endif\n    ;\n\n#ifndef __GNUC__\n# ifdef __sgi\n#  pragma pack 0\n# endif\n#endif\n\nvoid *ffi_closure_alloc (size_t size, void **code);\nvoid ffi_closure_free (void *);\n\nffi_status\nffi_prep_closure (ffi_closure*,\n\t\t  ffi_cif *,\n\t\t  void (*fun)(ffi_cif*,void*,void**,void*),\n\t\t  void *user_data)\n  __attribute__((deprecated (\"use ffi_prep_closure_loc instead\")));\n\nffi_status\nffi_prep_closure_loc (ffi_closure*,\n\t\t      ffi_cif *,\n\t\t      void (*fun)(ffi_cif*,void*,void**,void*),\n\t\t      void *user_data,\n\t\t      void*codeloc);\n\n#ifdef __sgi\n# pragma pack 8\n#endif\ntypedef struct {\n#if 1\n  void *trampoline_table;\n  void *trampoline_table_entry;\n#else\n  char tramp[FFI_TRAMPOLINE_SIZE];\n#endif\n  ffi_cif   *cif;\n\n#if !FFI_NATIVE_RAW_API\n\n  /* If this is enabled, then a raw closure has the same layout \n     as a regular closure.  We use this to install an intermediate \n     handler to do the transaltion, void** -> ffi_raw*.  */\n\n  void     (*translate_args)(ffi_cif*,void*,void**,void*);\n  void      *this_closure;\n\n#endif\n\n  void     (*fun)(ffi_cif*,void*,ffi_raw*,void*);\n  void      *user_data;\n\n} ffi_raw_closure;\n\ntypedef struct {\n#if 1\n  void *trampoline_table;\n  void *trampoline_table_entry;\n#else\n  char tramp[FFI_TRAMPOLINE_SIZE];\n#endif\n\n  ffi_cif   *cif;\n\n#if !FFI_NATIVE_RAW_API\n\n  /* If this is enabled, then a raw closure has the same layout \n     as a regular closure.  We use this to install an intermediate \n     handler to do the translation, void** -> ffi_raw*.  */\n\n  void     (*translate_args)(ffi_cif*,void*,void**,void*);\n  void      *this_closure;\n\n#endif\n\n  void     (*fun)(ffi_cif*,void*,ffi_java_raw*,void*);\n  void      *user_data;\n\n} ffi_java_raw_closure;\n\nffi_status\nffi_prep_raw_closure (ffi_raw_closure*,\n\t\t      ffi_cif *cif,\n\t\t      void (*fun)(ffi_cif*,void*,ffi_raw*,void*),\n\t\t      void *user_data);\n\nffi_status\nffi_prep_raw_closure_loc (ffi_raw_closure*,\n\t\t\t  ffi_cif *cif,\n\t\t\t  void (*fun)(ffi_cif*,void*,ffi_raw*,void*),\n\t\t\t  void *user_data,\n\t\t\t  void *codeloc);\n\nffi_status\nffi_prep_java_raw_closure (ffi_java_raw_closure*,\n\t\t           ffi_cif *cif,\n\t\t           void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),\n\t\t           void *user_data);\n\nffi_status\nffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,\n\t\t\t       ffi_cif *cif,\n\t\t\t       void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),\n\t\t\t       void *user_data,\n\t\t\t       void *codeloc);\n\n#endif /* FFI_CLOSURES */\n\n#if FFI_GO_CLOSURES\n\ntypedef struct {\n  void      *tramp;\n  ffi_cif   *cif;\n  void     (*fun)(ffi_cif*,void*,void**,void*);\n} ffi_go_closure;\n\nffi_status ffi_prep_go_closure (ffi_go_closure*, ffi_cif *,\n\t\t\t\tvoid (*fun)(ffi_cif*,void*,void**,void*));\n\nvoid ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,\n\t\t  void **avalue, void *closure);\n\n#endif /* FFI_GO_CLOSURES */\n\n/* ---- Public interface definition -------------------------------------- */\n\nffi_status ffi_prep_cif(ffi_cif *cif,\n\t\t\tffi_abi abi,\n\t\t\tunsigned int nargs,\n\t\t\tffi_type *rtype,\n\t\t\tffi_type **atypes);\n\nffi_status ffi_prep_cif_var(ffi_cif *cif,\n\t\t\t    ffi_abi abi,\n\t\t\t    unsigned int nfixedargs,\n\t\t\t    unsigned int ntotalargs,\n\t\t\t    ffi_type *rtype,\n\t\t\t    ffi_type **atypes);\n\nvoid ffi_call(ffi_cif *cif,\n\t      void (*fn)(void),\n\t      void *rvalue,\n\t      void **avalue);\n\nffi_status ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type,\n\t\t\t\t   size_t *offsets);\n\n/* Useful for eliminating compiler warnings.  */\n#define FFI_FN(f) ((void (*)(void))f)\n\n/* ---- Definitions shared with assembly code ---------------------------- */\n\n#endif\n\n/* If these change, update src/mips/ffitarget.h. */\n#define FFI_TYPE_VOID       0    \n#define FFI_TYPE_INT        1\n#define FFI_TYPE_FLOAT      2    \n#define FFI_TYPE_DOUBLE     3\n#if 0\n#define FFI_TYPE_LONGDOUBLE 4\n#else\n#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE\n#endif\n#define FFI_TYPE_UINT8      5   \n#define FFI_TYPE_SINT8      6\n#define FFI_TYPE_UINT16     7 \n#define FFI_TYPE_SINT16     8\n#define FFI_TYPE_UINT32     9\n#define FFI_TYPE_SINT32     10\n#define FFI_TYPE_UINT64     11\n#define FFI_TYPE_SINT64     12\n#define FFI_TYPE_STRUCT     13\n#define FFI_TYPE_POINTER    14\n#define FFI_TYPE_COMPLEX    15\n\n/* This should always refer to the last type code (for sanity checks).  */\n#define FFI_TYPE_LAST       FFI_TYPE_COMPLEX\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "Extensions/JPLibffi/libffi/ffi_arm64.h",
    "content": "/* -----------------------------------------------------------------*-C-*-\n   libffi 3.99999 - Copyright (c) 2011, 2014 Anthony Green\n                    - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.\n\n   Permission is hereby granted, free of charge, to any person\n   obtaining a copy of this software and associated documentation\n   files (the ``Software''), to deal in the Software without\n   restriction, including without limitation the rights to use, copy,\n   modify, merge, publish, distribute, sublicense, and/or sell copies\n   of the Software, and to permit persons to whom the Software is\n   furnished to do so, subject to the following conditions:\n\n   The above copyright notice and this permission notice shall be\n   included in all copies or substantial portions of the Software.\n\n   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,\n   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n   DEALINGS IN THE SOFTWARE.\n\n   ----------------------------------------------------------------------- */\n\n/* -------------------------------------------------------------------\n   Most of the API is documented in doc/libffi.texi.\n\n   The raw API is designed to bypass some of the argument packing and\n   unpacking on architectures for which it can be avoided.  Routines\n   are provided to emulate the raw API if the underlying platform\n   doesn't allow faster implementation.\n\n   More details on the raw API can be found in:\n\n   http://gcc.gnu.org/ml/java/1999-q3/msg00138.html\n\n   and\n\n   http://gcc.gnu.org/ml/java/1999-q3/msg00174.html\n   -------------------------------------------------------------------- */\n\n#ifndef LIBFFI_H\n#define LIBFFI_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Specify which architecture libffi is configured for. */\n#ifndef AARCH64\n#define AARCH64\n#endif\n\n/* ---- System configuration information --------------------------------- */\n\n#include \"ffitarget.h\"\n\n#ifndef LIBFFI_ASM\n\n#if defined(_MSC_VER) && !defined(__clang__)\n#define __attribute__(X)\n#endif\n\n#include <stddef.h>\n#include <limits.h>\n\n/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).\n   But we can find it either under the correct ANSI name, or under GNU\n   C's internal name.  */\n\n#define FFI_64_BIT_MAX 9223372036854775807\n\n#ifdef LONG_LONG_MAX\n# define FFI_LONG_LONG_MAX LONG_LONG_MAX\n#else\n# ifdef LLONG_MAX\n#  define FFI_LONG_LONG_MAX LLONG_MAX\n#  ifdef _AIX52 /* or newer has C99 LLONG_MAX */\n#   undef FFI_64_BIT_MAX\n#   define FFI_64_BIT_MAX 9223372036854775807LL\n#  endif /* _AIX52 or newer */\n# else\n#  ifdef __GNUC__\n#   define FFI_LONG_LONG_MAX __LONG_LONG_MAX__\n#  endif\n#  ifdef _AIX /* AIX 5.1 and earlier have LONGLONG_MAX */\n#   ifndef __PPC64__\n#    if defined (__IBMC__) || defined (__IBMCPP__)\n#     define FFI_LONG_LONG_MAX LONGLONG_MAX\n#    endif\n#   endif /* __PPC64__ */\n#   undef  FFI_64_BIT_MAX\n#   define FFI_64_BIT_MAX 9223372036854775807LL\n#  endif\n# endif\n#endif\n\n/* The closure code assumes that this works on pointers, i.e. a size_t\n   can hold a pointer.  */\n\ntypedef struct _ffi_type\n{\n  size_t size;\n  unsigned short alignment;\n  unsigned short type;\n  struct _ffi_type **elements;\n} ffi_type;\n\n#ifndef LIBFFI_HIDE_BASIC_TYPES\n#if SCHAR_MAX == 127\n# define ffi_type_uchar                ffi_type_uint8\n# define ffi_type_schar                ffi_type_sint8\n#else\n #error \"char size not supported\"\n#endif\n\n#if SHRT_MAX == 32767\n# define ffi_type_ushort       ffi_type_uint16\n# define ffi_type_sshort       ffi_type_sint16\n#elif SHRT_MAX == 2147483647\n# define ffi_type_ushort       ffi_type_uint32\n# define ffi_type_sshort       ffi_type_sint32\n#else\n #error \"short size not supported\"\n#endif\n\n#if INT_MAX == 32767\n# define ffi_type_uint         ffi_type_uint16\n# define ffi_type_sint         ffi_type_sint16\n#elif INT_MAX == 2147483647\n# define ffi_type_uint         ffi_type_uint32\n# define ffi_type_sint         ffi_type_sint32\n#elif INT_MAX == 9223372036854775807\n# define ffi_type_uint         ffi_type_uint64\n# define ffi_type_sint         ffi_type_sint64\n#else\n #error \"int size not supported\"\n#endif\n\n#if LONG_MAX == 2147483647\n# if FFI_LONG_LONG_MAX != FFI_64_BIT_MAX\n #error \"no 64-bit data type supported\"\n# endif\n#elif LONG_MAX != FFI_64_BIT_MAX\n #error \"long size not supported\"\n#endif\n\n#if LONG_MAX == 2147483647\n# define ffi_type_ulong        ffi_type_uint32\n# define ffi_type_slong        ffi_type_sint32\n#elif LONG_MAX == FFI_64_BIT_MAX\n# define ffi_type_ulong        ffi_type_uint64\n# define ffi_type_slong        ffi_type_sint64\n#else\n #error \"long size not supported\"\n#endif\n\n/* Need minimal decorations for DLLs to works on Windows.  GCC has\n   autoimport and autoexport.  Rely on Libtool to help MSVC export\n   from a DLL, but always declare data to be imported for MSVC\n   clients.  This costs an extra indirection for MSVC clients using\n   the static version of the library, but don't worry about that.\n   Besides, as a workaround, they can define FFI_BUILDING if they\n   *know* they are going to link with the static library.  */\n#if defined _MSC_VER && !defined FFI_BUILDING\n#define FFI_EXTERN extern __declspec(dllimport)\n#else\n#define FFI_EXTERN extern\n#endif\n\n/* These are defined in types.c.  */\nFFI_EXTERN ffi_type ffi_type_void;\nFFI_EXTERN ffi_type ffi_type_uint8;\nFFI_EXTERN ffi_type ffi_type_sint8;\nFFI_EXTERN ffi_type ffi_type_uint16;\nFFI_EXTERN ffi_type ffi_type_sint16;\nFFI_EXTERN ffi_type ffi_type_uint32;\nFFI_EXTERN ffi_type ffi_type_sint32;\nFFI_EXTERN ffi_type ffi_type_uint64;\nFFI_EXTERN ffi_type ffi_type_sint64;\nFFI_EXTERN ffi_type ffi_type_float;\nFFI_EXTERN ffi_type ffi_type_double;\nFFI_EXTERN ffi_type ffi_type_pointer;\n\n#if 0\nFFI_EXTERN ffi_type ffi_type_longdouble;\n#else\n#define ffi_type_longdouble ffi_type_double\n#endif\n\n#ifdef FFI_TARGET_HAS_COMPLEX_TYPE\nFFI_EXTERN ffi_type ffi_type_complex_float;\nFFI_EXTERN ffi_type ffi_type_complex_double;\n#if 0\nFFI_EXTERN ffi_type ffi_type_complex_longdouble;\n#else\n#define ffi_type_complex_longdouble ffi_type_complex_double\n#endif\n#endif\n#endif /* LIBFFI_HIDE_BASIC_TYPES */\n\ntypedef enum {\n  FFI_OK = 0,\n  FFI_BAD_TYPEDEF,\n  FFI_BAD_ABI\n} ffi_status;\n\ntypedef struct {\n  ffi_abi abi;\n  unsigned nargs;\n  ffi_type **arg_types;\n  ffi_type *rtype;\n  unsigned bytes;\n  unsigned flags;\n#ifdef FFI_EXTRA_CIF_FIELDS\n  FFI_EXTRA_CIF_FIELDS;\n#endif\n} ffi_cif;\n\n/* ---- Definitions for the raw API -------------------------------------- */\n\n#ifndef FFI_SIZEOF_ARG\n# if LONG_MAX == 2147483647\n#  define FFI_SIZEOF_ARG        4\n# elif LONG_MAX == FFI_64_BIT_MAX\n#  define FFI_SIZEOF_ARG        8\n# endif\n#endif\n\n#ifndef FFI_SIZEOF_JAVA_RAW\n#  define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG\n#endif\n\ntypedef union {\n  ffi_sarg  sint;\n  ffi_arg   uint;\n  float\t    flt;\n  char      data[FFI_SIZEOF_ARG];\n  void*     ptr;\n} ffi_raw;\n\n#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8\n/* This is a special case for mips64/n32 ABI (and perhaps others) where\n   sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8.  */\ntypedef union {\n  signed int\tsint;\n  unsigned int\tuint;\n  float\t\tflt;\n  char\t\tdata[FFI_SIZEOF_JAVA_RAW];\n  void*\t\tptr;\n} ffi_java_raw;\n#else\ntypedef ffi_raw ffi_java_raw;\n#endif\n\n\nvoid ffi_raw_call (ffi_cif *cif,\n\t\t   void (*fn)(void),\n\t\t   void *rvalue,\n\t\t   ffi_raw *avalue);\n\nvoid ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);\nvoid ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);\nsize_t ffi_raw_size (ffi_cif *cif);\n\n/* This is analogous to the raw API, except it uses Java parameter\n   packing, even on 64-bit machines.  I.e. on 64-bit machines longs\n   and doubles are followed by an empty 64-bit word.  */\n\nvoid ffi_java_raw_call (ffi_cif *cif,\n\t\t\tvoid (*fn)(void),\n\t\t\tvoid *rvalue,\n\t\t\tffi_java_raw *avalue);\n\nvoid ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw);\nvoid ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args);\nsize_t ffi_java_raw_size (ffi_cif *cif);\n\n/* ---- Definitions for closures ----------------------------------------- */\n\n#if FFI_CLOSURES\n\n#ifdef _MSC_VER\n__declspec(align(8))\n#endif\ntypedef struct {\n#if 1\n  void *trampoline_table;\n  void *trampoline_table_entry;\n#else\n  char tramp[FFI_TRAMPOLINE_SIZE];\n#endif\n  ffi_cif   *cif;\n  void     (*fun)(ffi_cif*,void*,void**,void*);\n  void      *user_data;\n} ffi_closure\n#ifdef __GNUC__\n    __attribute__((aligned (8)))\n#endif\n    ;\n\n#ifndef __GNUC__\n# ifdef __sgi\n#  pragma pack 0\n# endif\n#endif\n\nvoid *ffi_closure_alloc (size_t size, void **code);\nvoid ffi_closure_free (void *);\n\nffi_status\nffi_prep_closure (ffi_closure*,\n\t\t  ffi_cif *,\n\t\t  void (*fun)(ffi_cif*,void*,void**,void*),\n\t\t  void *user_data)\n  __attribute__((deprecated (\"use ffi_prep_closure_loc instead\")));\n\nffi_status\nffi_prep_closure_loc (ffi_closure*,\n\t\t      ffi_cif *,\n\t\t      void (*fun)(ffi_cif*,void*,void**,void*),\n\t\t      void *user_data,\n\t\t      void*codeloc);\n\n#ifdef __sgi\n# pragma pack 8\n#endif\ntypedef struct {\n#if 1\n  void *trampoline_table;\n  void *trampoline_table_entry;\n#else\n  char tramp[FFI_TRAMPOLINE_SIZE];\n#endif\n  ffi_cif   *cif;\n\n#if !FFI_NATIVE_RAW_API\n\n  /* If this is enabled, then a raw closure has the same layout \n     as a regular closure.  We use this to install an intermediate \n     handler to do the transaltion, void** -> ffi_raw*.  */\n\n  void     (*translate_args)(ffi_cif*,void*,void**,void*);\n  void      *this_closure;\n\n#endif\n\n  void     (*fun)(ffi_cif*,void*,ffi_raw*,void*);\n  void      *user_data;\n\n} ffi_raw_closure;\n\ntypedef struct {\n#if 1\n  void *trampoline_table;\n  void *trampoline_table_entry;\n#else\n  char tramp[FFI_TRAMPOLINE_SIZE];\n#endif\n\n  ffi_cif   *cif;\n\n#if !FFI_NATIVE_RAW_API\n\n  /* If this is enabled, then a raw closure has the same layout \n     as a regular closure.  We use this to install an intermediate \n     handler to do the translation, void** -> ffi_raw*.  */\n\n  void     (*translate_args)(ffi_cif*,void*,void**,void*);\n  void      *this_closure;\n\n#endif\n\n  void     (*fun)(ffi_cif*,void*,ffi_java_raw*,void*);\n  void      *user_data;\n\n} ffi_java_raw_closure;\n\nffi_status\nffi_prep_raw_closure (ffi_raw_closure*,\n\t\t      ffi_cif *cif,\n\t\t      void (*fun)(ffi_cif*,void*,ffi_raw*,void*),\n\t\t      void *user_data);\n\nffi_status\nffi_prep_raw_closure_loc (ffi_raw_closure*,\n\t\t\t  ffi_cif *cif,\n\t\t\t  void (*fun)(ffi_cif*,void*,ffi_raw*,void*),\n\t\t\t  void *user_data,\n\t\t\t  void *codeloc);\n\nffi_status\nffi_prep_java_raw_closure (ffi_java_raw_closure*,\n\t\t           ffi_cif *cif,\n\t\t           void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),\n\t\t           void *user_data);\n\nffi_status\nffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,\n\t\t\t       ffi_cif *cif,\n\t\t\t       void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),\n\t\t\t       void *user_data,\n\t\t\t       void *codeloc);\n\n#endif /* FFI_CLOSURES */\n\n#if FFI_GO_CLOSURES\n\ntypedef struct {\n  void      *tramp;\n  ffi_cif   *cif;\n  void     (*fun)(ffi_cif*,void*,void**,void*);\n} ffi_go_closure;\n\nffi_status ffi_prep_go_closure (ffi_go_closure*, ffi_cif *,\n\t\t\t\tvoid (*fun)(ffi_cif*,void*,void**,void*));\n\nvoid ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,\n\t\t  void **avalue, void *closure);\n\n#endif /* FFI_GO_CLOSURES */\n\n/* ---- Public interface definition -------------------------------------- */\n\nffi_status ffi_prep_cif(ffi_cif *cif,\n\t\t\tffi_abi abi,\n\t\t\tunsigned int nargs,\n\t\t\tffi_type *rtype,\n\t\t\tffi_type **atypes);\n\nffi_status ffi_prep_cif_var(ffi_cif *cif,\n\t\t\t    ffi_abi abi,\n\t\t\t    unsigned int nfixedargs,\n\t\t\t    unsigned int ntotalargs,\n\t\t\t    ffi_type *rtype,\n\t\t\t    ffi_type **atypes);\n\nvoid ffi_call(ffi_cif *cif,\n\t      void (*fn)(void),\n\t      void *rvalue,\n\t      void **avalue);\n\nffi_status ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type,\n\t\t\t\t   size_t *offsets);\n\n/* Useful for eliminating compiler warnings.  */\n#define FFI_FN(f) ((void (*)(void))f)\n\n/* ---- Definitions shared with assembly code ---------------------------- */\n\n#endif\n\n/* If these change, update src/mips/ffitarget.h. */\n#define FFI_TYPE_VOID       0    \n#define FFI_TYPE_INT        1\n#define FFI_TYPE_FLOAT      2    \n#define FFI_TYPE_DOUBLE     3\n#if 0\n#define FFI_TYPE_LONGDOUBLE 4\n#else\n#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE\n#endif\n#define FFI_TYPE_UINT8      5   \n#define FFI_TYPE_SINT8      6\n#define FFI_TYPE_UINT16     7 \n#define FFI_TYPE_SINT16     8\n#define FFI_TYPE_UINT32     9\n#define FFI_TYPE_SINT32     10\n#define FFI_TYPE_UINT64     11\n#define FFI_TYPE_SINT64     12\n#define FFI_TYPE_STRUCT     13\n#define FFI_TYPE_POINTER    14\n#define FFI_TYPE_COMPLEX    15\n\n/* This should always refer to the last type code (for sanity checks).  */\n#define FFI_TYPE_LAST       FFI_TYPE_COMPLEX\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "Extensions/JPLibffi/libffi/ffi_i386.h",
    "content": "#ifdef __i386__\n\n/* -----------------------------------------------------------------*-C-*-\n   libffi 3.2.1 - Copyright (c) 2011, 2014 Anthony Green\n                    - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.\n\n   Permission is hereby granted, free of charge, to any person\n   obtaining a copy of this software and associated documentation\n   files (the ``Software''), to deal in the Software without\n   restriction, including without limitation the rights to use, copy,\n   modify, merge, publish, distribute, sublicense, and/or sell copies\n   of the Software, and to permit persons to whom the Software is\n   furnished to do so, subject to the following conditions:\n\n   The above copyright notice and this permission notice shall be\n   included in all copies or substantial portions of the Software.\n\n   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,\n   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n   DEALINGS IN THE SOFTWARE.\n\n   ----------------------------------------------------------------------- */\n\n/* -------------------------------------------------------------------\n   The basic API is described in the README file.\n\n   The raw API is designed to bypass some of the argument packing\n   and unpacking on architectures for which it can be avoided.\n\n   The closure API allows interpreted functions to be packaged up\n   inside a C function pointer, so that they can be called as C functions,\n   with no understanding on the client side that they are interpreted.\n   It can also be used in other cases in which it is necessary to package\n   up a user specified parameter and a function pointer as a single\n   function pointer.\n\n   The closure API must be implemented in order to get its functionality,\n   e.g. for use by gij.  Routines are provided to emulate the raw API\n   if the underlying platform doesn't allow faster implementation.\n\n   More details on the raw and cloure API can be found in:\n\n   http://gcc.gnu.org/ml/java/1999-q3/msg00138.html\n\n   and\n\n   http://gcc.gnu.org/ml/java/1999-q3/msg00174.html\n   -------------------------------------------------------------------- */\n\n#ifndef LIBFFI_H\n#define LIBFFI_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Specify which architecture libffi is configured for. */\n#ifndef X86_DARWIN\n#define X86_DARWIN\n#endif\n\n/* ---- System configuration information --------------------------------- */\n\n#include \"ffitarget.h\"\n\n#ifndef LIBFFI_ASM\n\n#if defined(_MSC_VER) && !defined(__clang__)\n#define __attribute__(X)\n#endif\n\n#include <stddef.h>\n#include <limits.h>\n\n/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).\n   But we can find it either under the correct ANSI name, or under GNU\n   C's internal name.  */\n\n#define FFI_64_BIT_MAX 9223372036854775807\n\n#ifdef LONG_LONG_MAX\n# define FFI_LONG_LONG_MAX LONG_LONG_MAX\n#else\n# ifdef LLONG_MAX\n#  define FFI_LONG_LONG_MAX LLONG_MAX\n#  ifdef _AIX52 /* or newer has C99 LLONG_MAX */\n#   undef FFI_64_BIT_MAX\n#   define FFI_64_BIT_MAX 9223372036854775807LL\n#  endif /* _AIX52 or newer */\n# else\n#  ifdef __GNUC__\n#   define FFI_LONG_LONG_MAX __LONG_LONG_MAX__\n#  endif\n#  ifdef _AIX /* AIX 5.1 and earlier have LONGLONG_MAX */\n#   ifndef __PPC64__\n#    if defined (__IBMC__) || defined (__IBMCPP__)\n#     define FFI_LONG_LONG_MAX LONGLONG_MAX\n#    endif\n#   endif /* __PPC64__ */\n#   undef  FFI_64_BIT_MAX\n#   define FFI_64_BIT_MAX 9223372036854775807LL\n#  endif\n# endif\n#endif\n\n/* The closure code assumes that this works on pointers, i.e. a size_t\t*/\n/* can hold a pointer.\t\t\t\t\t\t\t*/\n\ntypedef struct _ffi_type\n{\n  size_t size;\n  unsigned short alignment;\n  unsigned short type;\n  struct _ffi_type **elements;\n} ffi_type;\n\n#ifndef LIBFFI_HIDE_BASIC_TYPES\n#if SCHAR_MAX == 127\n# define ffi_type_uchar                ffi_type_uint8\n# define ffi_type_schar                ffi_type_sint8\n#else\n #error \"char size not supported\"\n#endif\n\n#if SHRT_MAX == 32767\n# define ffi_type_ushort       ffi_type_uint16\n# define ffi_type_sshort       ffi_type_sint16\n#elif SHRT_MAX == 2147483647\n# define ffi_type_ushort       ffi_type_uint32\n# define ffi_type_sshort       ffi_type_sint32\n#else\n #error \"short size not supported\"\n#endif\n\n#if INT_MAX == 32767\n# define ffi_type_uint         ffi_type_uint16\n# define ffi_type_sint         ffi_type_sint16\n#elif INT_MAX == 2147483647\n# define ffi_type_uint         ffi_type_uint32\n# define ffi_type_sint         ffi_type_sint32\n#elif INT_MAX == 9223372036854775807\n# define ffi_type_uint         ffi_type_uint64\n# define ffi_type_sint         ffi_type_sint64\n#else\n #error \"int size not supported\"\n#endif\n\n#if LONG_MAX == 2147483647\n# if FFI_LONG_LONG_MAX != FFI_64_BIT_MAX\n #error \"no 64-bit data type supported\"\n# endif\n#elif LONG_MAX != FFI_64_BIT_MAX\n #error \"long size not supported\"\n#endif\n\n#if LONG_MAX == 2147483647\n# define ffi_type_ulong        ffi_type_uint32\n# define ffi_type_slong        ffi_type_sint32\n#elif LONG_MAX == FFI_64_BIT_MAX\n# define ffi_type_ulong        ffi_type_uint64\n# define ffi_type_slong        ffi_type_sint64\n#else\n #error \"long size not supported\"\n#endif\n\n/* Need minimal decorations for DLLs to works on Windows. */\n/* GCC has autoimport and autoexport.  Rely on Libtool to */\n/* help MSVC export from a DLL, but always declare data   */\n/* to be imported for MSVC clients.  This costs an extra  */\n/* indirection for MSVC clients using the static version  */\n/* of the library, but don't worry about that.  Besides,  */\n/* as a workaround, they can define FFI_BUILDING if they  */\n/* *know* they are going to link with the static library. */\n#if defined _MSC_VER && !defined FFI_BUILDING\n#define FFI_EXTERN extern __declspec(dllimport)\n#else\n#define FFI_EXTERN extern\n#endif\n\n/* These are defined in types.c */\nFFI_EXTERN ffi_type ffi_type_void;\nFFI_EXTERN ffi_type ffi_type_uint8;\nFFI_EXTERN ffi_type ffi_type_sint8;\nFFI_EXTERN ffi_type ffi_type_uint16;\nFFI_EXTERN ffi_type ffi_type_sint16;\nFFI_EXTERN ffi_type ffi_type_uint32;\nFFI_EXTERN ffi_type ffi_type_sint32;\nFFI_EXTERN ffi_type ffi_type_uint64;\nFFI_EXTERN ffi_type ffi_type_sint64;\nFFI_EXTERN ffi_type ffi_type_float;\nFFI_EXTERN ffi_type ffi_type_double;\nFFI_EXTERN ffi_type ffi_type_pointer;\n\n#if 1\nFFI_EXTERN ffi_type ffi_type_longdouble;\n#else\n#define ffi_type_longdouble ffi_type_double\n#endif\n\n#ifdef FFI_TARGET_HAS_COMPLEX_TYPE\nFFI_EXTERN ffi_type ffi_type_complex_float;\nFFI_EXTERN ffi_type ffi_type_complex_double;\n#if 1\nFFI_EXTERN ffi_type ffi_type_complex_longdouble;\n#else\n#define ffi_type_complex_longdouble ffi_type_complex_double\n#endif\n#endif\n#endif /* LIBFFI_HIDE_BASIC_TYPES */\n\ntypedef enum {\n  FFI_OK = 0,\n  FFI_BAD_TYPEDEF,\n  FFI_BAD_ABI\n} ffi_status;\n\ntypedef unsigned FFI_TYPE;\n\ntypedef struct {\n  ffi_abi abi;\n  unsigned nargs;\n  ffi_type **arg_types;\n  ffi_type *rtype;\n  unsigned bytes;\n  unsigned flags;\n#ifdef FFI_EXTRA_CIF_FIELDS\n  FFI_EXTRA_CIF_FIELDS;\n#endif\n} ffi_cif;\n\n#if 0\n/* Used to adjust size/alignment of ffi types.  */\nvoid ffi_prep_types (ffi_abi abi);\n#endif\n\n/* Used internally, but overridden by some architectures */\nffi_status ffi_prep_cif_core(ffi_cif *cif,\n\t\t\t     ffi_abi abi,\n\t\t\t     unsigned int isvariadic,\n\t\t\t     unsigned int nfixedargs,\n\t\t\t     unsigned int ntotalargs,\n\t\t\t     ffi_type *rtype,\n\t\t\t     ffi_type **atypes);\n\n/* ---- Definitions for the raw API -------------------------------------- */\n\n#ifndef FFI_SIZEOF_ARG\n# if LONG_MAX == 2147483647\n#  define FFI_SIZEOF_ARG        4\n# elif LONG_MAX == FFI_64_BIT_MAX\n#  define FFI_SIZEOF_ARG        8\n# endif\n#endif\n\n#ifndef FFI_SIZEOF_JAVA_RAW\n#  define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG\n#endif\n\ntypedef union {\n  ffi_sarg  sint;\n  ffi_arg   uint;\n  float\t    flt;\n  char      data[FFI_SIZEOF_ARG];\n  void*     ptr;\n} ffi_raw;\n\n#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8\n/* This is a special case for mips64/n32 ABI (and perhaps others) where\n   sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8.  */\ntypedef union {\n  signed int\tsint;\n  unsigned int\tuint;\n  float\t\tflt;\n  char\t\tdata[FFI_SIZEOF_JAVA_RAW];\n  void*\t\tptr;\n} ffi_java_raw;\n#else\ntypedef ffi_raw ffi_java_raw;\n#endif\n\n\nvoid ffi_raw_call (ffi_cif *cif,\n\t\t   void (*fn)(void),\n\t\t   void *rvalue,\n\t\t   ffi_raw *avalue);\n\nvoid ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);\nvoid ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);\nsize_t ffi_raw_size (ffi_cif *cif);\n\n/* This is analogous to the raw API, except it uses Java parameter\t*/\n/* packing, even on 64-bit machines.  I.e. on 64-bit machines\t\t*/\n/* longs and doubles are followed by an empty 64-bit word.\t\t*/\n\nvoid ffi_java_raw_call (ffi_cif *cif,\n\t\t\tvoid (*fn)(void),\n\t\t\tvoid *rvalue,\n\t\t\tffi_java_raw *avalue);\n\nvoid ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw);\nvoid ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args);\nsize_t ffi_java_raw_size (ffi_cif *cif);\n\n/* ---- Definitions for closures ----------------------------------------- */\n\n#if FFI_CLOSURES\n\n#ifdef _MSC_VER\n__declspec(align(8))\n#endif\ntypedef struct {\n#if 0\n  void *trampoline_table;\n  void *trampoline_table_entry;\n#else\n  char tramp[FFI_TRAMPOLINE_SIZE];\n#endif\n  ffi_cif   *cif;\n  void     (*fun)(ffi_cif*,void*,void**,void*);\n  void      *user_data;\n#ifdef __GNUC__\n} ffi_closure __attribute__((aligned (8)));\n#else\n} ffi_closure;\n# ifdef __sgi\n#  pragma pack 0\n# endif\n#endif\n\nvoid *ffi_closure_alloc (size_t size, void **code);\nvoid ffi_closure_free (void *);\n\nffi_status\nffi_prep_closure (ffi_closure*,\n\t\t  ffi_cif *,\n\t\t  void (*fun)(ffi_cif*,void*,void**,void*),\n\t\t  void *user_data);\n\nffi_status\nffi_prep_closure_loc (ffi_closure*,\n\t\t      ffi_cif *,\n\t\t      void (*fun)(ffi_cif*,void*,void**,void*),\n\t\t      void *user_data,\n\t\t      void*codeloc);\n\n#ifdef __sgi\n# pragma pack 8\n#endif\ntypedef struct {\n#if 0\n  void *trampoline_table;\n  void *trampoline_table_entry;\n#else\n  char tramp[FFI_TRAMPOLINE_SIZE];\n#endif\n  ffi_cif   *cif;\n\n#if !FFI_NATIVE_RAW_API\n\n  /* if this is enabled, then a raw closure has the same layout \n     as a regular closure.  We use this to install an intermediate \n     handler to do the transaltion, void** -> ffi_raw*. */\n\n  void     (*translate_args)(ffi_cif*,void*,void**,void*);\n  void      *this_closure;\n\n#endif\n\n  void     (*fun)(ffi_cif*,void*,ffi_raw*,void*);\n  void      *user_data;\n\n} ffi_raw_closure;\n\ntypedef struct {\n#if 0\n  void *trampoline_table;\n  void *trampoline_table_entry;\n#else\n  char tramp[FFI_TRAMPOLINE_SIZE];\n#endif\n\n  ffi_cif   *cif;\n\n#if !FFI_NATIVE_RAW_API\n\n  /* if this is enabled, then a raw closure has the same layout \n     as a regular closure.  We use this to install an intermediate \n     handler to do the transaltion, void** -> ffi_raw*. */\n\n  void     (*translate_args)(ffi_cif*,void*,void**,void*);\n  void      *this_closure;\n\n#endif\n\n  void     (*fun)(ffi_cif*,void*,ffi_java_raw*,void*);\n  void      *user_data;\n\n} ffi_java_raw_closure;\n\nffi_status\nffi_prep_raw_closure (ffi_raw_closure*,\n\t\t      ffi_cif *cif,\n\t\t      void (*fun)(ffi_cif*,void*,ffi_raw*,void*),\n\t\t      void *user_data);\n\nffi_status\nffi_prep_raw_closure_loc (ffi_raw_closure*,\n\t\t\t  ffi_cif *cif,\n\t\t\t  void (*fun)(ffi_cif*,void*,ffi_raw*,void*),\n\t\t\t  void *user_data,\n\t\t\t  void *codeloc);\n\nffi_status\nffi_prep_java_raw_closure (ffi_java_raw_closure*,\n\t\t           ffi_cif *cif,\n\t\t           void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),\n\t\t           void *user_data);\n\nffi_status\nffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,\n\t\t\t       ffi_cif *cif,\n\t\t\t       void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),\n\t\t\t       void *user_data,\n\t\t\t       void *codeloc);\n\n#endif /* FFI_CLOSURES */\n\n/* ---- Public interface definition -------------------------------------- */\n\nffi_status ffi_prep_cif(ffi_cif *cif,\n\t\t\tffi_abi abi,\n\t\t\tunsigned int nargs,\n\t\t\tffi_type *rtype,\n\t\t\tffi_type **atypes);\n\nffi_status ffi_prep_cif_var(ffi_cif *cif,\n\t\t\t    ffi_abi abi,\n\t\t\t    unsigned int nfixedargs,\n\t\t\t    unsigned int ntotalargs,\n\t\t\t    ffi_type *rtype,\n\t\t\t    ffi_type **atypes);\n\nvoid ffi_call(ffi_cif *cif,\n\t      void (*fn)(void),\n\t      void *rvalue,\n\t      void **avalue);\n\n/* Useful for eliminating compiler warnings */\n#define FFI_FN(f) ((void (*)(void))f)\n\n/* ---- Definitions shared with assembly code ---------------------------- */\n\n#endif\n\n/* If these change, update src/mips/ffitarget.h. */\n#define FFI_TYPE_VOID       0    \n#define FFI_TYPE_INT        1\n#define FFI_TYPE_FLOAT      2    \n#define FFI_TYPE_DOUBLE     3\n#if 1\n#define FFI_TYPE_LONGDOUBLE 4\n#else\n#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE\n#endif\n#define FFI_TYPE_UINT8      5   \n#define FFI_TYPE_SINT8      6\n#define FFI_TYPE_UINT16     7 \n#define FFI_TYPE_SINT16     8\n#define FFI_TYPE_UINT32     9\n#define FFI_TYPE_SINT32     10\n#define FFI_TYPE_UINT64     11\n#define FFI_TYPE_SINT64     12\n#define FFI_TYPE_STRUCT     13\n#define FFI_TYPE_POINTER    14\n#define FFI_TYPE_COMPLEX    15\n\n/* This should always refer to the last type code (for sanity checks) */\n#define FFI_TYPE_LAST       FFI_TYPE_COMPLEX\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n\n\n#endif\n"
  },
  {
    "path": "Extensions/JPLibffi/libffi/ffi_x86_64.h",
    "content": "/* -----------------------------------------------------------------*-C-*-\n   libffi 3.99999 - Copyright (c) 2011, 2014 Anthony Green\n                    - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc.\n\n   Permission is hereby granted, free of charge, to any person\n   obtaining a copy of this software and associated documentation\n   files (the ``Software''), to deal in the Software without\n   restriction, including without limitation the rights to use, copy,\n   modify, merge, publish, distribute, sublicense, and/or sell copies\n   of the Software, and to permit persons to whom the Software is\n   furnished to do so, subject to the following conditions:\n\n   The above copyright notice and this permission notice shall be\n   included in all copies or substantial portions of the Software.\n\n   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,\n   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n   DEALINGS IN THE SOFTWARE.\n\n   ----------------------------------------------------------------------- */\n\n/* -------------------------------------------------------------------\n   Most of the API is documented in doc/libffi.texi.\n\n   The raw API is designed to bypass some of the argument packing and\n   unpacking on architectures for which it can be avoided.  Routines\n   are provided to emulate the raw API if the underlying platform\n   doesn't allow faster implementation.\n\n   More details on the raw API can be found in:\n\n   http://gcc.gnu.org/ml/java/1999-q3/msg00138.html\n\n   and\n\n   http://gcc.gnu.org/ml/java/1999-q3/msg00174.html\n   -------------------------------------------------------------------- */\n\n#ifndef LIBFFI_H\n#define LIBFFI_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/* Specify which architecture libffi is configured for. */\n#ifndef X86_64\n#define X86_64\n#endif\n\n/* ---- System configuration information --------------------------------- */\n\n#include \"ffitarget.h\"\n\n#ifndef LIBFFI_ASM\n\n#if defined(_MSC_VER) && !defined(__clang__)\n#define __attribute__(X)\n#endif\n\n#include <stddef.h>\n#include <limits.h>\n\n/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example).\n   But we can find it either under the correct ANSI name, or under GNU\n   C's internal name.  */\n\n#define FFI_64_BIT_MAX 9223372036854775807\n\n#ifdef LONG_LONG_MAX\n# define FFI_LONG_LONG_MAX LONG_LONG_MAX\n#else\n# ifdef LLONG_MAX\n#  define FFI_LONG_LONG_MAX LLONG_MAX\n#  ifdef _AIX52 /* or newer has C99 LLONG_MAX */\n#   undef FFI_64_BIT_MAX\n#   define FFI_64_BIT_MAX 9223372036854775807LL\n#  endif /* _AIX52 or newer */\n# else\n#  ifdef __GNUC__\n#   define FFI_LONG_LONG_MAX __LONG_LONG_MAX__\n#  endif\n#  ifdef _AIX /* AIX 5.1 and earlier have LONGLONG_MAX */\n#   ifndef __PPC64__\n#    if defined (__IBMC__) || defined (__IBMCPP__)\n#     define FFI_LONG_LONG_MAX LONGLONG_MAX\n#    endif\n#   endif /* __PPC64__ */\n#   undef  FFI_64_BIT_MAX\n#   define FFI_64_BIT_MAX 9223372036854775807LL\n#  endif\n# endif\n#endif\n\n/* The closure code assumes that this works on pointers, i.e. a size_t\n   can hold a pointer.  */\n\ntypedef struct _ffi_type\n{\n  size_t size;\n  unsigned short alignment;\n  unsigned short type;\n  struct _ffi_type **elements;\n} ffi_type;\n\n#ifndef LIBFFI_HIDE_BASIC_TYPES\n#if SCHAR_MAX == 127\n# define ffi_type_uchar                ffi_type_uint8\n# define ffi_type_schar                ffi_type_sint8\n#else\n #error \"char size not supported\"\n#endif\n\n#if SHRT_MAX == 32767\n# define ffi_type_ushort       ffi_type_uint16\n# define ffi_type_sshort       ffi_type_sint16\n#elif SHRT_MAX == 2147483647\n# define ffi_type_ushort       ffi_type_uint32\n# define ffi_type_sshort       ffi_type_sint32\n#else\n #error \"short size not supported\"\n#endif\n\n#if INT_MAX == 32767\n# define ffi_type_uint         ffi_type_uint16\n# define ffi_type_sint         ffi_type_sint16\n#elif INT_MAX == 2147483647\n# define ffi_type_uint         ffi_type_uint32\n# define ffi_type_sint         ffi_type_sint32\n#elif INT_MAX == 9223372036854775807\n# define ffi_type_uint         ffi_type_uint64\n# define ffi_type_sint         ffi_type_sint64\n#else\n #error \"int size not supported\"\n#endif\n\n#if LONG_MAX == 2147483647\n# if FFI_LONG_LONG_MAX != FFI_64_BIT_MAX\n #error \"no 64-bit data type supported\"\n# endif\n#elif LONG_MAX != FFI_64_BIT_MAX\n #error \"long size not supported\"\n#endif\n\n#if LONG_MAX == 2147483647\n# define ffi_type_ulong        ffi_type_uint32\n# define ffi_type_slong        ffi_type_sint32\n#elif LONG_MAX == FFI_64_BIT_MAX\n# define ffi_type_ulong        ffi_type_uint64\n# define ffi_type_slong        ffi_type_sint64\n#else\n #error \"long size not supported\"\n#endif\n\n/* Need minimal decorations for DLLs to works on Windows.  GCC has\n   autoimport and autoexport.  Rely on Libtool to help MSVC export\n   from a DLL, but always declare data to be imported for MSVC\n   clients.  This costs an extra indirection for MSVC clients using\n   the static version of the library, but don't worry about that.\n   Besides, as a workaround, they can define FFI_BUILDING if they\n   *know* they are going to link with the static library.  */\n#if defined _MSC_VER && !defined FFI_BUILDING\n#define FFI_EXTERN extern __declspec(dllimport)\n#else\n#define FFI_EXTERN extern\n#endif\n\n/* These are defined in types.c.  */\nFFI_EXTERN ffi_type ffi_type_void;\nFFI_EXTERN ffi_type ffi_type_uint8;\nFFI_EXTERN ffi_type ffi_type_sint8;\nFFI_EXTERN ffi_type ffi_type_uint16;\nFFI_EXTERN ffi_type ffi_type_sint16;\nFFI_EXTERN ffi_type ffi_type_uint32;\nFFI_EXTERN ffi_type ffi_type_sint32;\nFFI_EXTERN ffi_type ffi_type_uint64;\nFFI_EXTERN ffi_type ffi_type_sint64;\nFFI_EXTERN ffi_type ffi_type_float;\nFFI_EXTERN ffi_type ffi_type_double;\nFFI_EXTERN ffi_type ffi_type_pointer;\n\n#if 1\nFFI_EXTERN ffi_type ffi_type_longdouble;\n#else\n#define ffi_type_longdouble ffi_type_double\n#endif\n\n#ifdef FFI_TARGET_HAS_COMPLEX_TYPE\nFFI_EXTERN ffi_type ffi_type_complex_float;\nFFI_EXTERN ffi_type ffi_type_complex_double;\n#if 1\nFFI_EXTERN ffi_type ffi_type_complex_longdouble;\n#else\n#define ffi_type_complex_longdouble ffi_type_complex_double\n#endif\n#endif\n#endif /* LIBFFI_HIDE_BASIC_TYPES */\n\ntypedef enum {\n  FFI_OK = 0,\n  FFI_BAD_TYPEDEF,\n  FFI_BAD_ABI\n} ffi_status;\n\ntypedef struct {\n  ffi_abi abi;\n  unsigned nargs;\n  ffi_type **arg_types;\n  ffi_type *rtype;\n  unsigned bytes;\n  unsigned flags;\n#ifdef FFI_EXTRA_CIF_FIELDS\n  FFI_EXTRA_CIF_FIELDS;\n#endif\n} ffi_cif;\n\n/* ---- Definitions for the raw API -------------------------------------- */\n\n#ifndef FFI_SIZEOF_ARG\n# if LONG_MAX == 2147483647\n#  define FFI_SIZEOF_ARG        4\n# elif LONG_MAX == FFI_64_BIT_MAX\n#  define FFI_SIZEOF_ARG        8\n# endif\n#endif\n\n#ifndef FFI_SIZEOF_JAVA_RAW\n#  define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG\n#endif\n\ntypedef union {\n  ffi_sarg  sint;\n  ffi_arg   uint;\n  float\t    flt;\n  char      data[FFI_SIZEOF_ARG];\n  void*     ptr;\n} ffi_raw;\n\n#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8\n/* This is a special case for mips64/n32 ABI (and perhaps others) where\n   sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8.  */\ntypedef union {\n  signed int\tsint;\n  unsigned int\tuint;\n  float\t\tflt;\n  char\t\tdata[FFI_SIZEOF_JAVA_RAW];\n  void*\t\tptr;\n} ffi_java_raw;\n#else\ntypedef ffi_raw ffi_java_raw;\n#endif\n\n\nvoid ffi_raw_call (ffi_cif *cif,\n\t\t   void (*fn)(void),\n\t\t   void *rvalue,\n\t\t   ffi_raw *avalue);\n\nvoid ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw);\nvoid ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args);\nsize_t ffi_raw_size (ffi_cif *cif);\n\n/* This is analogous to the raw API, except it uses Java parameter\n   packing, even on 64-bit machines.  I.e. on 64-bit machines longs\n   and doubles are followed by an empty 64-bit word.  */\n\nvoid ffi_java_raw_call (ffi_cif *cif,\n\t\t\tvoid (*fn)(void),\n\t\t\tvoid *rvalue,\n\t\t\tffi_java_raw *avalue);\n\nvoid ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw);\nvoid ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args);\nsize_t ffi_java_raw_size (ffi_cif *cif);\n\n/* ---- Definitions for closures ----------------------------------------- */\n\n#if FFI_CLOSURES\n\n#ifdef _MSC_VER\n__declspec(align(8))\n#endif\ntypedef struct {\n#if 0\n  void *trampoline_table;\n  void *trampoline_table_entry;\n#else\n  char tramp[FFI_TRAMPOLINE_SIZE];\n#endif\n  ffi_cif   *cif;\n  void     (*fun)(ffi_cif*,void*,void**,void*);\n  void      *user_data;\n} ffi_closure\n#ifdef __GNUC__\n    __attribute__((aligned (8)))\n#endif\n    ;\n\n#ifndef __GNUC__\n# ifdef __sgi\n#  pragma pack 0\n# endif\n#endif\n\nvoid *ffi_closure_alloc (size_t size, void **code);\nvoid ffi_closure_free (void *);\n\nffi_status\nffi_prep_closure (ffi_closure*,\n\t\t  ffi_cif *,\n\t\t  void (*fun)(ffi_cif*,void*,void**,void*),\n\t\t  void *user_data)\n  __attribute__((deprecated (\"use ffi_prep_closure_loc instead\")));\n\nffi_status\nffi_prep_closure_loc (ffi_closure*,\n\t\t      ffi_cif *,\n\t\t      void (*fun)(ffi_cif*,void*,void**,void*),\n\t\t      void *user_data,\n\t\t      void*codeloc);\n\n#ifdef __sgi\n# pragma pack 8\n#endif\ntypedef struct {\n#if 0\n  void *trampoline_table;\n  void *trampoline_table_entry;\n#else\n  char tramp[FFI_TRAMPOLINE_SIZE];\n#endif\n  ffi_cif   *cif;\n\n#if !FFI_NATIVE_RAW_API\n\n  /* If this is enabled, then a raw closure has the same layout \n     as a regular closure.  We use this to install an intermediate \n     handler to do the transaltion, void** -> ffi_raw*.  */\n\n  void     (*translate_args)(ffi_cif*,void*,void**,void*);\n  void      *this_closure;\n\n#endif\n\n  void     (*fun)(ffi_cif*,void*,ffi_raw*,void*);\n  void      *user_data;\n\n} ffi_raw_closure;\n\ntypedef struct {\n#if 0\n  void *trampoline_table;\n  void *trampoline_table_entry;\n#else\n  char tramp[FFI_TRAMPOLINE_SIZE];\n#endif\n\n  ffi_cif   *cif;\n\n#if !FFI_NATIVE_RAW_API\n\n  /* If this is enabled, then a raw closure has the same layout \n     as a regular closure.  We use this to install an intermediate \n     handler to do the translation, void** -> ffi_raw*.  */\n\n  void     (*translate_args)(ffi_cif*,void*,void**,void*);\n  void      *this_closure;\n\n#endif\n\n  void     (*fun)(ffi_cif*,void*,ffi_java_raw*,void*);\n  void      *user_data;\n\n} ffi_java_raw_closure;\n\nffi_status\nffi_prep_raw_closure (ffi_raw_closure*,\n\t\t      ffi_cif *cif,\n\t\t      void (*fun)(ffi_cif*,void*,ffi_raw*,void*),\n\t\t      void *user_data);\n\nffi_status\nffi_prep_raw_closure_loc (ffi_raw_closure*,\n\t\t\t  ffi_cif *cif,\n\t\t\t  void (*fun)(ffi_cif*,void*,ffi_raw*,void*),\n\t\t\t  void *user_data,\n\t\t\t  void *codeloc);\n\nffi_status\nffi_prep_java_raw_closure (ffi_java_raw_closure*,\n\t\t           ffi_cif *cif,\n\t\t           void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),\n\t\t           void *user_data);\n\nffi_status\nffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,\n\t\t\t       ffi_cif *cif,\n\t\t\t       void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),\n\t\t\t       void *user_data,\n\t\t\t       void *codeloc);\n\n#endif /* FFI_CLOSURES */\n\n#if FFI_GO_CLOSURES\n\ntypedef struct {\n  void      *tramp;\n  ffi_cif   *cif;\n  void     (*fun)(ffi_cif*,void*,void**,void*);\n} ffi_go_closure;\n\nffi_status ffi_prep_go_closure (ffi_go_closure*, ffi_cif *,\n\t\t\t\tvoid (*fun)(ffi_cif*,void*,void**,void*));\n\nvoid ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,\n\t\t  void **avalue, void *closure);\n\n#endif /* FFI_GO_CLOSURES */\n\n/* ---- Public interface definition -------------------------------------- */\n\nffi_status ffi_prep_cif(ffi_cif *cif,\n\t\t\tffi_abi abi,\n\t\t\tunsigned int nargs,\n\t\t\tffi_type *rtype,\n\t\t\tffi_type **atypes);\n\nffi_status ffi_prep_cif_var(ffi_cif *cif,\n\t\t\t    ffi_abi abi,\n\t\t\t    unsigned int nfixedargs,\n\t\t\t    unsigned int ntotalargs,\n\t\t\t    ffi_type *rtype,\n\t\t\t    ffi_type **atypes);\n\nvoid ffi_call(ffi_cif *cif,\n\t      void (*fn)(void),\n\t      void *rvalue,\n\t      void **avalue);\n\nffi_status ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type,\n\t\t\t\t   size_t *offsets);\n\n/* Useful for eliminating compiler warnings.  */\n#define FFI_FN(f) ((void (*)(void))f)\n\n/* ---- Definitions shared with assembly code ---------------------------- */\n\n#endif\n\n/* If these change, update src/mips/ffitarget.h. */\n#define FFI_TYPE_VOID       0    \n#define FFI_TYPE_INT        1\n#define FFI_TYPE_FLOAT      2    \n#define FFI_TYPE_DOUBLE     3\n#if 1\n#define FFI_TYPE_LONGDOUBLE 4\n#else\n#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE\n#endif\n#define FFI_TYPE_UINT8      5   \n#define FFI_TYPE_SINT8      6\n#define FFI_TYPE_UINT16     7 \n#define FFI_TYPE_SINT16     8\n#define FFI_TYPE_UINT32     9\n#define FFI_TYPE_SINT32     10\n#define FFI_TYPE_UINT64     11\n#define FFI_TYPE_SINT64     12\n#define FFI_TYPE_STRUCT     13\n#define FFI_TYPE_POINTER    14\n#define FFI_TYPE_COMPLEX    15\n\n/* This should always refer to the last type code (for sanity checks).  */\n#define FFI_TYPE_LAST       FFI_TYPE_COMPLEX\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "Extensions/JPLibffi/libffi/ffitarget.h",
    "content": "#ifdef __arm64__\n\n#include \"ffitarget_arm64.h\"\n\n\n#endif\n#ifdef __i386__\n\n#include \"ffitarget_i386.h\"\n\n\n#endif\n#ifdef __arm__\n\n#include \"ffitarget_arm.h\"\n\n\n#endif\n#ifdef __x86_64__\n\n#include \"ffitarget_x86_64.h\"\n\n\n#endif\n"
  },
  {
    "path": "Extensions/JPLibffi/libffi/ffitarget_arm.h",
    "content": "/* -----------------------------------------------------------------*-C-*-\n   ffitarget.h - Copyright (c) 2012  Anthony Green\n                 Copyright (c) 2010  CodeSourcery\n                 Copyright (c) 1996-2003  Red Hat, Inc.\n\n   Target configuration macros for ARM.\n\n   Permission is hereby granted, free of charge, to any person obtaining\n   a copy of this software and associated documentation files (the\n   ``Software''), to deal in the Software without restriction, including\n   without limitation the rights to use, copy, modify, merge, publish,\n   distribute, sublicense, and/or sell copies of the Software, and to\n   permit persons to whom the Software is furnished to do so, subject to\n   the following conditions:\n\n   The above copyright notice and this permission notice shall be included\n   in all copies or substantial portions of the Software.\n\n   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,\n   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n   DEALINGS IN THE SOFTWARE.\n\n   ----------------------------------------------------------------------- */\n\n#ifndef LIBFFI_TARGET_H\n#define LIBFFI_TARGET_H\n\n#ifndef LIBFFI_H\n#error \"Please do not include ffitarget.h directly into your source.  Use ffi.h instead.\"\n#endif\n\n#ifndef LIBFFI_ASM\ntypedef unsigned long          ffi_arg;\ntypedef signed long            ffi_sarg;\n\ntypedef enum ffi_abi {\n  FFI_FIRST_ABI = 0,\n  FFI_SYSV,\n  FFI_VFP,\n  FFI_LAST_ABI,\n#ifdef __ARM_PCS_VFP\n  FFI_DEFAULT_ABI = FFI_VFP,\n#else\n  FFI_DEFAULT_ABI = FFI_SYSV,\n#endif\n} ffi_abi;\n#endif\n\n#define FFI_EXTRA_CIF_FIELDS\t\t\t\\\n  int vfp_used;\t\t\t\t\t\\\n  unsigned short vfp_reg_free, vfp_nargs;\t\\\n  signed char vfp_args[16]\t\t\t\\\n\n#define FFI_TARGET_SPECIFIC_VARIADIC\n#define FFI_TARGET_HAS_COMPLEX_TYPE\n\n/* ---- Definitions for closures ----------------------------------------- */\n\n#define FFI_CLOSURES 1\n#define FFI_GO_CLOSURES 1\n#define FFI_NATIVE_RAW_API 0\n\n#if defined (FFI_EXEC_TRAMPOLINE_TABLE) && FFI_EXEC_TRAMPOLINE_TABLE\n\n#ifdef __MACH__\n#define FFI_TRAMPOLINE_SIZE 12\n#define FFI_TRAMPOLINE_CLOSURE_OFFSET 8\n#else\n#error \"No trampoline table implementation\"\n#endif\n\n#else\n#define FFI_TRAMPOLINE_SIZE 12\n#define FFI_TRAMPOLINE_CLOSURE_OFFSET FFI_TRAMPOLINE_SIZE\n#endif\n\n#endif\n"
  },
  {
    "path": "Extensions/JPLibffi/libffi/ffitarget_arm64.h",
    "content": "/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd.\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n``Software''), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */\n\n#ifndef LIBFFI_TARGET_H\n#define LIBFFI_TARGET_H\n\n#ifndef LIBFFI_H\n#error \"Please do not include ffitarget.h directly into your source.  Use ffi.h instead.\"\n#endif\n\n#ifndef LIBFFI_ASM\n#ifdef __ILP32__\n#define FFI_SIZEOF_ARG 8\n#define FFI_SIZEOF_JAVA_RAW  4\ntypedef unsigned long long ffi_arg;\ntypedef signed long long ffi_sarg;\n#else\ntypedef unsigned long ffi_arg;\ntypedef signed long ffi_sarg;\n#endif\n\ntypedef enum ffi_abi\n  {\n    FFI_FIRST_ABI = 0,\n    FFI_SYSV,\n    FFI_LAST_ABI,\n    FFI_DEFAULT_ABI = FFI_SYSV\n  } ffi_abi;\n#endif\n\n/* ---- Definitions for closures ----------------------------------------- */\n\n#define FFI_CLOSURES 1\n#define FFI_NATIVE_RAW_API 0\n\n#if defined (FFI_EXEC_TRAMPOLINE_TABLE) && FFI_EXEC_TRAMPOLINE_TABLE\n\n#ifdef __MACH__\n#define FFI_TRAMPOLINE_SIZE 16\n#define FFI_TRAMPOLINE_CLOSURE_OFFSET 16\n#else\n#error \"No trampoline table implementation\"\n#endif\n\n#else\n#define FFI_TRAMPOLINE_SIZE 24\n#define FFI_TRAMPOLINE_CLOSURE_OFFSET FFI_TRAMPOLINE_SIZE\n#endif\n\n/* ---- Internal ---- */\n\n#if defined (__APPLE__)\n#define FFI_TARGET_SPECIFIC_VARIADIC\n#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_nfixedargs\n#else\n/* iOS reserves x18 for the system.  Disable Go closures until\n   a new static chain is chosen.  */\n#define FFI_GO_CLOSURES 1\n#endif\n\n#define FFI_TARGET_HAS_COMPLEX_TYPE\n\n#endif\n"
  },
  {
    "path": "Extensions/JPLibffi/libffi/ffitarget_i386.h",
    "content": "#ifdef __i386__\n\n/* -----------------------------------------------------------------*-C-*-\n   ffitarget.h - Copyright (c) 2012, 2014  Anthony Green\n                 Copyright (c) 1996-2003, 2010  Red Hat, Inc.\n                 Copyright (C) 2008  Free Software Foundation, Inc.\n\n   Target configuration macros for x86 and x86-64.\n\n   Permission is hereby granted, free of charge, to any person obtaining\n   a copy of this software and associated documentation files (the\n   ``Software''), to deal in the Software without restriction, including\n   without limitation the rights to use, copy, modify, merge, publish,\n   distribute, sublicense, and/or sell copies of the Software, and to\n   permit persons to whom the Software is furnished to do so, subject to\n   the following conditions:\n\n   The above copyright notice and this permission notice shall be included\n   in all copies or substantial portions of the Software.\n\n   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,\n   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n   DEALINGS IN THE SOFTWARE.\n\n   ----------------------------------------------------------------------- */\n\n#ifndef LIBFFI_TARGET_H\n#define LIBFFI_TARGET_H\n\n#ifndef LIBFFI_H\n#error \"Please do not include ffitarget.h directly into your source.  Use ffi.h instead.\"\n#endif\n\n/* ---- System specific configurations ----------------------------------- */\n\n/* For code common to all platforms on x86 and x86_64. */\n#define X86_ANY\n\n#if defined (X86_64) && defined (__i386__)\n#undef X86_64\n#define X86\n#endif\n\n#ifdef X86_WIN64\n#define FFI_SIZEOF_ARG 8\n#define USE_BUILTIN_FFS 0 /* not yet implemented in mingw-64 */\n#endif\n\n#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION\n#define FFI_TARGET_HAS_COMPLEX_TYPE\n\n/* ---- Generic type definitions ----------------------------------------- */\n\n#ifndef LIBFFI_ASM\n#ifdef X86_WIN64\n#ifdef _MSC_VER\ntypedef unsigned __int64       ffi_arg;\ntypedef __int64                ffi_sarg;\n#else\ntypedef unsigned long long     ffi_arg;\ntypedef long long              ffi_sarg;\n#endif\n#else\n#if defined __x86_64__ && defined __ILP32__\n#define FFI_SIZEOF_ARG 8\n#define FFI_SIZEOF_JAVA_RAW  4\ntypedef unsigned long long     ffi_arg;\ntypedef long long              ffi_sarg;\n#else\ntypedef unsigned long          ffi_arg;\ntypedef signed long            ffi_sarg;\n#endif\n#endif\n\ntypedef enum ffi_abi {\n  FFI_FIRST_ABI = 0,\n\n  /* ---- Intel x86 Win32 ---------- */\n#ifdef X86_WIN32\n  FFI_SYSV,\n  FFI_STDCALL,\n  FFI_THISCALL,\n  FFI_FASTCALL,\n  FFI_MS_CDECL,\n  FFI_PASCAL,\n  FFI_REGISTER,\n  FFI_LAST_ABI,\n#ifdef _MSC_VER\n  FFI_DEFAULT_ABI = FFI_MS_CDECL\n#else\n  FFI_DEFAULT_ABI = FFI_SYSV\n#endif\n\n#elif defined(X86_WIN64)\n  FFI_WIN64,\n  FFI_LAST_ABI,\n  FFI_DEFAULT_ABI = FFI_WIN64\n\n#else\n  /* ---- Intel x86 and AMD x86-64 - */\n  FFI_SYSV,\n  FFI_UNIX64,   /* Unix variants all use the same ABI for x86-64  */\n  FFI_THISCALL,\n  FFI_FASTCALL,\n  FFI_STDCALL,\n  FFI_PASCAL,\n  FFI_REGISTER,\n  FFI_LAST_ABI,\n#if defined(__i386__) || defined(__i386)\n  FFI_DEFAULT_ABI = FFI_SYSV\n#else\n  FFI_DEFAULT_ABI = FFI_UNIX64\n#endif\n#endif\n} ffi_abi;\n#endif\n\n/* ---- Definitions for closures ----------------------------------------- */\n\n#define FFI_CLOSURES 1\n#define FFI_TYPE_SMALL_STRUCT_1B (FFI_TYPE_LAST + 1)\n#define FFI_TYPE_SMALL_STRUCT_2B (FFI_TYPE_LAST + 2)\n#define FFI_TYPE_SMALL_STRUCT_4B (FFI_TYPE_LAST + 3)\n#define FFI_TYPE_MS_STRUCT       (FFI_TYPE_LAST + 4)\n\n#if defined (X86_64) || (defined (__x86_64__) && defined (X86_DARWIN))\n#define FFI_TRAMPOLINE_SIZE 24\n#define FFI_NATIVE_RAW_API 0\n#else\n#ifdef X86_WIN32\n#define FFI_TRAMPOLINE_SIZE 52\n#else\n#ifdef X86_WIN64\n#define FFI_TRAMPOLINE_SIZE 29\n#define FFI_NATIVE_RAW_API 0\n#define FFI_NO_RAW_API 1\n#else\n#define FFI_TRAMPOLINE_SIZE 10\n#endif\n#endif\n#ifndef X86_WIN64\n#define FFI_NATIVE_RAW_API 1  /* x86 has native raw api support */\n#endif\n#endif\n\n#endif\n\n\n\n#endif"
  },
  {
    "path": "Extensions/JPLibffi/libffi/ffitarget_x86_64.h",
    "content": "/* -----------------------------------------------------------------*-C-*-\n   ffitarget.h - Copyright (c) 2012, 2014  Anthony Green\n                 Copyright (c) 1996-2003, 2010  Red Hat, Inc.\n                 Copyright (C) 2008  Free Software Foundation, Inc.\n\n   Target configuration macros for x86 and x86-64.\n\n   Permission is hereby granted, free of charge, to any person obtaining\n   a copy of this software and associated documentation files (the\n   ``Software''), to deal in the Software without restriction, including\n   without limitation the rights to use, copy, modify, merge, publish,\n   distribute, sublicense, and/or sell copies of the Software, and to\n   permit persons to whom the Software is furnished to do so, subject to\n   the following conditions:\n\n   The above copyright notice and this permission notice shall be included\n   in all copies or substantial portions of the Software.\n\n   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,\n   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n   DEALINGS IN THE SOFTWARE.\n\n   ----------------------------------------------------------------------- */\n\n#ifndef LIBFFI_TARGET_H\n#define LIBFFI_TARGET_H\n\n#ifndef LIBFFI_H\n#error \"Please do not include ffitarget.h directly into your source.  Use ffi.h instead.\"\n#endif\n\n/* ---- System specific configurations ----------------------------------- */\n\n/* For code common to all platforms on x86 and x86_64. */\n#define X86_ANY\n\n#if defined (X86_64) && defined (__i386__)\n#undef X86_64\n#define X86\n#endif\n\n#ifdef X86_WIN64\n#define FFI_SIZEOF_ARG 8\n#define USE_BUILTIN_FFS 0 /* not yet implemented in mingw-64 */\n#endif\n\n#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION\n#ifndef _MSC_VER\n#define FFI_TARGET_HAS_COMPLEX_TYPE\n#endif\n\n/* ---- Generic type definitions ----------------------------------------- */\n\n#ifndef LIBFFI_ASM\n#ifdef X86_WIN64\n#ifdef _MSC_VER\ntypedef unsigned __int64       ffi_arg;\ntypedef __int64                ffi_sarg;\n#else\ntypedef unsigned long long     ffi_arg;\ntypedef long long              ffi_sarg;\n#endif\n#else\n#if defined __x86_64__ && defined __ILP32__\n#define FFI_SIZEOF_ARG 8\n#define FFI_SIZEOF_JAVA_RAW  4\ntypedef unsigned long long     ffi_arg;\ntypedef long long              ffi_sarg;\n#else\ntypedef unsigned long          ffi_arg;\ntypedef signed long            ffi_sarg;\n#endif\n#endif\n\ntypedef enum ffi_abi {\n#if defined(X86_WIN64)\n  FFI_FIRST_ABI = 0,\n  FFI_WIN64,\n  FFI_LAST_ABI,\n  FFI_DEFAULT_ABI = FFI_WIN64\n\n#elif defined(X86_64) || (defined (__x86_64__) && defined (X86_DARWIN))\n  FFI_FIRST_ABI = 1,\n  FFI_UNIX64,\n  FFI_WIN64,\n  FFI_EFI64 = FFI_WIN64,\n  FFI_LAST_ABI,\n  FFI_DEFAULT_ABI = FFI_UNIX64\n\n#elif defined(X86_WIN32)\n  FFI_FIRST_ABI = 0,\n  FFI_SYSV      = 1,\n  FFI_STDCALL   = 2,\n  FFI_THISCALL  = 3,\n  FFI_FASTCALL  = 4,\n  FFI_MS_CDECL  = 5,\n  FFI_PASCAL    = 6,\n  FFI_REGISTER  = 7,\n  FFI_LAST_ABI,\n  FFI_DEFAULT_ABI = FFI_MS_CDECL\n#else\n  FFI_FIRST_ABI = 0,\n  FFI_SYSV      = 1,\n  FFI_THISCALL  = 3,\n  FFI_FASTCALL  = 4,\n  FFI_STDCALL   = 5,\n  FFI_PASCAL    = 6,\n  FFI_REGISTER  = 7,\n  FFI_MS_CDECL  = 8,\n  FFI_LAST_ABI,\n  FFI_DEFAULT_ABI = FFI_SYSV\n#endif\n} ffi_abi;\n#endif\n\n/* ---- Definitions for closures ----------------------------------------- */\n\n#define FFI_CLOSURES 1\n#define FFI_GO_CLOSURES 1\n\n#define FFI_TYPE_SMALL_STRUCT_1B (FFI_TYPE_LAST + 1)\n#define FFI_TYPE_SMALL_STRUCT_2B (FFI_TYPE_LAST + 2)\n#define FFI_TYPE_SMALL_STRUCT_4B (FFI_TYPE_LAST + 3)\n#define FFI_TYPE_MS_STRUCT       (FFI_TYPE_LAST + 4)\n\n#if defined (X86_64) || defined(X86_WIN64) \\\n    || (defined (__x86_64__) && defined (X86_DARWIN))\n# define FFI_TRAMPOLINE_SIZE 24\n# define FFI_NATIVE_RAW_API 0\n#else\n# define FFI_TRAMPOLINE_SIZE 12\n# define FFI_NATIVE_RAW_API 1  /* x86 has native raw api support */\n#endif\n\n#endif\n\n"
  },
  {
    "path": "Extensions/JPLocker.h",
    "content": "//\n//  JPLocker.h\n//  JSPatchDemo\n//\n//  Created by bang on 3/22/16.\n//  Copyright © 2016 bang. All rights reserved.\n//\n\n#import \"JPEngine.h\"\n\n@interface JPLocker : JPExtension\n\n@end\n"
  },
  {
    "path": "Extensions/JPLocker.m",
    "content": "//\n//  JPLocker.m\n//  JSPatchDemo\n//\n//  Created by bang on 3/22/16.\n//  Copyright © 2016 bang. All rights reserved.\n//\n\n#import \"JPLocker.h\"\n\n@implementation JPLocker\n+ (void)main:(JSContext *)context\n{\n    context[@\"synchronized\"] = ^void(JSValue *jsVal, JSValue *cb) {\n        @synchronized([self formatJSToOC:jsVal]) {\n            [cb callWithArguments:nil];\n        }\n    };\n}\n@end\n"
  },
  {
    "path": "Extensions/JPNumber.h",
    "content": "//\n//  JPNumber.h\n//  JSPatchDemo\n//\n//  Created by pucheng on 16/7/5.\n//  Copyright © 2016年 pucheng. All rights reserved.\n//\n\n#import \"JPEngine.h\"\n@interface JPNumber : JPExtension\n\n@end\n"
  },
  {
    "path": "Extensions/JPNumber.m",
    "content": "//\n//  JPNumber.m\n//  JSPatchDemo\n//\n//  Created by pucheng on 16/7/5.\n//  Copyright © 2016年 pucheng. All rights reserved.\n//\n\n#import \"JPNumber.h\"\n#import <objc/runtime.h>\n\n@implementation JPNumber\n\n+ (void)main:(JSContext *)context {\n    \n    // for subclass of NSNumber, e.g. NSDecimalNumber\n    context[@\"OCNumber\"] = ^ id (NSString *clsName, NSString *selName, JSValue *arguments) {\n        Class cls = NSClassFromString(clsName);\n        SEL sel = NSSelectorFromString(selName);\n        if (!cls || !sel) return nil;\n        Method m = class_getClassMethod(cls, sel);\n        if (!m) return nil;\n        \n        NSMethodSignature *methodSignature = [cls methodSignatureForSelector:sel];\n        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature];\n        [invocation setTarget:cls];\n        [invocation setSelector:sel];\n        id argumentsObj = [self formatJSToOC: arguments];\n        NSUInteger numberOfArguments = methodSignature.numberOfArguments;\n        \n        for (NSUInteger i = 2; i < numberOfArguments; i++) {\n            const char *argumentType = [methodSignature getArgumentTypeAtIndex:i];\n            id valObj = argumentsObj[i-2];\n            switch (argumentType[0] == 'r' ? argumentType[1] : argumentType[0]) {\n                    \n                #define JP_OCNumber_CASE(_typeString, _type, _selector) \\\n                    case _typeString: { \\\n                        _type value = [valObj _selector];  \\\n                        [invocation setArgument:&value atIndex:i];  \\\n                        break;  \\\n                    }\n                    \n                    JP_OCNumber_CASE('c', char, charValue)\n                    JP_OCNumber_CASE('C', unsigned char, unsignedCharValue)\n                    JP_OCNumber_CASE('s', short, shortValue)\n                    JP_OCNumber_CASE('S', unsigned short, unsignedShortValue)\n                    JP_OCNumber_CASE('i', int, intValue)\n                    JP_OCNumber_CASE('I', unsigned int, unsignedIntValue)\n                    JP_OCNumber_CASE('l', long, longValue)\n                    JP_OCNumber_CASE('L', unsigned long, unsignedLongValue)\n                    JP_OCNumber_CASE('q', long long, longLongValue)\n                    JP_OCNumber_CASE('Q', unsigned long long, unsignedLongLongValue)\n                    JP_OCNumber_CASE('f', float, floatValue)\n                    JP_OCNumber_CASE('d', double, doubleValue)\n                    JP_OCNumber_CASE('B', BOOL, boolValue)\n                default:\n                    [invocation setArgument:&valObj atIndex:i];\n            }\n        }\n        [invocation invoke];\n        void *result;\n        [invocation getReturnValue:&result];\n        id returnValue = (__bridge id)result;\n        /**\n         * must be boxed in JPBoxing.\n         * Otherwise when calling functions in JS, the number valued 0 which is considered as null will call a class function rather than a instance function in JSPatch.js\n         */\n        JPBoxing *box = [[JPBoxing alloc] init];\n        box.obj = returnValue;\n        return  @{@\"__obj\": box, @\"__clsName\": clsName};\n    };\n    \n    context[@\"toOCNumber\"] = ^ id (JSValue *value) {\n        id obj = [value toObject];\n        if (!obj || ![obj isKindOfClass:[NSNumber class]]) {\n            return nil;\n        }\n        JPBoxing *box = [[JPBoxing alloc] init];\n        box.obj = obj;\n        return  @{@\"__obj\": box, @\"__clsName\": NSStringFromClass([obj class])};\n    };\n    \n    context[@\"toJSNumber\"] = ^ NSNumber *(JSValue *value) {\n        NSDictionary *dict = [value toDictionary];\n        if (dict) {\n            return [(JPBoxing *)dict[@\"__obj\"] unbox];\n        }\n        return 0;\n    };\n}\n\n@end\n"
  },
  {
    "path": "Extensions/JPPlaygroundTool/JPPlayground.h",
    "content": "//\n//  JPPlayground.h\n//  JSPatchPlaygroundDemo\n//\n//  Created by Awhisper on 16/8/7.\n//  Copyright © 2016年 baidu. All rights reserved.\n//\n#import <Foundation/Foundation.h>\n\n@interface JPPlayground : NSObject\n\n+(void)startPlaygroundWithJSPath:(NSString *)path;\n\n+(void)setReloadCompleteHandler:(void(^)())complete;\n\n+(void)reload;\n\n@end\n"
  },
  {
    "path": "Extensions/JPPlaygroundTool/JPPlayground.m",
    "content": "//\n//  JPPlayground.m\n//  JSPatchPlaygroundDemo\n//\n//  Created by Awhisper on 16/8/7.\n//  Copyright © 2016年 baidu. All rights reserved.\n//\n\n#import \"JPPlayground.h\"\n#import \"JPKeyCommands.h\"\n#import \"JPDevErrorView.h\"\n#import \"JPDevMenu.h\"\n#import \"JPDevTipView.h\"\n#import \"SGDirWatchdog.h\"\n\n@interface JPPlayground ()<UIActionSheetDelegate,JPDevMenuDelegate>\n\n@property (nonatomic,strong) NSString *rootPath;\n\n@property (nonatomic,strong) JPKeyCommands *keyManager;\n\n@property (nonatomic,strong) UIView *errorView;\n\n@property (nonatomic,strong) JPDevMenu *devMenu;\n\n@property (nonatomic,assign) BOOL isAutoReloading;\n\n@property (nonatomic,strong) NSMutableArray<SGDirWatchdog *> *watchDogs;\n\n@end\n\nstatic void (^_reloadCompleteHandler)(void) = ^void(void) {\n   \n};\n\n@implementation JPPlayground\n\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wundeclared-selector\"\n\n+ (instancetype)sharedInstance\n{\n#if TARGET_IPHONE_SIMULATOR\n    static JPPlayground *sharedInstance;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        sharedInstance = [self new];\n    });\n    \n    return sharedInstance;\n#else\n    return nil;\n#endif\n}\n\n- (instancetype)init\n{\n    if ((self = [super init])) {\n#if TARGET_IPHONE_SIMULATOR\n        _keyManager = [JPKeyCommands sharedInstance];\n        _devMenu = [[JPDevMenu alloc]init];\n        _devMenu.delegate = self;\n        _isAutoReloading = NO;\n        _watchDogs = [[NSMutableArray alloc] init];\n#endif\n    }\n    return self;\n}\n\n+(void)setReloadCompleteHandler:(void (^)())complete\n{\n    _reloadCompleteHandler = [complete copy];\n}\n\n+(void)startPlaygroundWithJSPath:(NSString *)path\n{\n    [[JPPlayground sharedInstance] startPlaygroundWithJSPath:path];\n}\n\n-(void)startPlaygroundWithJSPath:(NSString *)mainScriptPath\n{\n#if TARGET_IPHONE_SIMULATOR\n    self.rootPath = mainScriptPath;\n    \n    NSString *scriptRootPath = [mainScriptPath stringByDeletingLastPathComponent];\n    \n    NSArray *contentOfFolder = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:scriptRootPath error:NULL];\n    [self watchFolder:scriptRootPath mainScriptPath:mainScriptPath];\n    \n    if ([scriptRootPath rangeOfString:@\".app\"].location != NSNotFound) {\n        NSString *apphomepath = [scriptRootPath stringByDeletingLastPathComponent];\n        [self watchFolder:apphomepath mainScriptPath:mainScriptPath];\n    }\n    \n    for (NSString *aPath in contentOfFolder) {\n        NSString * fullPath = [scriptRootPath stringByAppendingPathComponent:aPath];\n        BOOL isDir;\n        if ([[NSFileManager defaultManager] fileExistsAtPath:fullPath isDirectory:&isDir] && isDir) {\n            [self watchFolder:fullPath mainScriptPath:mainScriptPath];\n        }\n    }\n    void(^exceptionhandler)(NSString *msg) = ^(NSString *msg){\n        JPDevErrorView *errV = [[JPDevErrorView alloc]initError:msg];\n        [[UIApplication sharedApplication].keyWindow addSubview:errV];\n        self.errorView = errV;\n        [self.devMenu toggle];\n    };\n    id JPEngineClass = (id)NSClassFromString(@\"JPEngine\");\n    if (JPEngineClass && [JPEngineClass respondsToSelector:@selector(handleException:)]) {\n        [JPEngineClass performSelector:@selector(handleException:) withObject:exceptionhandler];\n    }else{\n        NSCAssert(NO, @\"can't find JPEngine handleException: Method\");\n    }\n    \n    [self.keyManager registerKeyCommandWithInput:@\"x\" modifierFlags:UIKeyModifierCommand action:^(UIKeyCommand *command) {\n        [self.devMenu toggle];\n    }];\n    \n    [self.keyManager registerKeyCommandWithInput:@\"r\" modifierFlags:UIKeyModifierCommand action:^(UIKeyCommand *command) {\n        [self reload];\n    }];\n    \n    [self reload];\n#endif\n}\n\n+(void)reload\n{\n    [[JPPlayground sharedInstance]reload];\n}\n\n-(void)reload\n{\n#if TARGET_IPHONE_SIMULATOR\n    [JPDevTipView showJPDevTip:@\"JSPatch Reloading ...\"];\n    [self hideErrorView];\n    id JPCleanerClass = (id)NSClassFromString(@\"JPCleaner\");\n    if (JPCleanerClass && [JPCleanerClass respondsToSelector:@selector(cleanAll)]) {\n        [JPCleanerClass performSelector:@selector(cleanAll)];\n    }else{\n        NSCAssert(NO, @\"can't find JPCleaner cleanAll Method\");\n    }\n    \n    NSString *script = [NSString stringWithContentsOfFile:self.rootPath encoding:NSUTF8StringEncoding error:nil];\n    \n    id JPEngineClass = (id)NSClassFromString(@\"JPEngine\");\n    if (JPEngineClass && [JPEngineClass respondsToSelector:@selector(evaluateScript:)]) {\n        [JPEngineClass performSelector:@selector(evaluateScript:) withObject:script];\n    }else{\n        NSCAssert(NO, @\"can't find JPEngine evaluateScript: Method\");\n    }\n    \n    _reloadCompleteHandler();\n#endif\n}\n\n-(void)openInFinder\n{\n#if TARGET_IPHONE_SIMULATOR\n    NSLog(@\"%@\\n\",self.rootPath);\n    \n    NSLog(@\"请打开以上路径的文件，事实编辑JS，事实刷新\");\n    \n    NSString *msg = [NSString stringWithFormat:@\"JS文件路径：%@\\n 编辑JS文件后保存，按Command+R刷新就可以看到最新的代码效果\",self.rootPath];\n    \n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n    UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@\"Edit JS File and Reload\" message:msg delegate:nil cancelButtonTitle:@\"OK\" otherButtonTitles:nil, nil];\n    [alert show];\n    [UIPasteboard generalPasteboard].string = self.rootPath;\n#pragma clang diagnostic pop\n    \n#endif\n}\n\n-(void)watchJSFile:(BOOL)watch\n{\n#if TARGET_IPHONE_SIMULATOR\n    for (SGDirWatchdog *dog in self.watchDogs) {\n        if (watch) {\n            [dog start];\n        }else{\n            [dog stop];\n        }\n    }\n#endif\n}\n\n- (void)watchFolder:(NSString *)folderPath mainScriptPath:(NSString *)mainScriptPath\n{\n#if TARGET_IPHONE_SIMULATOR\n    SGDirWatchdog *watchDog = [[SGDirWatchdog alloc] initWithPath:folderPath update:^{\n        [self reload];\n    }];\n    [self.watchDogs addObject:watchDog];\n#endif\n}\n\n-(void)hideErrorView\n{\n#if TARGET_IPHONE_SIMULATOR\n    [self.errorView removeFromSuperview];\n    self.errorView = nil;\n#endif\n}\n\n\n-(void)devMenuDidAction:(JPDevMenuAction)action withValue:(id)value\n{\n#if TARGET_IPHONE_SIMULATOR\n    switch (action) {\n        case JPDevMenuActionReload:{\n            [self reload];\n            break;\n        }\n        case JPDevMenuActionAutoReload:{\n            BOOL select = [value boolValue];\n            [self watchJSFile:select];\n            break;\n        }\n        case JPDevMenuActionOpenJS:{\n            [self openInFinder];\n            break;\n        }\n        case JPDevMenuActionCancel:{\n            [self hideErrorView];\n            break;\n        }\n            \n            \n        default:\n            break;\n    }\n#endif\n}\n\n#pragma clang diagnostic pop\n@end\n"
  },
  {
    "path": "Extensions/JPPlaygroundTool/JPPlaygroundModule/JPKeyCommands.h",
    "content": "//\n//  JPKeyCommands.h\n//  JSPatchPlaygroundDemo\n//\n//  Created by Awhisper on 16/8/7.\n//  Copyright © 2016年 baidu. All rights reserved.\n//\n\n\n#import <UIKit/UIKit.h>\n\n@interface JPKeyCommands : NSObject\n\n+ (instancetype)sharedInstance;\n\n- (void)registerKeyCommandWithInput:(NSString *)input\n                      modifierFlags:(UIKeyModifierFlags)flags\n                             action:(void (^)(UIKeyCommand *))block;\n\n- (void)unregisterKeyCommandWithInput:(NSString *)input\n                        modifierFlags:(UIKeyModifierFlags)flags;\n\n- (BOOL)isKeyCommandRegisteredForInput:(NSString *)input\n                         modifierFlags:(UIKeyModifierFlags)flags;\n@end\n"
  },
  {
    "path": "Extensions/JPPlaygroundTool/JPPlaygroundModule/JPKeyCommands.m",
    "content": "/**\n * Copyright (c) 2015-present, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\n#import \"JPKeyCommands.h\"\n\n#import <UIKit/UIKit.h>\n#import <objc/runtime.h>\n\nstatic BOOL JPIsIOS8OrEarlier()\n{\n    return [UIDevice currentDevice].systemVersion.floatValue < 9;\n}\n\n\nvoid JPSwapInstanceMethods(Class cls, SEL original, SEL replacement)\n{\n    Method originalMethod = class_getInstanceMethod(cls, original);\n    IMP originalImplementation = method_getImplementation(originalMethod);\n    const char *originalArgTypes = method_getTypeEncoding(originalMethod);\n    \n    Method replacementMethod = class_getInstanceMethod(cls, replacement);\n    IMP replacementImplementation = method_getImplementation(replacementMethod);\n    const char *replacementArgTypes = method_getTypeEncoding(replacementMethod);\n    \n    if (class_addMethod(cls, original, replacementImplementation, replacementArgTypes)) {\n        class_replaceMethod(cls, replacement, originalImplementation, originalArgTypes);\n    } else {\n        method_exchangeImplementations(originalMethod, replacementMethod);\n    }\n}\n\n\n#if TARGET_IPHONE_SIMULATOR\n\n@interface JPKeyCommand : NSObject <NSCopying>\n\n@property (nonatomic, strong) UIKeyCommand *keyCommand;\n@property (nonatomic, copy) void (^block)(UIKeyCommand *);\n\n@end\n\n@implementation JPKeyCommand\n\n- (instancetype)initWithKeyCommand:(UIKeyCommand *)keyCommand\n                             block:(void (^)(UIKeyCommand *))block\n{\n    if ((self = [super init])) {\n        _keyCommand = keyCommand;\n        _block = block;\n    }\n    return self;\n}\n\n\n- (id)copyWithZone:(__unused NSZone *)zone\n{\n    return self;\n}\n\n- (NSUInteger)hash\n{\n    return _keyCommand.input.hash ^ _keyCommand.modifierFlags;\n}\n\n- (BOOL)isEqual:(JPKeyCommand *)object\n{\n    if (![object isKindOfClass:[JPKeyCommand class]]) {\n        return NO;\n    }\n    return [self matchesInput:object.keyCommand.input\n                        flags:object.keyCommand.modifierFlags];\n}\n\n- (BOOL)matchesInput:(NSString *)input flags:(UIKeyModifierFlags)flags\n{\n    return [_keyCommand.input isEqual:input] && _keyCommand.modifierFlags == flags;\n}\n\n- (NSString *)description\n{\n    return [NSString stringWithFormat:@\"<%@:%p input=\\\"%@\\\" flags=%zd hasBlock=%@>\",\n            [self class], self, _keyCommand.input, _keyCommand.modifierFlags,\n            _block ? @\"YES\" : @\"NO\"];\n}\n\n@end\n\n@interface JPKeyCommands ()\n\n@property (nonatomic, strong) NSMutableSet<JPKeyCommand *> *commands;\n\n@end\n\n@implementation UIResponder (RCTKeyCommands)\n\n- (NSArray<UIKeyCommand *> *)JP_keyCommands\n{\n    NSSet<JPKeyCommand *> *commands = [JPKeyCommands sharedInstance].commands;\n    return [[commands valueForKeyPath:@\"keyCommand\"] allObjects];\n}\n\n\n- (void)JP_handleKeyCommand:(UIKeyCommand *)key\n{\n    // NOTE: throttle the key handler because on iOS 9 the handleKeyCommand:\n    // method gets called repeatedly if the command key is held down.\n    \n    static NSTimeInterval lastCommand = 0;\n    if (JPIsIOS8OrEarlier() || CACurrentMediaTime() - lastCommand > 0.5) {\n        for (JPKeyCommand *command in [JPKeyCommands sharedInstance].commands) {\n            if ([command.keyCommand.input isEqualToString:key.input] &&\n                command.keyCommand.modifierFlags == key.modifierFlags) {\n                if (command.block) {\n                    command.block(key);\n                    lastCommand = CACurrentMediaTime();\n                }\n            }\n        }\n    }\n}\n\n@end\n\n@implementation UIApplication (JPKeyCommands)\n\n// Required for iOS 8.x\n- (BOOL)JP_sendAction:(SEL)action to:(id)target from:(id)sender forEvent:(UIEvent *)event\n{\n    if (action == @selector(JP_handleKeyCommand:)) {\n        [self JP_handleKeyCommand:sender];\n        return YES;\n    }\n    return [self JP_sendAction:action to:target from:sender forEvent:event];\n}\n\n@end\n\n@implementation JPKeyCommands\n\n+ (void)initialize\n{\n    if (JPIsIOS8OrEarlier()) {\n        \n        //swizzle UIApplication\n        JPSwapInstanceMethods([UIApplication class],\n                              @selector(keyCommands),\n                              @selector(JP_keyCommands));\n        \n        JPSwapInstanceMethods([UIApplication class],\n                              @selector(sendAction:to:from:forEvent:),\n                              @selector(JP_sendAction:to:from:forEvent:));\n    } else {\n        \n        //swizzle UIResponder\n        JPSwapInstanceMethods([UIResponder class],\n                              @selector(keyCommands),\n                              @selector(JP_keyCommands));\n    }\n}\n\n+ (instancetype)sharedInstance\n{\n    static JPKeyCommands *sharedInstance;\n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        sharedInstance = [self new];\n    });\n    \n    return sharedInstance;\n}\n\n- (instancetype)init\n{\n    if ((self = [super init])) {\n        _commands = [NSMutableSet new];\n    }\n    return self;\n}\n\n- (void)registerKeyCommandWithInput:(NSString *)input\n                      modifierFlags:(UIKeyModifierFlags)flags\n                             action:(void (^)(UIKeyCommand *))block\n{\n    \n    if (input.length && flags && JPIsIOS8OrEarlier()) {\n        \n        // Workaround around the first cmd not working: http://openradar.appspot.com/19613391\n        // You can register just the cmd key and do nothing. This ensures that\n        // command-key modified commands will work first time. Fixed in iOS 9.\n        \n        [self registerKeyCommandWithInput:@\"\"\n                            modifierFlags:flags\n                                   action:nil];\n    }\n    \n    UIKeyCommand *command = [UIKeyCommand keyCommandWithInput:input\n                                                modifierFlags:flags\n                                                       action:@selector(JP_handleKeyCommand:)];\n    \n    JPKeyCommand *keyCommand = [[JPKeyCommand alloc] initWithKeyCommand:command block:block];\n    [_commands removeObject:keyCommand];\n    [_commands addObject:keyCommand];\n}\n\n- (void)unregisterKeyCommandWithInput:(NSString *)input\n                        modifierFlags:(UIKeyModifierFlags)flags\n{\n    \n    for (JPKeyCommand *command in _commands.allObjects) {\n        if ([command matchesInput:input flags:flags]) {\n            [_commands removeObject:command];\n            break;\n        }\n    }\n}\n\n- (BOOL)isKeyCommandRegisteredForInput:(NSString *)input\n                         modifierFlags:(UIKeyModifierFlags)flags\n{\n    \n    for (JPKeyCommand *command in _commands) {\n        if ([command matchesInput:input flags:flags]) {\n            return YES;\n        }\n    }\n    return NO;\n}\n\n@end\n\n#else\n\n@implementation JPKeyCommands\n\n+ (instancetype)sharedInstance\n{\n    return nil;\n}\n\n- (void)registerKeyCommandWithInput:(NSString *)input\n                      modifierFlags:(UIKeyModifierFlags)flags\n                             action:(void (^)(UIKeyCommand *))block {\n\n};\n\n- (void)unregisterKeyCommandWithInput:(NSString *)input\n                        modifierFlags:(UIKeyModifierFlags)flags {\n\n};\n\n- (BOOL)isKeyCommandRegisteredForInput:(NSString *)input\n                         modifierFlags:(UIKeyModifierFlags)flags\n{\n    return NO;\n}\n\n@end\n\n#endif\n\n"
  },
  {
    "path": "Extensions/JPPlaygroundTool/JPPlaygroundModule/SGDirWatchdog.h",
    "content": "//\n//  SGDirObserver.h\n//  DirectoryObserver\n//\n//  Copyright (c) 2011 Simon Grätzer.\n//\n\n#import <Foundation/Foundation.h>\n\n@interface SGDirWatchdog : NSObject\n\n@property (readonly, nonatomic) NSString *path;\n@property (copy, nonatomic) void (^update)(void);\n\n+ (NSString *)documentsPath;\n+ (id)watchtdogOnDocumentsDir:(void (^)(void))update;\n\n- (id)initWithPath:(NSString *)path update:(void (^)(void))update;\n\n- (void)start;\n- (void)stop;\n\n@end\n"
  },
  {
    "path": "Extensions/JPPlaygroundTool/JPPlaygroundModule/SGDirWatchdog.m",
    "content": "//\n//  SGDirObserver.m\n//  DirectoryObserver\n//\n//  Copyright (c) 2011 Simon Grätzer.\n//\n\n#import \"SGDirWatchdog.h\"\n#import <fcntl.h>\n#import <unistd.h>\n#import <sys/event.h>\n\n@interface SGDirWatchdog ()\n@property (nonatomic, readonly) CFFileDescriptorRef kqRef;\n- (void)kqueueFired;\n@end\n\n\nstatic void KQCallback(CFFileDescriptorRef kqRef, CFOptionFlags callBackTypes, void *info) {\n\t// Pick up the object passed in the \"info\" member of the CFFileDescriptorContext passed to CFFileDescriptorCreate\n    SGDirWatchdog* obj = (__bridge SGDirWatchdog*) info;\n\t\n\tif ([obj isKindOfClass:[SGDirWatchdog class]]\t\t&&\t// If we can call back to the proper sort of object ...\n\t\t(kqRef == obj.kqRef)\t\t\t\t\t\t\t\t&&\t// and the FD that issued the CB is the expected one ...\n\t\t(callBackTypes == kCFFileDescriptorReadCallBack)\t)\t// and we're processing the proper sort of CB ...\n\t{\n\t\t[obj kqueueFired];\t\t\t\t\t\t\t\t\t\t// Invoke the instance's CB handler\n\t}\n}\n\n@implementation SGDirWatchdog {\n    int\t\t\t\t\t_dirFD;\n    CFFileDescriptorRef _kqRef;\n}\n\n+ (NSString *)documentsPath {\n\tNSArray *documentsPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);\n    \n\treturn documentsPaths[0]; // Path to the application's \"Documents\" directory\n}\n\n+ (id)watchtdogOnDocumentsDir:(void (^)(void))update; {\n    return [[SGDirWatchdog alloc]initWithPath:[self documentsPath] update:update];\n}\n\n\n- (id)initWithPath:(NSString *)path update:(void (^)(void))update; {\n    if ((self = [super init])) {\n        _path = path;\n        _update = [update copy];\n    }\n    return self;\n}\n\n- (void)dealloc {\n    [self stop];\n    \n    \n}\n\n#pragma mark -\n#pragma mark Extension methods\n\n- (void)kqueueFired {\n\t// Pull the native FD around which the CFFileDescriptor was wrapped\n    int kq = CFFileDescriptorGetNativeDescriptor(_kqRef);\n\tif (kq < 0) return;\n\t\n\t// If we pull a single available event out of the queue, assume the directory was updated\n    struct kevent event;\n    struct timespec timeout = {0, 0};\n    if (kevent(kq, NULL, 0, &event, 1, &timeout) == 1 && _update) {\n\t\t_update();\n    }    \n\t\n\t// (Re-)Enable a one-shot (the only kind) callback\n    CFFileDescriptorEnableCallBacks(_kqRef, kCFFileDescriptorReadCallBack);\n}\n\n\n- (void)start {\n\t// One ping only\n    if (_kqRef != NULL) return;\n\t\n\t// Fetch pathname of the directory to monitor\n\tNSString* docPath = self.path;\n\tif (!docPath) return;\n    \n\t// Open an event-only file descriptor associated with the directory\n    int dirFD = open([docPath fileSystemRepresentation], O_EVTONLY);\n\tif (dirFD < 0) return;\n\t\n\t// Create a new kernel event queue\n    int kq = kqueue();\n\tif (kq < 0)\n\t{\n\t\tclose(dirFD);\n\t\treturn;\n\t}\n    \n\t// Set up a kevent to monitor\n    struct kevent eventToAdd;\t\t\t\t\t// Register an (ident, filter) pair with the kqueue\n    eventToAdd.ident  = dirFD;\t\t\t\t\t// The object to watch (the directory FD)\n    eventToAdd.filter = EVFILT_VNODE;\t\t\t// Watch for certain events on the VNODE spec'd by ident\n    eventToAdd.flags  = EV_ADD | EV_CLEAR;\t\t// Add a resetting kevent\n    eventToAdd.fflags = NOTE_WRITE;\t\t\t\t// The events to watch for on the VNODE spec'd by ident (writes)\n    eventToAdd.data   = 0;\t\t\t\t\t\t// No filter-specific data\n    eventToAdd.udata  = NULL;\t\t\t\t\t// No user data\n    \n\t// Add a kevent to monitor \n\tif (kevent(kq, &eventToAdd, 1, NULL, 0, NULL)) {\n\t\tclose(kq);\n\t\tclose(dirFD);\n\t\treturn;\n\t}\n\t\n\t// Wrap a CFFileDescriptor around a native FD\n\tCFFileDescriptorContext context = {0, (__bridge void *)(self), NULL, NULL, NULL};\n    _kqRef = CFFileDescriptorCreate(NULL,\t\t// Use the default allocator\n\t\t\t\t\t\t\t\t\tkq,\t\t\t// Wrap the kqueue\n\t\t\t\t\t\t\t\t\ttrue,\t\t// Close the CFFileDescriptor if kq is invalidated\n\t\t\t\t\t\t\t\t\tKQCallback,\t// Fxn to call on activity\n\t\t\t\t\t\t\t\t\t&context);\t// Supply a context to set the callback's \"info\" argument\n    if (_kqRef == NULL) {\n\t\tclose(kq);\n\t\tclose(dirFD);\n\t\treturn;\n\t}\n\t\n\t// Spin out a pluggable run loop source from the CFFileDescriptorRef\n\t// Add it to the current run loop, then release it\n    CFRunLoopSourceRef rls = CFFileDescriptorCreateRunLoopSource(NULL, _kqRef, 0);\n    if (rls == NULL) {\n\t\tCFRelease(_kqRef); _kqRef = NULL;\n\t\tclose(kq);\n\t\tclose(dirFD);\n\t\treturn;\n\t}\n    CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);\n    CFRelease(rls);\n    \n\t// Store the directory FD for later closing\n\t_dirFD = dirFD;\n\t\n\t// Enable a one-shot (the only kind) callback\n    CFFileDescriptorEnableCallBacks(_kqRef, kCFFileDescriptorReadCallBack);\n}\n\n- (void)stop {\n\tif (_kqRef) {\n\t\tclose(_dirFD);\n\t\tCFFileDescriptorInvalidate(_kqRef);\n\t\tCFRelease(_kqRef);\n\t\t_kqRef = NULL;\n\t}\n}\n\n@end\n"
  },
  {
    "path": "Extensions/JPPlaygroundTool/JPPlaygroundView/JPDevErrorView.h",
    "content": "//\n//  JPErrorView.h\n//  JSPatchPlaygroundDemo\n//\n//  Created by Awhisper on 16/8/7.\n//  Copyright © 2016年 baidu. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface JPDevErrorView : UIView\n\n- (instancetype)initError:(NSString *)errMsg;\n\n@end\n"
  },
  {
    "path": "Extensions/JPPlaygroundTool/JPPlaygroundView/JPDevErrorView.m",
    "content": "//\n//  JPErrorView.m\n//  JSPatchPlaygroundDemo\n//\n//  Created by Awhisper on 16/8/7.\n//  Copyright © 2016年 baidu. All rights reserved.\n//\n\n#import \"JPDevErrorView.h\"\n\n\n\n@implementation JPDevErrorView\n\n- (instancetype)initError:(NSString *)errMsg\n{\n    self = [super initWithFrame:[UIScreen mainScreen].bounds];\n    if (self) {\n        self.backgroundColor = [UIColor redColor];\n        \n        UITextView *text = [[UITextView alloc]initWithFrame:CGRectMake(0, 20, self.bounds.size.width, self.bounds.size.height-20)];\n        text.backgroundColor = [UIColor redColor];\n        text.textColor = [UIColor whiteColor];\n        text.font = [UIFont systemFontOfSize:20];\n        text.userInteractionEnabled = NO;\n        \n        text.text = errMsg;\n        \n        [self addSubview:text];\n        \n    }\n    return self;\n}\n\n@end\n"
  },
  {
    "path": "Extensions/JPPlaygroundTool/JPPlaygroundView/JPDevMenu.h",
    "content": "//\n//  JPPlaygroundMenu.h\n//  JSPatchPlaygroundDemo\n//\n//  Created by Awhisper on 16/8/7.\n//  Copyright © 2016年 baidu. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\ntypedef enum : NSUInteger {\n    JPDevMenuActionReload = 0,\n    JPDevMenuActionAutoReload,\n    JPDevMenuActionOpenJS,\n    JPDevMenuActionCancel\n} JPDevMenuAction;\n\n@protocol JPDevMenuDelegate <NSObject>\n\n-(void)devMenuDidAction:(JPDevMenuAction)action withValue:(id)value;\n\n@end\n\n@interface JPDevMenu : NSObject\n\n@property (nonatomic,weak) id<JPDevMenuDelegate> delegate;\n- (void)toggle;\n@end\n"
  },
  {
    "path": "Extensions/JPPlaygroundTool/JPPlaygroundView/JPDevMenu.m",
    "content": "//\n//  JPPlaygroundMenu.m\n//  JSPatchPlaygroundDemo\n//\n//  Created by Awhisper on 16/8/7.\n//  Copyright © 2016年 baidu. All rights reserved.\n//\n\n#import \"JPDevMenu.h\"\n#import <UIKit/UIKit.h>\n\n@interface JPDevMenuItem : NSObject\n\n/**\n * This creates an item with a simple push-button interface, used to trigger an\n * action.\n */\n+ (instancetype)buttonItemWithTitle:(NSString *)title\n                            handler:(void(^)(void))handler;\n\n/**\n * This creates an item with a toggle behavior. The key is used to store the\n * state of the toggle. For toggle items, the handler will be called immediately\n * after the item is added if the item was already selected when the module was\n * last loaded.\n */\n+ (instancetype)toggleItemWithKey:(NSString *)key\n                            title:(NSString *)title\n                    selectedTitle:(NSString *)selectedTitle\n                          handler:(void(^)(BOOL selected))handler;\n@end\n\ntypedef NS_ENUM(NSInteger, JPDevMenuType) {\n    JPDevMenuTypeButton,\n    JPDevMenuTypeToggle\n};\n\n@interface JPDevMenuItem ()\n\n@property (nonatomic, assign, readonly) JPDevMenuType type;\n@property (nonatomic, copy, readonly) NSString *key;\n@property (nonatomic, copy, readonly) NSString *title;\n@property (nonatomic, copy, readonly) NSString *selectedTitle;\n@property (nonatomic, copy) id value;\n\n@end\n\n@implementation JPDevMenuItem\n{\n    id _handler; // block\n}\n\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n\n- (instancetype)initWithType:(JPDevMenuType)type\n                         key:(NSString *)key\n                       title:(NSString *)title\n               selectedTitle:(NSString *)selectedTitle\n                     handler:(id /* block */)handler\n{\n    if ((self = [super init])) {\n        _type = type;\n        _key = [key copy];\n        _title = [title copy];\n        _selectedTitle = [selectedTitle copy];\n        _handler = [handler copy];\n        _value = nil;\n    }\n    return self;\n}\n\n+ (instancetype)buttonItemWithTitle:(NSString *)title\n                            handler:(void (^)(void))handler\n{\n    return [[self alloc] initWithType:JPDevMenuTypeButton\n                                  key:nil\n                                title:title\n                        selectedTitle:nil\n                              handler:handler];\n}\n\n+ (instancetype)toggleItemWithKey:(NSString *)key\n                            title:(NSString *)title\n                    selectedTitle:(NSString *)selectedTitle\n                          handler:(void (^)(BOOL selected))handler\n{\n    return [[self alloc] initWithType:JPDevMenuTypeToggle\n                                  key:key\n                                title:title\n                        selectedTitle:selectedTitle\n                              handler:handler];\n}\n\n- (void)callHandler\n{\n    switch (_type) {\n        case JPDevMenuTypeButton: {\n            if (_handler) {\n                ((void(^)())_handler)();\n            }\n            break;\n        }\n        case JPDevMenuTypeToggle: {\n            if (_handler) {\n                ((void(^)(BOOL selected))_handler)([_value boolValue]);\n            }\n            break;\n        }\n    }\n}\n\n@end\n\n@interface JPDevMenu ()<UIActionSheetDelegate>\n\n@property (nonatomic,strong) UIActionSheet * actionSheet;\n@property (nonatomic,strong) NSMutableDictionary *settings;\n@property (nonatomic,strong) NSArray<JPDevMenuItem *> *presentedItems;\n\n@end\n\n@implementation JPDevMenu\n\n-(instancetype)init\n{\n    self = [super init];\n    if (self) {\n        _settings = [[NSMutableDictionary alloc]init];\n    }\n    return self;\n}\n\n\n- (NSArray<JPDevMenuItem *> *)menuItems\n{\n    NSMutableArray<JPDevMenuItem *> *items = [NSMutableArray new];\n    \n    // Add built-in items\n    \n    \n    [items addObject:[JPDevMenuItem buttonItemWithTitle:@\"Reload JS (Command+R)\" handler:^{\n        if (self.delegate && [self.delegate respondsToSelector:@selector(devMenuDidAction:withValue:)]) {\n            [self.delegate devMenuDidAction:JPDevMenuActionReload withValue:nil];\n        }\n    }]];\n    \n    JPDevMenuItem *toggle = [JPDevMenuItem toggleItemWithKey:@\"autoReloadJS\" title:@\"open Auto Reload JS\" selectedTitle:@\"Auto Reload JS Is Open\" handler:^(BOOL selected) {\n        if (self.delegate && [self.delegate respondsToSelector:@selector(devMenuDidAction:withValue:)]) {\n            [self.delegate devMenuDidAction:JPDevMenuActionAutoReload withValue:@(selected)];\n        }\n        \n    }];\n    toggle.value = _settings[@\"autoReloadJS\"];\n    [items addObject:toggle];\n    \n    \n    [items addObject:[JPDevMenuItem buttonItemWithTitle:@\"Help\" handler:^{\n        if (self.delegate && [self.delegate respondsToSelector:@selector(devMenuDidAction:withValue:)]) {\n            [self.delegate devMenuDidAction:JPDevMenuActionOpenJS withValue:nil];\n        }\n    }]];\n    \n    \n    return items;\n}\n\n\n- (void)toggle\n{\n    if (_actionSheet) {\n        [_actionSheet dismissWithClickedButtonIndex:_actionSheet.cancelButtonIndex animated:YES];\n        _actionSheet = nil;\n    } else {\n        [self show];\n    }\n    \n}\n\n-(void)show\n{\n    UIActionSheet *actionSheet = [UIActionSheet new];\n    actionSheet.title = @\"JPatch Playgournd : Command + X\";\n    actionSheet.delegate = self;\n    \n    NSArray<JPDevMenuItem *> *items = [self menuItems];\n    for (JPDevMenuItem *item in items) {\n        switch (item.type) {\n            case JPDevMenuTypeButton: {\n                [actionSheet addButtonWithTitle:item.title];\n                break;\n            }\n            case JPDevMenuTypeToggle: {\n                BOOL selected = [item.value boolValue];\n                [actionSheet addButtonWithTitle:selected? item.selectedTitle : item.title];\n                break;\n            }\n        }\n    }\n    \n    [actionSheet addButtonWithTitle:@\"Cancel\"];\n    actionSheet.cancelButtonIndex = actionSheet.numberOfButtons - 1;\n    \n    [actionSheet showInView:[UIApplication sharedApplication].keyWindow.rootViewController.view];\n    _actionSheet = actionSheet;\n    _presentedItems = items;\n}\n\n\n- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex\n{\n    _actionSheet = nil;\n    if (buttonIndex == actionSheet.cancelButtonIndex) {\n        return;\n    }\n    \n    JPDevMenuItem *item = _presentedItems[buttonIndex];\n    switch (item.type) {\n        case JPDevMenuTypeButton: {\n            [item callHandler];\n            break;\n        }\n        case JPDevMenuTypeToggle: {\n            BOOL value = [_settings[item.key] boolValue];\n            [self updateSetting:item.key value:@(!value)]; // will call handler\n            break;\n        }\n    }\n    return;\n}\n\n- (void)updateSetting:(NSString *)name value:(id)value\n{\n    // Fire handler for item whose values has changed\n    for (JPDevMenuItem *item in _presentedItems) {\n        if ([item.key isEqualToString:name]) {\n            if (value != item.value && ![value isEqual:item.value]) {\n                item.value = value;\n                [item callHandler];\n            }\n            break;\n        }\n    }\n    \n    // Save the setting\n    id currentValue = _settings[name];\n    if (currentValue == value || [currentValue isEqual:value]) {\n        return;\n    }\n    if (value) {\n        _settings[name] = value;\n    } else {\n        [_settings removeObjectForKey:name];\n    }\n}\n\n\n\n-(void)actionSheetCancel:(UIActionSheet *)actionSheet\n{\n    if (self.delegate && [self.delegate respondsToSelector:@selector(devMenuDidAction:withValue:)]) {\n        [self.delegate devMenuDidAction:JPDevMenuActionCancel withValue:nil];\n    }\n}\n\n-(void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex\n{\n    if (self.delegate && [self.delegate respondsToSelector:@selector(devMenuDidAction:withValue:)]) {\n        [self.delegate devMenuDidAction:JPDevMenuActionCancel withValue:nil];\n    }\n}\n\n#pragma clang diagnostic pop\n\n@end\n"
  },
  {
    "path": "Extensions/JPPlaygroundTool/JPPlaygroundView/JPDevTipView.h",
    "content": "//\n//  JPTipView.h\n//  JSPatchPlaygroundDemo\n//\n//  Created by Awhisper on 16/8/7.\n//  Copyright © 2016年 baidu. All rights reserved.\n//\n\n#import <UIKit/UIKit.h>\n\n@interface JPDevTipView : UIView\n\n+(void)showJPDevTip:(NSString *)msg;\n\n-(instancetype)initWithMsg:(NSString*)msg;\n\n@end\n"
  },
  {
    "path": "Extensions/JPPlaygroundTool/JPPlaygroundView/JPDevTipView.m",
    "content": "//\n//  JPTipView.m\n//  JSPatchPlaygroundDemo\n//\n//  Created by Awhisper on 16/8/7.\n//  Copyright © 2016年 baidu. All rights reserved.\n//\n\n#import \"JPDevTipView.h\"\n\n@implementation JPDevTipView\n\n-(instancetype)initWithMsg:(NSString*)msg{\n    BOOL statusBarShow = [UIApplication sharedApplication].isStatusBarHidden;\n    \n    \n    self = [super initWithFrame:CGRectMake(0,0,[UIScreen mainScreen].bounds.size.width,statusBarShow?20:40)];\n    if (self) {\n        self.backgroundColor = [UIColor redColor];\n        \n        UILabel *tip = [[UILabel alloc]initWithFrame:CGRectMake(0, statusBarShow?0:20, self.bounds.size.width, 20)];\n        tip.textColor = [UIColor whiteColor];\n        tip.font = [UIFont systemFontOfSize:18];\n        tip.textAlignment = NSTextAlignmentCenter;\n        tip.text = msg;\n        [self addSubview:tip];\n    }\n    return self;\n}\n\n\n+(void)showJPDevTip:(NSString *)msg\n{\n    JPDevTipView *tip = [[JPDevTipView alloc]initWithMsg:msg];\n    UIView *window = [UIApplication sharedApplication].keyWindow;\n    \n    [window addSubview:tip];\n    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{\n        [UIView animateWithDuration:1 animations:^{\n            tip.alpha = 0;\n        } completion:^(BOOL finished) {\n            [tip removeFromSuperview];\n        }];\n    });\n}\n/*\n// Only override drawRect: if you perform custom drawing.\n// An empty implementation adversely affects performance during animation.\n- (void)drawRect:(CGRect)rect {\n    // Drawing code\n}\n*/\n\n@end\n"
  },
  {
    "path": "Extensions/JPPlaygroundTool/README.md",
    "content": "# JSPatchPlaygroundTool\n\nJSPatch天然能实现playground黑科技一样的效果，什么样的黑科技呢？我们改的每一行代码，每一个语句，完全无需重新运行app，直接能立刻看到效果。\n\n并且bang哥已经给出了如何操作和说明\n\n# JSPatch Playground\n\n[JSPatch Playground Github](https://github.com/bang590/JSPatch/tree/master/Demo/iOSPlayground)\n\n\n![Screenshot](https://raw.github.com/bang590/JSPatch/master/Demo/iOSPlayground/Screenshot.gif)\n\n## 介绍\n\nJSPatch Playground 可以让你快速看到 JSPatch 代码执行效果，APP在模拟器运行后，每次修改脚本保存模拟器都会自动刷新，无需重启模拟器，即时看到效果。\n\n你也可以仿照 JSPatch Playground 在你的项目里添加 JSPatch 脚本即时刷新功能，帮助你快速使用 JSPatch 开发功能模块。\n\nTips: 如果运行过程中脚本执行错误，会在状态栏里显示错误原因，点击状态栏可以看到更详细的错误提示。\n\n\n\n# JSPatchPlaygroundTool\n\nbang哥的Playground工程下面，可以看到想要配置这样一个如此酷炫的黑科技，[JSPatch Playground Github](https://github.com/bang590/JSPatch/tree/master/Demo/iOSPlayground) 项目下的`JPRootViewController.m`文件里面的代码还是挺多的\n\n由于前些日子搞了一阵子ReactNative，发现ReactNative下面的Debug，Reload工具很是方便，心想也给JSPatch弄一套，于是就有了这个`JSPatchPlaygroundTool`\n\n初衷是，把一整套playground的思路以及环境代码配置，封装成工具，以简洁的API就能轻松运行。\n\n<!--more-->\n\n## JSPatchPlaygroundTool的使用\n\n这段代码分成两部分，上半部分就是配置`JSPatchPlaygroundTool`，让JSPatch以Playground的模式进行工作。下半部分则是正常代码，正常的按既有方案加载JSPatch\n\n```objectivec\n#if TARGET_IPHONE_SIMULATOR\n    //playground调试\n    //JS测试包的本地绝对路径\n    NSString *rootPath = @\"/Users/Awhisper/Desktop/Github/JSPatchPlaygroundTool/JSPatchPlaygroundDemo/JSPatchPlaygroundDemo\";\n    \n    NSString *scriptRootPath = [rootPath stringByAppendingPathComponent:@\"js\"];\n    NSString *mainScriptPath = [NSString stringWithFormat:@\"%@/%@\", scriptRootPath, @\"demo.js\"];\n    [JPPlayground setReloadCompleteHandler:^{\n        [self showController];\n    }];\n    [JPPlayground startPlaygroundWithJSPath:mainScriptPath];\n    \n#else\n    //正常执行JSPatch\n    //JS测试包的本地绝对路径\n    NSString *rootPath = [[NSBundle mainBundle] bundlePath];\n    \n    NSString *scriptPath = [rootPath stringByAppendingPathComponent:@\"demo.js\"];\n    NSString *script = [NSString stringWithContentsOfFile:scriptPath encoding:NSUTF8StringEncoding error:nil];\n    [JPEngine evaluateScript:script];\n#endif\n    \n```\n\n这里只讲解上半部分的API，`rootPath`此处切记输入Mac电脑的mainJS文件所在的路径，我的目录里在工程文件`JSPatchPlaygroundDemo`下专门放了个名字为JS的文件夹，里面放着核心的JS代码逻辑，所以我又补充了`\\js\\demo.js`作为后缀\n\n- [JPPlayground setReloadCompleteHandler:block]\n\n这个API的意义在于，每次重新刷新JS后，如果有一些额外的想要操作的东西就可以在此时执行，如果没有，这个API完全可以不使用\n\n- [JPPlayground startPlaygroundWithJSPath:path]\n\n\n这个API是核心API，输入mainJS的路径后，整个JSPatch将会以playground的模式进行运行\n\n## JSPatchPlaygroundTool的效果\n\n__command + X__:可以打开操作菜单\n\n![menu](http://ww2.sinaimg.cn/mw690/678c3e91jw1f6lkzh8zwdj208n0fyaam.jpg)\n\n\n__command + R__:可以ReloadJS\n\n当APP在保持运行的时候，我们可以任意修改main.js文件然后进行保存，然后按command+R的组合键，就可以立刻刷新\n\n__JS Error__:当JS文件有错误，app并不会崩溃，保持持续运行，并且弹出红色界面，详细描述错误信息，当把js文件修改正确后，重新reload，自然就会顺利运行。\n\n![error](http://ww2.sinaimg.cn/mw690/678c3e91jw1f6lkzglfruj208n0fyq3t.jpg)\n\n__AutoReload JS__:Tool可以开启监听JS文件的变化，当你把menu中的这个开关打开，每一次修改js文件进行保存，都会自动触发reload。再次点击这个按钮，会关闭监听，（AutoReload默认不开启）\n\n__Todo List__:我还想尝试在菜单里面多做2个功能，但并未能找到办法\n\n- 自动打开Finder，打开JS文件所在的目录，从而能快速找到要修改的JS文件，轻轻松松的开始畅快的JS代码之旅，从此告别编译，运行，重启app的烦躁过程\n\n- 自动打开Safari的开发者模式，打开正在run的JSContext，从而能对js代码进行断点调试，就好像ReactNative能自动打开chrome一样\n\n我没有找到很好的办法，能在iOS框架里面，在模拟器里面，打开Mac上的Mac app，太多的方法都是OSX开发才能使用的库，比如`NSWorkSpace`，这玩意没法在iOS项目里用。发愁\n\n## JSPatchPlaygroundTool的目标\n\n当使用JSPatch进行一整个功能模块的开发，而不仅仅是只用来修改bug，能像ReactNative一样，run起app后，告别反锁的编译，运行，写出来的代码立刻就生效，代码出错也立刻报出来，丝毫不影响运行，重新修改好后，自然完美运作。\n\n# JSPatchPlayground的原理\n\n之前提到过JSPatch是天然支持这种playground的黑科技玩法的~\n\n原因就在于JSPatch的一个Extension`JPCleaner`，他可以让所有被JSPatch的hook的函数都恢复原样，这样将修改过最新的JS，重新执行以下，就实现了Reload的效果"
  },
  {
    "path": "Extensions/JPProtocol.h",
    "content": "//\n//  JPProtocol.h\n//  JSPatchDemo\n//\n//  Created by bang on 9/9/16.\n//  Copyright © 2016 bang. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import \"JPEngine.h\"\n\n@interface JPProtocol : JPExtension\n\n@end\n"
  },
  {
    "path": "Extensions/JPProtocol.m",
    "content": "//\n//  JPProtocol.m\n//  JSPatchDemo\n//\n//  Created by bang on 9/9/16.\n//  Copyright © 2016 bang. All rights reserved.\n//\n\n#import \"JPProtocol.h\"\n#import <objc/runtime.h>\n\n@implementation JPProtocol\n+ (void)main:(JSContext *)context\n{\n    context[@\"protocol\"] = ^id(NSString *protocolName) {\n        return objc_getProtocol([protocolName cStringUsingEncoding:NSUTF8StringEncoding]);\n    };\n}\n@end\n"
  },
  {
    "path": "Extensions/JPSpecialInit.h",
    "content": "//\n//  JPSpecialInit.h\n//  SwiftDemo\n//\n//  Created by KouArlen on 16/2/25.\n//  Copyright © 2016年 Arlen. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import <UIKit/UIKit.h>\n\n/**\n handle the Init of some Special Class\n https://github.com/bang590/JSPatch/issues/248\n \n */\n\n@interface JPSpecialInit : NSObject\n\n+ (NSCalendar *)calendarWithCalendarIdentifier:(NSString *)iden;\n\n#if TARGET_OS_IOS\n+ (UIWebView *)newWebView;\n#endif\n\n@end\n"
  },
  {
    "path": "Extensions/JPSpecialInit.m",
    "content": "//\n//  JPSpecialInit.m\n//  SwiftDemo\n//\n//  Created by KouArlen on 16/2/25.\n//  Copyright © 2016年 Arlen. All rights reserved.\n//\n\n#import \"JPSpecialInit.h\"\n\n@implementation JPSpecialInit\n\n+ (NSCalendar *)calendarWithCalendarIdentifier:(NSString *)iden\n{\n    return [[NSCalendar alloc] initWithCalendarIdentifier:iden];\n}\n\n#if TARGET_OS_IOS\n+ (UIWebView *)newWebView\n{\n    return [[UIWebView alloc] init];\n}\n#endif\n\n@end\n"
  },
  {
    "path": "JSPatch/JPEngine.h",
    "content": "//\n//  JPEngine.h\n//  JSPatch\n//\n//  Created by bang on 15/4/30.\n//  Copyright (c) 2015 bang. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n#import <JavaScriptCore/JavaScriptCore.h>\n\n\n@interface JPEngine : NSObject\n\n/*!\n @method\n @discussion start the JSPatch engine, execute only once.\n !Deprecated! will be call automatically before evaluate script\n */\n+ (void)startEngine;\n\n/*!\n @method\n @description Evaluate Javascript code from a file Path. Call it after +startEngine.\n @param filePath: The filePath of the Javascript code.\n @result The last value generated by the script.\n */\n+ (JSValue *)evaluateScriptWithPath:(NSString *)filePath;\n\n/*!\n @method\n @description Evaluate a string of JavaScript code. Call it after +startEngine.\n              The method will generate a default resouceURL named \"main.js\" to the Safari debugger.\n @param script: A string containing the JavaScript code to evaluate.\n @result The last value generated by the script.\n */\n+ (JSValue *)evaluateScript:(NSString *)script;\n\n/*!\n @method\n @description Return the JSPatch JavaScript execution environment.\n */\n+ (JSContext *)context;\n\n\n\n/*!\n @method\n @description Add JPExtension.\n @param extensions: An array containing class name string.\n */\n+ (void)addExtensions:(NSArray *)extensions;\n\n/*!\n @method\n @description add new struct type supporting to JS\n @param defineDict: the definition of struct, for Example:\n    @{\n      @\"name\": @\"CGAffineTransform\",   //struct name\n      @\"types\": @\"ffffff\",  //struct types\n      @\"keys\": @[@\"a\", @\"b\", @\"c\", @\"d\", @\"tx\", @\"ty\"]  //struct keys in JS\n    }\n */\n+ (void)defineStruct:(NSDictionary *)defineDict;\n\n+ (void)handleException:(void (^)(NSString *msg))exceptionBlock;\n@end\n\n\n\n@interface JPExtension : NSObject\n+ (void)main:(JSContext *)context;\n\n+ (void *)formatPointerJSToOC:(JSValue *)val;\n+ (id)formatRetainedCFTypeOCToJS:(CFTypeRef)CF_CONSUMED type;\n+ (id)formatPointerOCToJS:(void *)pointer;\n+ (id)formatJSToOC:(JSValue *)val;\n+ (id)formatOCToJS:(id)obj;\n\n+ (int)sizeOfStructTypes:(NSString *)structTypes;\n+ (void)getStructDataWidthDict:(void *)structData dict:(NSDictionary *)dict structDefine:(NSDictionary *)structDefine;\n+ (NSDictionary *)getDictOfStruct:(void *)structData structDefine:(NSDictionary *)structDefine;\n\n/*!\n @method\n @description Return the registered struct definition in JSPatch,\n the key of dictionary is the struct name.\n */\n+ (NSMutableDictionary *)registeredStruct;\n\n+ (NSDictionary *)overideMethods;\n+ (NSMutableSet *)includedScriptPaths;\n@end\n\n\n\n@interface JPBoxing : NSObject\n@property (nonatomic) id obj;\n@property (nonatomic) void *pointer;\n@property (nonatomic) Class cls;\n@property (nonatomic, weak) id weakObj;\n@property (nonatomic, assign) id assignObj;\n- (id)unbox;\n- (void *)unboxPointer;\n- (Class)unboxClass;\n@end\n\n"
  },
  {
    "path": "JSPatch/JPEngine.m",
    "content": "//  JPEngine.m\n//  JSPatch\n//\n//  Created by bang on 15/4/30.\n//  Copyright (c) 2015 bang. All rights reserved.\n//\n\n#import \"JPEngine.h\"\n#import <objc/runtime.h>\n#import <objc/message.h>\n\n#if TARGET_OS_IPHONE\n#import <UIKit/UIApplication.h>\n#endif\n\n#if CGFLOAT_IS_DOUBLE\n#define CGFloatValue doubleValue\n#else\n#define CGFloatValue floatValue\n#endif\n\n@implementation JPBoxing\n\n#define JPBOXING_GEN(_name, _prop, _type) \\\n+ (instancetype)_name:(_type)obj  \\\n{   \\\n    JPBoxing *boxing = [[JPBoxing alloc] init]; \\\n    boxing._prop = obj;   \\\n    return boxing;  \\\n}\n\nJPBOXING_GEN(boxObj, obj, id)\nJPBOXING_GEN(boxPointer, pointer, void *)\nJPBOXING_GEN(boxClass, cls, Class)\nJPBOXING_GEN(boxWeakObj, weakObj, id)\nJPBOXING_GEN(boxAssignObj, assignObj, id)\n\n- (id)unbox\n{\n    if (self.obj) return self.obj;\n    if (self.weakObj) return self.weakObj;\n    if (self.assignObj) return self.assignObj;\n    if (self.cls) return self.cls;\n    return self;\n}\n- (void *)unboxPointer\n{\n    return self.pointer;\n}\n- (Class)unboxClass\n{\n    return self.cls;\n}\n@end\n\n#pragma mark - Fix iOS7 NSInvocation fatal error\n// A fatal error of NSInvocation on iOS7.0.\n// A invocation return 0 when the return type is double/float.\n// http://stackoverflow.com/questions/19874502/nsinvocation-getreturnvalue-with-double-value-produces-0-unexpectedly\n\ntypedef struct {double d;} JPDouble;\ntypedef struct {float f;} JPFloat;\n\nstatic NSMethodSignature *fixSignature(NSMethodSignature *signature)\n{\n#if TARGET_OS_IPHONE\n#ifdef __LP64__\n    if (!signature) {\n        return nil;\n    }\n    \n    if ([[UIDevice currentDevice].systemVersion floatValue] < 7.09) {\n        BOOL isReturnDouble = (strcmp([signature methodReturnType], \"d\") == 0);\n        BOOL isReturnFloat = (strcmp([signature methodReturnType], \"f\") == 0);\n\n        if (isReturnDouble || isReturnFloat) {\n            NSMutableString *types = [NSMutableString stringWithFormat:@\"%s@:\", isReturnDouble ? @encode(JPDouble) : @encode(JPFloat)];\n            for (int i = 2; i < signature.numberOfArguments; i++) {\n                const char *argType = [signature getArgumentTypeAtIndex:i];\n                [types appendFormat:@\"%s\", argType];\n            }\n            signature = [NSMethodSignature signatureWithObjCTypes:[types UTF8String]];\n        }\n    }\n#endif\n#endif\n    return signature;\n}\n\n@interface NSObject (JPFix)\n- (NSMethodSignature *)jp_methodSignatureForSelector:(SEL)aSelector;\n+ (void)jp_fixMethodSignature;\n@end\n\n@implementation NSObject (JPFix)\nconst static void *JPFixedFlagKey = &JPFixedFlagKey;\n- (NSMethodSignature *)jp_methodSignatureForSelector:(SEL)aSelector\n{\n    NSMethodSignature *signature = [self jp_methodSignatureForSelector:aSelector];\n    return fixSignature(signature);\n}\n+ (void)jp_fixMethodSignature\n{\n#if TARGET_OS_IPHONE\n#ifdef __LP64__\n    if ([[UIDevice currentDevice].systemVersion floatValue] < 7.1) {\n        NSNumber *flag = objc_getAssociatedObject(self, JPFixedFlagKey);\n        if (!flag.boolValue) {\n            SEL originalSelector = @selector(methodSignatureForSelector:);\n            SEL swizzledSelector = @selector(jp_methodSignatureForSelector:);\n            Method originalMethod = class_getInstanceMethod(self, originalSelector);\n            Method swizzledMethod = class_getInstanceMethod(self, swizzledSelector);\n            BOOL didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));\n            if (didAddMethod) {\n                class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));\n            } else {\n                method_exchangeImplementations(originalMethod, swizzledMethod);\n            }\n            objc_setAssociatedObject(self, JPFixedFlagKey, @YES, OBJC_ASSOCIATION_RETAIN_NONATOMIC);\n        }\n    }\n#endif\n#endif\n}\n@end\n\n#pragma mark -\n\nstatic JSContext *_context;\nstatic NSString *_regexStr = @\"(?<!\\\\\\\\)\\\\.\\\\s*(\\\\w+)\\\\s*\\\\(\";\nstatic NSString *_replaceStr = @\".__c(\\\"$1\\\")(\";\nstatic NSRegularExpression* _regex;\nstatic NSObject *_nullObj;\nstatic NSObject *_nilObj;\nstatic NSMutableDictionary *_registeredStruct;\nstatic NSMutableDictionary *_currInvokeSuperClsName;\nstatic char *kPropAssociatedObjectKey;\nstatic BOOL _autoConvert;\nstatic BOOL _convertOCNumberToString;\nstatic NSString *_scriptRootDir;\nstatic NSMutableSet *_runnedScript;\n\nstatic NSMutableDictionary *_JSOverideMethods;\nstatic NSMutableDictionary *_TMPMemoryPool;\nstatic NSMutableDictionary *_propKeys;\nstatic NSMutableDictionary *_JSMethodSignatureCache;\nstatic NSLock              *_JSMethodSignatureLock;\nstatic NSRecursiveLock     *_JSMethodForwardCallLock;\nstatic NSMutableDictionary *_protocolTypeEncodeDict;\nstatic NSMutableArray      *_pointersToRelease;\n\n#ifdef DEBUG\nstatic NSArray *_JSLastCallStack;\n#endif\n\nstatic void (^_exceptionBlock)(NSString *log) = ^void(NSString *log) {\n    NSCAssert(NO, log);\n};\n\n@implementation JPEngine\n\n#pragma clang diagnostic push\n#pragma clang diagnostic ignored \"-Wundeclared-selector\"\n\n#pragma mark - APIS\n\n+ (void)startEngine\n{\n    if (![JSContext class] || _context) {\n        return;\n    }\n    \n    JSContext *context = [[JSContext alloc] init];\n    \n#ifdef DEBUG\n    context[@\"po\"] = ^JSValue*(JSValue *obj) {\n        id ocObject = formatJSToOC(obj);\n        return [JSValue valueWithObject:[ocObject description] inContext:_context];\n    };\n\n    context[@\"bt\"] = ^JSValue*() {\n        return [JSValue valueWithObject:_JSLastCallStack inContext:_context];\n    };\n#endif\n\n    context[@\"_OC_defineClass\"] = ^(NSString *classDeclaration, JSValue *instanceMethods, JSValue *classMethods) {\n        return defineClass(classDeclaration, instanceMethods, classMethods);\n    };\n\n    context[@\"_OC_defineProtocol\"] = ^(NSString *protocolDeclaration, JSValue *instProtocol, JSValue *clsProtocol) {\n        return defineProtocol(protocolDeclaration, instProtocol,clsProtocol);\n    };\n    \n    context[@\"_OC_callI\"] = ^id(JSValue *obj, NSString *selectorName, JSValue *arguments, BOOL isSuper) {\n        return callSelector(nil, selectorName, arguments, obj, isSuper);\n    };\n    context[@\"_OC_callC\"] = ^id(NSString *className, NSString *selectorName, JSValue *arguments) {\n        return callSelector(className, selectorName, arguments, nil, NO);\n    };\n    context[@\"_OC_formatJSToOC\"] = ^id(JSValue *obj) {\n        return formatJSToOC(obj);\n    };\n    \n    context[@\"_OC_formatOCToJS\"] = ^id(JSValue *obj) {\n        return formatOCToJS([obj toObject]);\n    };\n    \n    context[@\"_OC_getCustomProps\"] = ^id(JSValue *obj) {\n        id realObj = formatJSToOC(obj);\n        return objc_getAssociatedObject(realObj, kPropAssociatedObjectKey);\n    };\n    \n    context[@\"_OC_setCustomProps\"] = ^(JSValue *obj, JSValue *val) {\n        id realObj = formatJSToOC(obj);\n        objc_setAssociatedObject(realObj, kPropAssociatedObjectKey, val, OBJC_ASSOCIATION_RETAIN_NONATOMIC);\n    };\n    \n    context[@\"__weak\"] = ^id(JSValue *jsval) {\n        id obj = formatJSToOC(jsval);\n        return [[JSContext currentContext][@\"_formatOCToJS\"] callWithArguments:@[formatOCToJS([JPBoxing boxWeakObj:obj])]];\n    };\n\n    context[@\"__strong\"] = ^id(JSValue *jsval) {\n        id obj = formatJSToOC(jsval);\n        return [[JSContext currentContext][@\"_formatOCToJS\"] callWithArguments:@[formatOCToJS(obj)]];\n    };\n    \n    context[@\"_OC_superClsName\"] = ^(NSString *clsName) {\n        Class cls = NSClassFromString(clsName);\n        return NSStringFromClass([cls superclass]);\n    };\n    \n    context[@\"autoConvertOCType\"] = ^(BOOL autoConvert) {\n        _autoConvert = autoConvert;\n    };\n\n    context[@\"convertOCNumberToString\"] = ^(BOOL convertOCNumberToString) {\n        _convertOCNumberToString = convertOCNumberToString;\n    };\n    \n    context[@\"include\"] = ^(NSString *filePath) {\n        NSString *absolutePath = [_scriptRootDir stringByAppendingPathComponent:filePath];\n        if (!_runnedScript) {\n            _runnedScript = [[NSMutableSet alloc] init];\n        }\n        if (absolutePath && ![_runnedScript containsObject:absolutePath]) {\n            [JPEngine _evaluateScriptWithPath:absolutePath];\n            [_runnedScript addObject:absolutePath];\n        }\n    };\n    \n    context[@\"resourcePath\"] = ^(NSString *filePath) {\n        return [_scriptRootDir stringByAppendingPathComponent:filePath];\n    };\n\n    context[@\"dispatch_after\"] = ^(double time, JSValue *func) {\n        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(time * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{\n            [func callWithArguments:nil];\n        });\n    };\n    \n    context[@\"dispatch_async_main\"] = ^(JSValue *func) {\n        dispatch_async(dispatch_get_main_queue(), ^{\n            [func callWithArguments:nil];\n        });\n    };\n    \n    context[@\"dispatch_sync_main\"] = ^(JSValue *func) {\n        if ([NSThread currentThread].isMainThread) {\n            [func callWithArguments:nil];\n        } else {\n            dispatch_sync(dispatch_get_main_queue(), ^{\n                [func callWithArguments:nil];\n            });\n        }\n    };\n    \n    context[@\"dispatch_async_global_queue\"] = ^(JSValue *func) {\n        dispatch_async(dispatch_get_global_queue(0, 0), ^{\n            [func callWithArguments:nil];\n        });\n    };\n    \n    context[@\"releaseTmpObj\"] = ^void(JSValue *jsVal) {\n        if ([[jsVal toObject] isKindOfClass:[NSDictionary class]]) {\n            void *pointer =  [(JPBoxing *)([jsVal toObject][@\"__obj\"]) unboxPointer];\n            id obj = *((__unsafe_unretained id *)pointer);\n            @synchronized(_TMPMemoryPool) {\n                [_TMPMemoryPool removeObjectForKey:[NSNumber numberWithInteger:[(NSObject*)obj hash]]];\n            }\n        }\n    };\n    \n    context[@\"_OC_log\"] = ^() {\n        NSArray *args = [JSContext currentArguments];\n        for (JSValue *jsVal in args) {\n            id obj = formatJSToOC(jsVal);\n            NSLog(@\"JSPatch.log: %@\", obj == _nilObj ? nil : (obj == _nullObj ? [NSNull null]: obj));\n        }\n    };\n    \n    context[@\"_OC_catch\"] = ^(JSValue *msg, JSValue *stack) {\n        _exceptionBlock([NSString stringWithFormat:@\"js exception, \\nmsg: %@, \\nstack: \\n %@\", [msg toObject], [stack toObject]]);\n    };\n    \n    context.exceptionHandler = ^(JSContext *con, JSValue *exception) {\n        NSLog(@\"%@\", exception);\n        _exceptionBlock([NSString stringWithFormat:@\"js exception: %@\", exception]);\n    };\n    \n    _nullObj = [[NSObject alloc] init];\n    context[@\"_OC_null\"] = formatOCToJS(_nullObj);\n    \n    _context = context;\n    \n    _nilObj = [[NSObject alloc] init];\n    _JSMethodSignatureLock = [[NSLock alloc] init];\n    _JSMethodForwardCallLock = [[NSRecursiveLock alloc] init];\n    _registeredStruct = [[NSMutableDictionary alloc] init];\n    _currInvokeSuperClsName = [[NSMutableDictionary alloc] init];\n    \n#if TARGET_OS_IPHONE\n    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleMemoryWarning) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];\n#endif\n    \n    NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@\"JSPatch\" ofType:@\"js\"];\n    if (!path) _exceptionBlock(@\"can't find JSPatch.js\");\n    NSString *jsCore = [[NSString alloc] initWithData:[[NSFileManager defaultManager] contentsAtPath:path] encoding:NSUTF8StringEncoding];\n    \n    if ([_context respondsToSelector:@selector(evaluateScript:withSourceURL:)]) {\n        [_context evaluateScript:jsCore withSourceURL:[NSURL URLWithString:@\"JSPatch.js\"]];\n    } else {\n        [_context evaluateScript:jsCore];\n    }\n}\n\n+ (JSValue *)evaluateScript:(NSString *)script\n{\n    return [self _evaluateScript:script withSourceURL:[NSURL URLWithString:@\"main.js\"]];\n}\n\n+ (JSValue *)evaluateScriptWithPath:(NSString *)filePath\n{\n    _scriptRootDir = [filePath stringByDeletingLastPathComponent];\n    return [self _evaluateScriptWithPath:filePath];\n}\n\n+ (JSValue *)_evaluateScriptWithPath:(NSString *)filePath\n{\n    NSString *script = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];\n    return [self _evaluateScript:script withSourceURL:[NSURL URLWithString:[filePath lastPathComponent]]];\n}\n\n+ (JSValue *)_evaluateScript:(NSString *)script withSourceURL:(NSURL *)resourceURL\n{\n    if (!script || ![JSContext class]) {\n        _exceptionBlock(@\"script is nil\");\n        return nil;\n    }\n    [self startEngine];\n    \n    if (!_regex) {\n        _regex = [NSRegularExpression regularExpressionWithPattern:_regexStr options:0 error:nil];\n    }\n    NSString *formatedScript = [NSString stringWithFormat:@\";(function(){try{\\n%@\\n}catch(e){_OC_catch(e.message, e.stack)}})();\", [_regex stringByReplacingMatchesInString:script options:0 range:NSMakeRange(0, script.length) withTemplate:_replaceStr]];\n    @try {\n        if ([_context respondsToSelector:@selector(evaluateScript:withSourceURL:)]) {\n            return [_context evaluateScript:formatedScript withSourceURL:resourceURL];\n        } else {\n            return [_context evaluateScript:formatedScript];\n        }\n    }\n    @catch (NSException *exception) {\n        _exceptionBlock([NSString stringWithFormat:@\"%@\", exception]);\n    }\n    return nil;\n}\n\n+ (JSContext *)context\n{\n    return _context;\n}\n\n+ (void)addExtensions:(NSArray *)extensions\n{\n    if (![JSContext class]) {\n        return;\n    }\n    if (!_context) _exceptionBlock(@\"please call [JPEngine startEngine]\");\n    for (NSString *className in extensions) {\n        Class extCls = NSClassFromString(className);\n        [extCls main:_context];\n    }\n}\n\n+ (void)defineStruct:(NSDictionary *)defineDict\n{\n    @synchronized (_context) {\n        [_registeredStruct setObject:defineDict forKey:defineDict[@\"name\"]];\n    }\n}\n\n+ (void)handleMemoryWarning {\n    [_JSMethodSignatureLock lock];\n    _JSMethodSignatureCache = nil;\n    [_JSMethodSignatureLock unlock];\n}\n\n+ (void)handleException:(void (^)(NSString *msg))exceptionBlock\n{\n    _exceptionBlock = [exceptionBlock copy];\n}\n\n#pragma mark - Implements\n\nstatic const void *propKey(NSString *propName) {\n    if (!_propKeys) _propKeys = [[NSMutableDictionary alloc] init];\n    id key = _propKeys[propName];\n    if (!key) {\n        key = [propName copy];\n        [_propKeys setObject:key forKey:propName];\n    }\n    return (__bridge const void *)(key);\n}\nstatic id getPropIMP(id slf, SEL selector, NSString *propName) {\n    return objc_getAssociatedObject(slf, propKey(propName));\n}\nstatic void setPropIMP(id slf, SEL selector, id val, NSString *propName) {\n    objc_setAssociatedObject(slf, propKey(propName), val, OBJC_ASSOCIATION_RETAIN_NONATOMIC);\n}\n\nstatic char *methodTypesInProtocol(NSString *protocolName, NSString *selectorName, BOOL isInstanceMethod, BOOL isRequired)\n{\n    Protocol *protocol = objc_getProtocol([trim(protocolName) cStringUsingEncoding:NSUTF8StringEncoding]);\n    unsigned int selCount = 0;\n    struct objc_method_description *methods = protocol_copyMethodDescriptionList(protocol, isRequired, isInstanceMethod, &selCount);\n    for (int i = 0; i < selCount; i ++) {\n        if ([selectorName isEqualToString:NSStringFromSelector(methods[i].name)]) {\n            char *types = malloc(strlen(methods[i].types) + 1);\n            strcpy(types, methods[i].types);\n            free(methods);\n            return types;\n        }\n    }\n    free(methods);\n    return NULL;\n}\n\nstatic void defineProtocol(NSString *protocolDeclaration, JSValue *instProtocol, JSValue *clsProtocol)\n{\n    const char *protocolName = [protocolDeclaration UTF8String];\n    Protocol* newprotocol = objc_allocateProtocol(protocolName);\n    if (newprotocol) {\n        addGroupMethodsToProtocol(newprotocol, instProtocol, YES);\n        addGroupMethodsToProtocol(newprotocol, clsProtocol, NO);\n        objc_registerProtocol(newprotocol);\n    }\n}\n\nstatic void addGroupMethodsToProtocol(Protocol* protocol,JSValue *groupMethods,BOOL isInstance)\n{\n    NSDictionary *groupDic = [groupMethods toDictionary];\n    for (NSString *jpSelector in groupDic.allKeys) {\n        NSDictionary *methodDict = groupDic[jpSelector];\n        NSString *paraString = methodDict[@\"paramsType\"];\n        NSString *returnString = methodDict[@\"returnType\"] && [methodDict[@\"returnType\"] length] > 0 ? methodDict[@\"returnType\"] : @\"void\";\n        NSString *typeEncode = methodDict[@\"typeEncode\"];\n        \n        NSArray *argStrArr = [paraString componentsSeparatedByString:@\",\"];\n        NSString *selectorName = convertJPSelectorString(jpSelector);\n        \n        if ([selectorName componentsSeparatedByString:@\":\"].count - 1 < argStrArr.count) {\n            selectorName = [selectorName stringByAppendingString:@\":\"];\n        }\n\n        if (typeEncode) {\n            addMethodToProtocol(protocol, selectorName, typeEncode, isInstance);\n            \n        } else {\n            if (!_protocolTypeEncodeDict) {\n                _protocolTypeEncodeDict = [[NSMutableDictionary alloc] init];\n                #define JP_DEFINE_TYPE_ENCODE_CASE(_type) \\\n                    [_protocolTypeEncodeDict setObject:[NSString stringWithUTF8String:@encode(_type)] forKey:@#_type];\\\n\n                JP_DEFINE_TYPE_ENCODE_CASE(id);\n                JP_DEFINE_TYPE_ENCODE_CASE(BOOL);\n                JP_DEFINE_TYPE_ENCODE_CASE(int);\n                JP_DEFINE_TYPE_ENCODE_CASE(void);\n                JP_DEFINE_TYPE_ENCODE_CASE(char);\n                JP_DEFINE_TYPE_ENCODE_CASE(short);\n                JP_DEFINE_TYPE_ENCODE_CASE(unsigned short);\n                JP_DEFINE_TYPE_ENCODE_CASE(unsigned int);\n                JP_DEFINE_TYPE_ENCODE_CASE(long);\n                JP_DEFINE_TYPE_ENCODE_CASE(unsigned long);\n                JP_DEFINE_TYPE_ENCODE_CASE(long long);\n                JP_DEFINE_TYPE_ENCODE_CASE(float);\n                JP_DEFINE_TYPE_ENCODE_CASE(double);\n                JP_DEFINE_TYPE_ENCODE_CASE(CGFloat);\n                JP_DEFINE_TYPE_ENCODE_CASE(CGSize);\n                JP_DEFINE_TYPE_ENCODE_CASE(CGRect);\n                JP_DEFINE_TYPE_ENCODE_CASE(CGPoint);\n                JP_DEFINE_TYPE_ENCODE_CASE(CGVector);\n                JP_DEFINE_TYPE_ENCODE_CASE(NSRange);\n                JP_DEFINE_TYPE_ENCODE_CASE(NSInteger);\n                JP_DEFINE_TYPE_ENCODE_CASE(Class);\n                JP_DEFINE_TYPE_ENCODE_CASE(SEL);\n                JP_DEFINE_TYPE_ENCODE_CASE(void*);\n#if TARGET_OS_IPHONE\n                JP_DEFINE_TYPE_ENCODE_CASE(UIEdgeInsets);\n#else\n                JP_DEFINE_TYPE_ENCODE_CASE(NSEdgeInsets);\n#endif\n\n                [_protocolTypeEncodeDict setObject:@\"@?\" forKey:@\"block\"];\n                [_protocolTypeEncodeDict setObject:@\"^@\" forKey:@\"id*\"];\n            }\n            \n            NSString *returnEncode = _protocolTypeEncodeDict[returnString];\n            if (returnEncode.length > 0) {\n                NSMutableString *encode = [returnEncode mutableCopy];\n                [encode appendString:@\"@:\"];\n                for (NSInteger i = 0; i < argStrArr.count; i++) {\n                    NSString *argStr = trim([argStrArr objectAtIndex:i]);\n                    NSString *argEncode = _protocolTypeEncodeDict[argStr];\n                    if (!argEncode) {\n                        NSString *argClassName = trim([argStr stringByReplacingOccurrencesOfString:@\"*\" withString:@\"\"]);\n                        if (NSClassFromString(argClassName) != NULL) {\n                            argEncode = @\"@\";\n                        } else {\n                            _exceptionBlock([NSString stringWithFormat:@\"unreconized type %@\", argStr]);\n                            return;\n                        }\n                    }\n                    [encode appendString:argEncode];\n                }\n                addMethodToProtocol(protocol, selectorName, encode, isInstance);\n            }\n        }\n    }\n}\n\nstatic void addMethodToProtocol(Protocol* protocol, NSString *selectorName, NSString *typeencoding, BOOL isInstance)\n{\n    SEL sel = NSSelectorFromString(selectorName);\n    const char* type = [typeencoding UTF8String];\n    protocol_addMethodDescription(protocol, sel, type, YES, isInstance);\n}\n\nstatic NSDictionary *defineClass(NSString *classDeclaration, JSValue *instanceMethods, JSValue *classMethods)\n{\n    NSScanner *scanner = [NSScanner scannerWithString:classDeclaration];\n    \n    NSString *className;\n    NSString *superClassName;\n    NSString *protocolNames;\n    [scanner scanUpToString:@\":\" intoString:&className];\n    if (!scanner.isAtEnd) {\n        scanner.scanLocation = scanner.scanLocation + 1;\n        [scanner scanUpToString:@\"<\" intoString:&superClassName];\n        if (!scanner.isAtEnd) {\n            scanner.scanLocation = scanner.scanLocation + 1;\n            [scanner scanUpToString:@\">\" intoString:&protocolNames];\n        }\n    }\n    \n    if (!superClassName) superClassName = @\"NSObject\";\n    className = trim(className);\n    superClassName = trim(superClassName);\n    \n    NSArray *protocols = [protocolNames length] ? [protocolNames componentsSeparatedByString:@\",\"] : nil;\n    \n    Class cls = NSClassFromString(className);\n    if (!cls) {\n        Class superCls = NSClassFromString(superClassName);\n        if (!superCls) {\n            _exceptionBlock([NSString stringWithFormat:@\"can't find the super class %@\", superClassName]);\n            return @{@\"cls\": className};\n        }\n        cls = objc_allocateClassPair(superCls, className.UTF8String, 0);\n        objc_registerClassPair(cls);\n    }\n    \n    if (protocols.count > 0) {\n        for (NSString* protocolName in protocols) {\n            Protocol *protocol = objc_getProtocol([trim(protocolName) cStringUsingEncoding:NSUTF8StringEncoding]);\n            class_addProtocol (cls, protocol);\n        }\n    }\n    \n    for (int i = 0; i < 2; i ++) {\n        BOOL isInstance = i == 0;\n        JSValue *jsMethods = isInstance ? instanceMethods: classMethods;\n        \n        Class currCls = isInstance ? cls: objc_getMetaClass(className.UTF8String);\n        NSDictionary *methodDict = [jsMethods toDictionary];\n        for (NSString *jsMethodName in methodDict.allKeys) {\n            JSValue *jsMethodArr = [jsMethods valueForProperty:jsMethodName];\n            int numberOfArg = [jsMethodArr[0] toInt32];\n            NSString *selectorName = convertJPSelectorString(jsMethodName);\n            \n            if ([selectorName componentsSeparatedByString:@\":\"].count - 1 < numberOfArg) {\n                selectorName = [selectorName stringByAppendingString:@\":\"];\n            }\n            \n            JSValue *jsMethod = jsMethodArr[1];\n            if (class_respondsToSelector(currCls, NSSelectorFromString(selectorName))) {\n                overrideMethod(currCls, selectorName, jsMethod, !isInstance, NULL);\n            } else {\n                BOOL overrided = NO;\n                for (NSString *protocolName in protocols) {\n                    char *types = methodTypesInProtocol(protocolName, selectorName, isInstance, YES);\n                    if (!types) types = methodTypesInProtocol(protocolName, selectorName, isInstance, NO);\n                    if (types) {\n                        overrideMethod(currCls, selectorName, jsMethod, !isInstance, types);\n                        free(types);\n                        overrided = YES;\n                        break;\n                    }\n                }\n                if (!overrided) {\n                    if (![[jsMethodName substringToIndex:1] isEqualToString:@\"_\"]) {\n                        NSMutableString *typeDescStr = [@\"@@:\" mutableCopy];\n                        for (int i = 0; i < numberOfArg; i ++) {\n                            [typeDescStr appendString:@\"@\"];\n                        }\n                        overrideMethod(currCls, selectorName, jsMethod, !isInstance, [typeDescStr cStringUsingEncoding:NSUTF8StringEncoding]);\n                    }\n                }\n            }\n        }\n    }\n    \n    class_addMethod(cls, @selector(getProp:), (IMP)getPropIMP, \"@@:@\");\n    class_addMethod(cls, @selector(setProp:forKey:), (IMP)setPropIMP, \"v@:@@\");\n\n    return @{@\"cls\": className, @\"superCls\": superClassName};\n}\n\nstatic JSValue *getJSFunctionInObjectHierachy(id slf, NSString *selectorName)\n{\n    Class cls = object_getClass(slf);\n    if (_currInvokeSuperClsName[selectorName]) {\n        cls = NSClassFromString(_currInvokeSuperClsName[selectorName]);\n        selectorName = [selectorName stringByReplacingOccurrencesOfString:@\"_JPSUPER_\" withString:@\"_JP\"];\n    }\n    JSValue *func = _JSOverideMethods[cls][selectorName];\n    while (!func) {\n        cls = class_getSuperclass(cls);\n        if (!cls) {\n            return nil;\n        }\n        func = _JSOverideMethods[cls][selectorName];\n    }\n    return func;\n}\n\nstatic void JPForwardInvocation(__unsafe_unretained id assignSlf, SEL selector, NSInvocation *invocation)\n{\n    \n#ifdef DEBUG\n    _JSLastCallStack = [NSThread callStackSymbols];\n#endif\n    BOOL deallocFlag = NO;\n    id slf = assignSlf;\n    BOOL isBlock = [[assignSlf class] isSubclassOfClass : NSClassFromString(@\"NSBlock\")];\n    \n    NSMethodSignature *methodSignature = [invocation methodSignature];\n    NSInteger numberOfArguments = [methodSignature numberOfArguments];\n    NSString *selectorName = isBlock ? @\"\" : NSStringFromSelector(invocation.selector);\n    NSString *JPSelectorName = [NSString stringWithFormat:@\"_JP%@\", selectorName];\n    JSValue *jsFunc = isBlock ? objc_getAssociatedObject(assignSlf, \"_JSValue\")[@\"cb\"] : getJSFunctionInObjectHierachy(slf, JPSelectorName);\n    if (!jsFunc) {\n        JPExecuteORIGForwardInvocation(slf, selector, invocation);\n        return;\n    }\n    \n    NSMutableArray *argList = [[NSMutableArray alloc] init];\n    if (!isBlock) {\n        if ([slf class] == slf) {\n            [argList addObject:[JSValue valueWithObject:@{@\"__clsName\": NSStringFromClass([slf class])} inContext:_context]];\n        } else if ([selectorName isEqualToString:@\"dealloc\"]) {\n            [argList addObject:[JPBoxing boxAssignObj:slf]];\n            deallocFlag = YES;\n        } else {\n            [argList addObject:[JPBoxing boxWeakObj:slf]];\n        }\n    }\n    \n    for (NSUInteger i = isBlock ? 1 : 2; i < numberOfArguments; i++) {\n        const char *argumentType = [methodSignature getArgumentTypeAtIndex:i];\n        switch(argumentType[0] == 'r' ? argumentType[1] : argumentType[0]) {\n        \n            #define JP_FWD_ARG_CASE(_typeChar, _type) \\\n            case _typeChar: {   \\\n                _type arg;  \\\n                [invocation getArgument:&arg atIndex:i];    \\\n                [argList addObject:@(arg)]; \\\n                break;  \\\n            }\n            JP_FWD_ARG_CASE('c', char)\n            JP_FWD_ARG_CASE('C', unsigned char)\n            JP_FWD_ARG_CASE('s', short)\n            JP_FWD_ARG_CASE('S', unsigned short)\n            JP_FWD_ARG_CASE('i', int)\n            JP_FWD_ARG_CASE('I', unsigned int)\n            JP_FWD_ARG_CASE('l', long)\n            JP_FWD_ARG_CASE('L', unsigned long)\n            JP_FWD_ARG_CASE('q', long long)\n            JP_FWD_ARG_CASE('Q', unsigned long long)\n            JP_FWD_ARG_CASE('f', float)\n            JP_FWD_ARG_CASE('d', double)\n            JP_FWD_ARG_CASE('B', BOOL)\n            case '@': {\n                __unsafe_unretained id arg;\n                [invocation getArgument:&arg atIndex:i];\n                if ([arg isKindOfClass:NSClassFromString(@\"NSBlock\")]) {\n                    [argList addObject:(arg ? [arg copy]: _nilObj)];\n                } else {\n                    [argList addObject:(arg ? arg: _nilObj)];\n                }\n                break;\n            }\n            case '{': {\n                NSString *typeString = extractStructName([NSString stringWithUTF8String:argumentType]);\n                #define JP_FWD_ARG_STRUCT(_type, _transFunc) \\\n                if ([typeString rangeOfString:@#_type].location != NSNotFound) {    \\\n                    _type arg; \\\n                    [invocation getArgument:&arg atIndex:i];    \\\n                    [argList addObject:[JSValue _transFunc:arg inContext:_context]];  \\\n                    break; \\\n                }\n                JP_FWD_ARG_STRUCT(CGRect, valueWithRect)\n                JP_FWD_ARG_STRUCT(CGPoint, valueWithPoint)\n                JP_FWD_ARG_STRUCT(CGSize, valueWithSize)\n                JP_FWD_ARG_STRUCT(NSRange, valueWithRange)\n                \n                @synchronized (_context) {\n                    NSDictionary *structDefine = _registeredStruct[typeString];\n                    if (structDefine) {\n                        size_t size = sizeOfStructTypes(structDefine[@\"types\"]);\n                        if (size) {\n                            void *ret = malloc(size);\n                            [invocation getArgument:ret atIndex:i];\n                            NSDictionary *dict = getDictOfStruct(ret, structDefine);\n                            [argList addObject:[JSValue valueWithObject:dict inContext:_context]];\n                            free(ret);\n                            break;\n                        }\n                    }\n                }\n                \n                break;\n            }\n            case ':': {\n                SEL selector;\n                [invocation getArgument:&selector atIndex:i];\n                NSString *selectorName = NSStringFromSelector(selector);\n                [argList addObject:(selectorName ? selectorName: _nilObj)];\n                break;\n            }\n            case '^':\n            case '*': {\n                void *arg;\n                [invocation getArgument:&arg atIndex:i];\n                [argList addObject:[JPBoxing boxPointer:arg]];\n                break;\n            }\n            case '#': {\n                Class arg;\n                [invocation getArgument:&arg atIndex:i];\n                [argList addObject:[JPBoxing boxClass:arg]];\n                break;\n            }\n            default: {\n                NSLog(@\"error type %s\", argumentType);\n                break;\n            }\n        }\n    }\n    \n    if (_currInvokeSuperClsName[selectorName]) {\n        Class cls = NSClassFromString(_currInvokeSuperClsName[selectorName]);\n        NSString *tmpSelectorName = [[selectorName stringByReplacingOccurrencesOfString:@\"_JPSUPER_\" withString:@\"_JP\"] stringByReplacingOccurrencesOfString:@\"SUPER_\" withString:@\"_JP\"];\n        if (!_JSOverideMethods[cls][tmpSelectorName]) {\n            NSString *ORIGSelectorName = [selectorName stringByReplacingOccurrencesOfString:@\"SUPER_\" withString:@\"ORIG\"];\n            [argList removeObjectAtIndex:0];\n            id retObj = callSelector(_currInvokeSuperClsName[selectorName], ORIGSelectorName, [JSValue valueWithObject:argList inContext:_context], [JSValue valueWithObject:@{@\"__obj\": slf, @\"__realClsName\": @\"\"} inContext:_context], NO);\n            id __autoreleasing ret = formatJSToOC([JSValue valueWithObject:retObj inContext:_context]);\n            [invocation setReturnValue:&ret];\n            return;\n        }\n    }\n    \n    NSArray *params = _formatOCToJSList(argList);\n    char returnType[255];\n    strcpy(returnType, [methodSignature methodReturnType]);\n    \n    // Restore the return type\n    if (strcmp(returnType, @encode(JPDouble)) == 0) {\n        strcpy(returnType, @encode(double));\n    }\n    if (strcmp(returnType, @encode(JPFloat)) == 0) {\n        strcpy(returnType, @encode(float));\n    }\n\n    switch (returnType[0] == 'r' ? returnType[1] : returnType[0]) {\n        #define JP_FWD_RET_CALL_JS \\\n            JSValue *jsval; \\\n            [_JSMethodForwardCallLock lock];   \\\n            jsval = [jsFunc callWithArguments:params]; \\\n            [_JSMethodForwardCallLock unlock]; \\\n            while (![jsval isNull] && ![jsval isUndefined] && [jsval hasProperty:@\"__isPerformInOC\"]) { \\\n                NSArray *args = nil;  \\\n                JSValue *cb = jsval[@\"cb\"]; \\\n                if ([jsval hasProperty:@\"sel\"]) {   \\\n                    id callRet = callSelector(![jsval[@\"clsName\"] isUndefined] ? [jsval[@\"clsName\"] toString] : nil, [jsval[@\"sel\"] toString], jsval[@\"args\"], ![jsval[@\"obj\"] isUndefined] ? jsval[@\"obj\"] : nil, NO);  \\\n                    args = @[[_context[@\"_formatOCToJS\"] callWithArguments:callRet ? @[callRet] : _formatOCToJSList(@[_nilObj])]];  \\\n                }   \\\n                [_JSMethodForwardCallLock lock];    \\\n                jsval = [cb callWithArguments:args];  \\\n                [_JSMethodForwardCallLock unlock];  \\\n            }\n\n        #define JP_FWD_RET_CASE_RET(_typeChar, _type, _retCode)   \\\n            case _typeChar : { \\\n                JP_FWD_RET_CALL_JS \\\n                _retCode \\\n                [invocation setReturnValue:&ret];\\\n                break;  \\\n            }\n\n        #define JP_FWD_RET_CASE(_typeChar, _type, _typeSelector)   \\\n            JP_FWD_RET_CASE_RET(_typeChar, _type, _type ret = [[jsval toObject] _typeSelector];)   \\\n\n        #define JP_FWD_RET_CODE_ID \\\n            id __autoreleasing ret = formatJSToOC(jsval); \\\n            if (ret == _nilObj ||   \\\n                ([ret isKindOfClass:[NSNumber class]] && strcmp([ret objCType], \"c\") == 0 && ![ret boolValue])) ret = nil;  \\\n\n        #define JP_FWD_RET_CODE_POINTER    \\\n            void *ret; \\\n            id obj = formatJSToOC(jsval); \\\n            if ([obj isKindOfClass:[JPBoxing class]]) { \\\n                ret = [((JPBoxing *)obj) unboxPointer]; \\\n            }\n\n        #define JP_FWD_RET_CODE_CLASS    \\\n            Class ret;   \\\n            ret = formatJSToOC(jsval);\n\n\n        #define JP_FWD_RET_CODE_SEL    \\\n            SEL ret;   \\\n            id obj = formatJSToOC(jsval); \\\n            if ([obj isKindOfClass:[NSString class]]) { \\\n                ret = NSSelectorFromString(obj); \\\n            }\n\n        JP_FWD_RET_CASE_RET('@', id, JP_FWD_RET_CODE_ID)\n        JP_FWD_RET_CASE_RET('^', void*, JP_FWD_RET_CODE_POINTER)\n        JP_FWD_RET_CASE_RET('*', void*, JP_FWD_RET_CODE_POINTER)\n        JP_FWD_RET_CASE_RET('#', Class, JP_FWD_RET_CODE_CLASS)\n        JP_FWD_RET_CASE_RET(':', SEL, JP_FWD_RET_CODE_SEL)\n\n        JP_FWD_RET_CASE('c', char, charValue)\n        JP_FWD_RET_CASE('C', unsigned char, unsignedCharValue)\n        JP_FWD_RET_CASE('s', short, shortValue)\n        JP_FWD_RET_CASE('S', unsigned short, unsignedShortValue)\n        JP_FWD_RET_CASE('i', int, intValue)\n        JP_FWD_RET_CASE('I', unsigned int, unsignedIntValue)\n        JP_FWD_RET_CASE('l', long, longValue)\n        JP_FWD_RET_CASE('L', unsigned long, unsignedLongValue)\n        JP_FWD_RET_CASE('q', long long, longLongValue)\n        JP_FWD_RET_CASE('Q', unsigned long long, unsignedLongLongValue)\n        JP_FWD_RET_CASE('f', float, floatValue)\n        JP_FWD_RET_CASE('d', double, doubleValue)\n        JP_FWD_RET_CASE('B', BOOL, boolValue)\n\n        case 'v': {\n            JP_FWD_RET_CALL_JS\n            break;\n        }\n        \n        case '{': {\n            NSString *typeString = extractStructName([NSString stringWithUTF8String:returnType]);\n            #define JP_FWD_RET_STRUCT(_type, _funcSuffix) \\\n            if ([typeString rangeOfString:@#_type].location != NSNotFound) {    \\\n                JP_FWD_RET_CALL_JS \\\n                _type ret = [jsval _funcSuffix]; \\\n                [invocation setReturnValue:&ret];\\\n                break;  \\\n            }\n            JP_FWD_RET_STRUCT(CGRect, toRect)\n            JP_FWD_RET_STRUCT(CGPoint, toPoint)\n            JP_FWD_RET_STRUCT(CGSize, toSize)\n            JP_FWD_RET_STRUCT(NSRange, toRange)\n            \n            @synchronized (_context) {\n                NSDictionary *structDefine = _registeredStruct[typeString];\n                if (structDefine) {\n                    size_t size = sizeOfStructTypes(structDefine[@\"types\"]);\n                    JP_FWD_RET_CALL_JS\n                    void *ret = malloc(size);\n                    NSDictionary *dict = formatJSToOC(jsval);\n                    getStructDataWithDict(ret, dict, structDefine);\n                    [invocation setReturnValue:ret];\n                    free(ret);\n                }\n            }\n            break;\n        }\n        default: {\n            break;\n        }\n    }\n    \n    if (_pointersToRelease) {\n        for (NSValue *val in _pointersToRelease) {\n            void *pointer = NULL;\n            [val getValue:&pointer];\n            CFRelease(pointer);\n        }\n        _pointersToRelease = nil;\n    }\n    \n    if (deallocFlag) {\n        slf = nil;\n        Class instClass = object_getClass(assignSlf);\n        Method deallocMethod = class_getInstanceMethod(instClass, NSSelectorFromString(@\"ORIGdealloc\"));\n        void (*originalDealloc)(__unsafe_unretained id, SEL) = (__typeof__(originalDealloc))method_getImplementation(deallocMethod);\n        originalDealloc(assignSlf, NSSelectorFromString(@\"dealloc\"));\n    }\n}\n\nstatic void JPExecuteORIGForwardInvocation(id slf, SEL selector, NSInvocation *invocation)\n{\n    SEL origForwardSelector = @selector(ORIGforwardInvocation:);\n    \n    if ([slf respondsToSelector:origForwardSelector]) {\n        NSMethodSignature *methodSignature = [slf methodSignatureForSelector:origForwardSelector];\n        if (!methodSignature) {\n            _exceptionBlock([NSString stringWithFormat:@\"unrecognized selector -ORIGforwardInvocation: for instance %@\", slf]);\n            return;\n        }\n        NSInvocation *forwardInv= [NSInvocation invocationWithMethodSignature:methodSignature];\n        [forwardInv setTarget:slf];\n        [forwardInv setSelector:origForwardSelector];\n        [forwardInv setArgument:&invocation atIndex:2];\n        [forwardInv invoke];\n    } else {\n        Class superCls = [[slf class] superclass];\n        Method superForwardMethod = class_getInstanceMethod(superCls, @selector(forwardInvocation:));\n        void (*superForwardIMP)(id, SEL, NSInvocation *);\n        superForwardIMP = (void (*)(id, SEL, NSInvocation *))method_getImplementation(superForwardMethod);\n        superForwardIMP(slf, @selector(forwardInvocation:), invocation);\n    }\n}\n\nstatic void _initJPOverideMethods(Class cls) {\n    if (!_JSOverideMethods) {\n        _JSOverideMethods = [[NSMutableDictionary alloc] init];\n    }\n    if (!_JSOverideMethods[cls]) {\n        _JSOverideMethods[(id<NSCopying>)cls] = [[NSMutableDictionary alloc] init];\n    }\n}\n\nstatic void overrideMethod(Class cls, NSString *selectorName, JSValue *function, BOOL isClassMethod, const char *typeDescription)\n{\n    SEL selector = NSSelectorFromString(selectorName);\n    \n    if (!typeDescription) {\n        Method method = class_getInstanceMethod(cls, selector);\n        typeDescription = (char *)method_getTypeEncoding(method);\n    }\n    \n    IMP originalImp = class_respondsToSelector(cls, selector) ? class_getMethodImplementation(cls, selector) : NULL;\n    \n    IMP msgForwardIMP = _objc_msgForward;\n    #if !defined(__arm64__)\n        if (typeDescription[0] == '{') {\n            //In some cases that returns struct, we should use the '_stret' API:\n            //http://sealiesoftware.com/blog/archive/2008/10/30/objc_explain_objc_msgSend_stret.html\n            //NSMethodSignature knows the detail but has no API to return, we can only get the info from debugDescription.\n            NSMethodSignature *methodSignature = [NSMethodSignature signatureWithObjCTypes:typeDescription];\n            if ([methodSignature.debugDescription rangeOfString:@\"is special struct return? YES\"].location != NSNotFound) {\n                msgForwardIMP = (IMP)_objc_msgForward_stret;\n            }\n        }\n    #endif\n\n    if (class_getMethodImplementation(cls, @selector(forwardInvocation:)) != (IMP)JPForwardInvocation) {\n        IMP originalForwardImp = class_replaceMethod(cls, @selector(forwardInvocation:), (IMP)JPForwardInvocation, \"v@:@\");\n        if (originalForwardImp) {\n            class_addMethod(cls, @selector(ORIGforwardInvocation:), originalForwardImp, \"v@:@\");\n        }\n    }\n\n    [cls jp_fixMethodSignature];\n    if (class_respondsToSelector(cls, selector)) {\n        NSString *originalSelectorName = [NSString stringWithFormat:@\"ORIG%@\", selectorName];\n        SEL originalSelector = NSSelectorFromString(originalSelectorName);\n        if(!class_respondsToSelector(cls, originalSelector)) {\n            class_addMethod(cls, originalSelector, originalImp, typeDescription);\n        }\n    }\n    \n    NSString *JPSelectorName = [NSString stringWithFormat:@\"_JP%@\", selectorName];\n    \n    _initJPOverideMethods(cls);\n    _JSOverideMethods[cls][JPSelectorName] = function;\n    \n    // Replace the original selector at last, preventing threading issus when\n    // the selector get called during the execution of `overrideMethod`\n    class_replaceMethod(cls, selector, msgForwardIMP, typeDescription);\n}\n\n#pragma mark -\nstatic id callSelector(NSString *className, NSString *selectorName, JSValue *arguments, JSValue *instance, BOOL isSuper)\n{\n    NSString *realClsName = [[instance valueForProperty:@\"__realClsName\"] toString];\n   \n    if (instance) {\n        instance = formatJSToOC(instance);\n        if (class_isMetaClass(object_getClass(instance))) {\n            className = NSStringFromClass((Class)instance);\n            instance = nil;\n        } else if (!instance || instance == _nilObj || [instance isKindOfClass:[JPBoxing class]]) {\n            return @{@\"__isNil\": @(YES)};\n        }\n    }\n    id argumentsObj = formatJSToOC(arguments);\n    \n    if (instance && [selectorName isEqualToString:@\"toJS\"]) {\n        if ([instance isKindOfClass:[NSString class]] || [instance isKindOfClass:[NSDictionary class]] || [instance isKindOfClass:[NSArray class]] || [instance isKindOfClass:[NSDate class]]) {\n            return _unboxOCObjectToJS(instance);\n        }\n    }\n\n    Class cls = instance ? [instance class] : NSClassFromString(className);\n    SEL selector = NSSelectorFromString(selectorName);\n    \n    NSString *superClassName = nil;\n    if (isSuper) {\n        NSString *superSelectorName = [NSString stringWithFormat:@\"SUPER_%@\", selectorName];\n        SEL superSelector = NSSelectorFromString(superSelectorName);\n        \n        Class superCls;\n        if (realClsName.length) {\n            Class defineClass = NSClassFromString(realClsName);\n            superCls = defineClass ? [defineClass superclass] : [cls superclass];\n        } else {\n            superCls = [cls superclass];\n        }\n        \n        Method superMethod = class_getInstanceMethod(superCls, selector);\n        IMP superIMP = method_getImplementation(superMethod);\n        \n        class_addMethod(cls, superSelector, superIMP, method_getTypeEncoding(superMethod));\n        \n        NSString *JPSelectorName = [NSString stringWithFormat:@\"_JP%@\", selectorName];\n        JSValue *overideFunction = _JSOverideMethods[superCls][JPSelectorName];\n        if (overideFunction) {\n            overrideMethod(cls, superSelectorName, overideFunction, NO, NULL);\n        }\n        \n        selector = superSelector;\n        superClassName = NSStringFromClass(superCls);\n    }\n    \n    \n    NSMutableArray *_markArray;\n    \n    NSInvocation *invocation;\n    NSMethodSignature *methodSignature;\n    if (!_JSMethodSignatureCache) {\n        _JSMethodSignatureCache = [[NSMutableDictionary alloc]init];\n    }\n    if (instance) {\n        [_JSMethodSignatureLock lock];\n        if (!_JSMethodSignatureCache[cls]) {\n            _JSMethodSignatureCache[(id<NSCopying>)cls] = [[NSMutableDictionary alloc]init];\n        }\n        methodSignature = _JSMethodSignatureCache[cls][selectorName];\n        if (!methodSignature) {\n            methodSignature = [cls instanceMethodSignatureForSelector:selector];\n            methodSignature = fixSignature(methodSignature);\n            _JSMethodSignatureCache[cls][selectorName] = methodSignature;\n        }\n        [_JSMethodSignatureLock unlock];\n        if (!methodSignature) {\n            _exceptionBlock([NSString stringWithFormat:@\"unrecognized selector %@ for instance %@\", selectorName, instance]);\n            return nil;\n        }\n        invocation = [NSInvocation invocationWithMethodSignature:methodSignature];\n        [invocation setTarget:instance];\n    } else {\n        methodSignature = [cls methodSignatureForSelector:selector];\n        methodSignature = fixSignature(methodSignature);\n        if (!methodSignature) {\n            _exceptionBlock([NSString stringWithFormat:@\"unrecognized selector %@ for class %@\", selectorName, className]);\n            return nil;\n        }\n        invocation= [NSInvocation invocationWithMethodSignature:methodSignature];\n        [invocation setTarget:cls];\n    }\n    [invocation setSelector:selector];\n    \n    NSUInteger numberOfArguments = methodSignature.numberOfArguments;\n    NSInteger inputArguments = [(NSArray *)argumentsObj count];\n    if (inputArguments > numberOfArguments - 2) {\n        // calling variable argument method, only support parameter type `id` and return type `id`\n        id sender = instance != nil ? instance : cls;\n        id result = invokeVariableParameterMethod(argumentsObj, methodSignature, sender, selector);\n        return formatOCToJS(result);\n    }\n    \n    for (NSUInteger i = 2; i < numberOfArguments; i++) {\n        const char *argumentType = [methodSignature getArgumentTypeAtIndex:i];\n        id valObj = argumentsObj[i-2];\n        switch (argumentType[0] == 'r' ? argumentType[1] : argumentType[0]) {\n                \n                #define JP_CALL_ARG_CASE(_typeString, _type, _selector) \\\n                case _typeString: {                              \\\n                    _type value = [valObj _selector];                     \\\n                    [invocation setArgument:&value atIndex:i];\\\n                    break; \\\n                }\n                \n                JP_CALL_ARG_CASE('c', char, charValue)\n                JP_CALL_ARG_CASE('C', unsigned char, unsignedCharValue)\n                JP_CALL_ARG_CASE('s', short, shortValue)\n                JP_CALL_ARG_CASE('S', unsigned short, unsignedShortValue)\n                JP_CALL_ARG_CASE('i', int, intValue)\n                JP_CALL_ARG_CASE('I', unsigned int, unsignedIntValue)\n                JP_CALL_ARG_CASE('l', long, longValue)\n                JP_CALL_ARG_CASE('L', unsigned long, unsignedLongValue)\n                JP_CALL_ARG_CASE('q', long long, longLongValue)\n                JP_CALL_ARG_CASE('Q', unsigned long long, unsignedLongLongValue)\n                JP_CALL_ARG_CASE('f', float, floatValue)\n                JP_CALL_ARG_CASE('d', double, doubleValue)\n                JP_CALL_ARG_CASE('B', BOOL, boolValue)\n                \n            case ':': {\n                SEL value = nil;\n                if (valObj != _nilObj) {\n                    value = NSSelectorFromString(valObj);\n                }\n                [invocation setArgument:&value atIndex:i];\n                break;\n            }\n            case '{': {\n                NSString *typeString = extractStructName([NSString stringWithUTF8String:argumentType]);\n                JSValue *val = arguments[i-2];\n                #define JP_CALL_ARG_STRUCT(_type, _methodName) \\\n                if ([typeString rangeOfString:@#_type].location != NSNotFound) {    \\\n                    _type value = [val _methodName];  \\\n                    [invocation setArgument:&value atIndex:i];  \\\n                    break; \\\n                }\n                JP_CALL_ARG_STRUCT(CGRect, toRect)\n                JP_CALL_ARG_STRUCT(CGPoint, toPoint)\n                JP_CALL_ARG_STRUCT(CGSize, toSize)\n                JP_CALL_ARG_STRUCT(NSRange, toRange)\n                @synchronized (_context) {\n                    NSDictionary *structDefine = _registeredStruct[typeString];\n                    if (structDefine) {\n                        size_t size = sizeOfStructTypes(structDefine[@\"types\"]);\n                        void *ret = malloc(size);\n                        getStructDataWithDict(ret, valObj, structDefine);\n                        [invocation setArgument:ret atIndex:i];\n                        free(ret);\n                        break;\n                    }\n                }\n                \n                break;\n            }\n            case '*':\n            case '^': {\n                if ([valObj isKindOfClass:[JPBoxing class]]) {\n                    void *value = [((JPBoxing *)valObj) unboxPointer];\n                    \n                    if (argumentType[1] == '@') {\n                        if (!_TMPMemoryPool) {\n                            _TMPMemoryPool = [[NSMutableDictionary alloc] init];\n                        }\n                        if (!_markArray) {\n                            _markArray = [[NSMutableArray alloc] init];\n                        }\n                        memset(value, 0, sizeof(id));\n                        [_markArray addObject:valObj];\n                    }\n                    \n                    [invocation setArgument:&value atIndex:i];\n                    break;\n                }\n            }\n            case '#': {\n                if ([valObj isKindOfClass:[JPBoxing class]]) {\n                    Class value = [((JPBoxing *)valObj) unboxClass];\n                    [invocation setArgument:&value atIndex:i];\n                    break;\n                }\n            }\n            default: {\n                if (valObj == _nullObj) {\n                    valObj = [NSNull null];\n                    [invocation setArgument:&valObj atIndex:i];\n                    break;\n                }\n                if (valObj == _nilObj ||\n                    ([valObj isKindOfClass:[NSNumber class]] && strcmp([valObj objCType], \"c\") == 0 && ![valObj boolValue])) {\n                    valObj = nil;\n                    [invocation setArgument:&valObj atIndex:i];\n                    break;\n                }\n                if ([(JSValue *)arguments[i-2] hasProperty:@\"__isBlock\"]) {\n                    JSValue *blkJSVal = arguments[i-2];\n                    Class JPBlockClass = NSClassFromString(@\"JPBlock\");\n                    if (JPBlockClass && ![blkJSVal[@\"blockObj\"] isUndefined]) {\n                        __autoreleasing id cb = [JPBlockClass performSelector:@selector(blockWithBlockObj:) withObject:[blkJSVal[@\"blockObj\"] toObject]];\n                        [invocation setArgument:&cb atIndex:i];\n                        Block_release((__bridge void *)cb);\n                    } else {\n                        __autoreleasing id cb = genCallbackBlock(arguments[i-2]);\n                        [invocation setArgument:&cb atIndex:i];\n                    }\n                } else {\n                    [invocation setArgument:&valObj atIndex:i];\n                }\n            }\n        }\n    }\n    \n    if (superClassName) _currInvokeSuperClsName[selectorName] = superClassName;\n    [invocation invoke];\n    if (superClassName) [_currInvokeSuperClsName removeObjectForKey:selectorName];\n    if ([_markArray count] > 0) {\n        for (JPBoxing *box in _markArray) {\n            void *pointer = [box unboxPointer];\n            id obj = *((__unsafe_unretained id *)pointer);\n            if (obj) {\n                @synchronized(_TMPMemoryPool) {\n                    [_TMPMemoryPool setObject:obj forKey:[NSNumber numberWithInteger:[(NSObject*)obj hash]]];\n                }\n            }\n        }\n    }\n    \n    char returnType[255];\n    strcpy(returnType, [methodSignature methodReturnType]);\n    \n    // Restore the return type\n    if (strcmp(returnType, @encode(JPDouble)) == 0) {\n        strcpy(returnType, @encode(double));\n    }\n    if (strcmp(returnType, @encode(JPFloat)) == 0) {\n        strcpy(returnType, @encode(float));\n    }\n\n    id returnValue;\n    if (strncmp(returnType, \"v\", 1) != 0) {\n        if (strncmp(returnType, \"@\", 1) == 0) {\n            void *result;\n            [invocation getReturnValue:&result];\n            \n            //For performance, ignore the other methods prefix with alloc/new/copy/mutableCopy\n            if ([selectorName isEqualToString:@\"alloc\"] || [selectorName isEqualToString:@\"new\"] ||\n                [selectorName isEqualToString:@\"copy\"] || [selectorName isEqualToString:@\"mutableCopy\"]) {\n                returnValue = (__bridge_transfer id)result;\n            } else {\n                returnValue = (__bridge id)result;\n            }\n            return formatOCToJS(returnValue);\n            \n        } else {\n            switch (returnType[0] == 'r' ? returnType[1] : returnType[0]) {\n                    \n                #define JP_CALL_RET_CASE(_typeString, _type) \\\n                case _typeString: {                              \\\n                    _type tempResultSet; \\\n                    [invocation getReturnValue:&tempResultSet];\\\n                    returnValue = @(tempResultSet); \\\n                    break; \\\n                }\n                    \n                JP_CALL_RET_CASE('c', char)\n                JP_CALL_RET_CASE('C', unsigned char)\n                JP_CALL_RET_CASE('s', short)\n                JP_CALL_RET_CASE('S', unsigned short)\n                JP_CALL_RET_CASE('i', int)\n                JP_CALL_RET_CASE('I', unsigned int)\n                JP_CALL_RET_CASE('l', long)\n                JP_CALL_RET_CASE('L', unsigned long)\n                JP_CALL_RET_CASE('q', long long)\n                JP_CALL_RET_CASE('Q', unsigned long long)\n                JP_CALL_RET_CASE('f', float)\n                JP_CALL_RET_CASE('d', double)\n                JP_CALL_RET_CASE('B', BOOL)\n\n                case '{': {\n                    NSString *typeString = extractStructName([NSString stringWithUTF8String:returnType]);\n                    #define JP_CALL_RET_STRUCT(_type, _methodName) \\\n                    if ([typeString rangeOfString:@#_type].location != NSNotFound) {    \\\n                        _type result;   \\\n                        [invocation getReturnValue:&result];    \\\n                        return [JSValue _methodName:result inContext:_context];    \\\n                    }\n                    JP_CALL_RET_STRUCT(CGRect, valueWithRect)\n                    JP_CALL_RET_STRUCT(CGPoint, valueWithPoint)\n                    JP_CALL_RET_STRUCT(CGSize, valueWithSize)\n                    JP_CALL_RET_STRUCT(NSRange, valueWithRange)\n                    @synchronized (_context) {\n                        NSDictionary *structDefine = _registeredStruct[typeString];\n                        if (structDefine) {\n                            size_t size = sizeOfStructTypes(structDefine[@\"types\"]);\n                            void *ret = malloc(size);\n                            [invocation getReturnValue:ret];\n                            NSDictionary *dict = getDictOfStruct(ret, structDefine);\n                            free(ret);\n                            return dict;\n                        }\n                    }\n                    break;\n                }\n                case '*':\n                case '^': {\n                    void *result;\n                    [invocation getReturnValue:&result];\n                    returnValue = formatOCToJS([JPBoxing boxPointer:result]);\n                    if (strncmp(returnType, \"^{CG\", 4) == 0) {\n                        if (!_pointersToRelease) {\n                            _pointersToRelease = [[NSMutableArray alloc] init];\n                        }\n                        [_pointersToRelease addObject:[NSValue valueWithPointer:result]];\n                        CFRetain(result);\n                    }\n                    break;\n                }\n                case '#': {\n                    Class result;\n                    [invocation getReturnValue:&result];\n                    returnValue = formatOCToJS([JPBoxing boxClass:result]);\n                    break;\n                }\n            }\n            return returnValue;\n        }\n    }\n    return nil;\n}\n\nstatic id (*new_msgSend1)(id, SEL, id,...) = (id (*)(id, SEL, id,...)) objc_msgSend;\nstatic id (*new_msgSend2)(id, SEL, id, id,...) = (id (*)(id, SEL, id, id,...)) objc_msgSend;\nstatic id (*new_msgSend3)(id, SEL, id, id, id,...) = (id (*)(id, SEL, id, id, id,...)) objc_msgSend;\nstatic id (*new_msgSend4)(id, SEL, id, id, id, id,...) = (id (*)(id, SEL, id, id, id, id,...)) objc_msgSend;\nstatic id (*new_msgSend5)(id, SEL, id, id, id, id, id,...) = (id (*)(id, SEL, id, id, id, id, id,...)) objc_msgSend;\nstatic id (*new_msgSend6)(id, SEL, id, id, id, id, id, id,...) = (id (*)(id, SEL, id, id, id, id, id, id,...)) objc_msgSend;\nstatic id (*new_msgSend7)(id, SEL, id, id, id, id, id, id, id,...) = (id (*)(id, SEL, id, id, id, id, id, id,id,...)) objc_msgSend;\nstatic id (*new_msgSend8)(id, SEL, id, id, id, id, id, id, id, id,...) = (id (*)(id, SEL, id, id, id, id, id, id, id, id,...)) objc_msgSend;\nstatic id (*new_msgSend9)(id, SEL, id, id, id, id, id, id, id, id, id,...) = (id (*)(id, SEL, id, id, id, id, id, id, id, id, id, ...)) objc_msgSend;\nstatic id (*new_msgSend10)(id, SEL, id, id, id, id, id, id, id, id, id, id,...) = (id (*)(id, SEL, id, id, id, id, id, id, id, id, id, id,...)) objc_msgSend;\n\nstatic id invokeVariableParameterMethod(NSMutableArray *origArgumentsList, NSMethodSignature *methodSignature, id sender, SEL selector) {\n    \n    NSInteger inputArguments = [(NSArray *)origArgumentsList count];\n    NSUInteger numberOfArguments = methodSignature.numberOfArguments;\n    \n    NSMutableArray *argumentsList = [[NSMutableArray alloc] init];\n    for (NSUInteger j = 0; j < inputArguments; j++) {\n        NSInteger index = MIN(j + 2, numberOfArguments - 1);\n        const char *argumentType = [methodSignature getArgumentTypeAtIndex:index];\n        id valObj = origArgumentsList[j];\n        char argumentTypeChar = argumentType[0] == 'r' ? argumentType[1] : argumentType[0];\n        if (argumentTypeChar == '@') {\n            [argumentsList addObject:valObj];\n        } else {\n            return nil;\n        }\n    }\n    \n    id results = nil;\n    numberOfArguments = numberOfArguments - 2;\n    \n    //If you want to debug the macro code below, replace it to the expanded code:\n    //https://gist.github.com/bang590/ca3720ae1da594252a2e\n    #define JP_G_ARG(_idx) getArgument(argumentsList[_idx])\n    #define JP_CALL_MSGSEND_ARG1(_num) results = new_msgSend##_num(sender, selector, JP_G_ARG(0));\n    #define JP_CALL_MSGSEND_ARG2(_num) results = new_msgSend##_num(sender, selector, JP_G_ARG(0), JP_G_ARG(1));\n    #define JP_CALL_MSGSEND_ARG3(_num) results = new_msgSend##_num(sender, selector, JP_G_ARG(0), JP_G_ARG(1), JP_G_ARG(2));\n    #define JP_CALL_MSGSEND_ARG4(_num) results = new_msgSend##_num(sender, selector, JP_G_ARG(0), JP_G_ARG(1), JP_G_ARG(2), JP_G_ARG(3));\n    #define JP_CALL_MSGSEND_ARG5(_num) results = new_msgSend##_num(sender, selector, JP_G_ARG(0), JP_G_ARG(1), JP_G_ARG(2), JP_G_ARG(3), JP_G_ARG(4));\n    #define JP_CALL_MSGSEND_ARG6(_num) results = new_msgSend##_num(sender, selector, JP_G_ARG(0), JP_G_ARG(1), JP_G_ARG(2), JP_G_ARG(3), JP_G_ARG(4), JP_G_ARG(5));\n    #define JP_CALL_MSGSEND_ARG7(_num) results = new_msgSend##_num(sender, selector, JP_G_ARG(0), JP_G_ARG(1), JP_G_ARG(2), JP_G_ARG(3), JP_G_ARG(4), JP_G_ARG(5), JP_G_ARG(6));\n    #define JP_CALL_MSGSEND_ARG8(_num) results = new_msgSend##_num(sender, selector, JP_G_ARG(0), JP_G_ARG(1), JP_G_ARG(2), JP_G_ARG(3), JP_G_ARG(4), JP_G_ARG(5), JP_G_ARG(6), JP_G_ARG(7));\n    #define JP_CALL_MSGSEND_ARG9(_num) results = new_msgSend##_num(sender, selector, JP_G_ARG(0), JP_G_ARG(1), JP_G_ARG(2), JP_G_ARG(3), JP_G_ARG(4), JP_G_ARG(5), JP_G_ARG(6), JP_G_ARG(7), JP_G_ARG(8));\n    #define JP_CALL_MSGSEND_ARG10(_num) results = new_msgSend##_num(sender, selector, JP_G_ARG(0), JP_G_ARG(1), JP_G_ARG(2), JP_G_ARG(3), JP_G_ARG(4), JP_G_ARG(5), JP_G_ARG(6), JP_G_ARG(7), JP_G_ARG(8), JP_G_ARG(9));\n    #define JP_CALL_MSGSEND_ARG11(_num) results = new_msgSend##_num(sender, selector, JP_G_ARG(0), JP_G_ARG(1), JP_G_ARG(2), JP_G_ARG(3), JP_G_ARG(4), JP_G_ARG(5), JP_G_ARG(6), JP_G_ARG(7), JP_G_ARG(8), JP_G_ARG(9), JP_G_ARG(10));\n        \n    #define JP_IF_REAL_ARG_COUNT(_num) if([argumentsList count] == _num)\n\n    #define JP_DEAL_MSGSEND(_realArgCount, _defineArgCount) \\\n        if(numberOfArguments == _defineArgCount) { \\\n            JP_CALL_MSGSEND_ARG##_realArgCount(_defineArgCount) \\\n        }\n    \n    JP_IF_REAL_ARG_COUNT(1) { JP_CALL_MSGSEND_ARG1(1) }\n    JP_IF_REAL_ARG_COUNT(2) { JP_DEAL_MSGSEND(2, 1) JP_DEAL_MSGSEND(2, 2) }\n    JP_IF_REAL_ARG_COUNT(3) { JP_DEAL_MSGSEND(3, 1) JP_DEAL_MSGSEND(3, 2) JP_DEAL_MSGSEND(3, 3) }\n    JP_IF_REAL_ARG_COUNT(4) { JP_DEAL_MSGSEND(4, 1) JP_DEAL_MSGSEND(4, 2) JP_DEAL_MSGSEND(4, 3) JP_DEAL_MSGSEND(4, 4) }\n    JP_IF_REAL_ARG_COUNT(5) { JP_DEAL_MSGSEND(5, 1) JP_DEAL_MSGSEND(5, 2) JP_DEAL_MSGSEND(5, 3) JP_DEAL_MSGSEND(5, 4) JP_DEAL_MSGSEND(5, 5) }\n    JP_IF_REAL_ARG_COUNT(6) { JP_DEAL_MSGSEND(6, 1) JP_DEAL_MSGSEND(6, 2) JP_DEAL_MSGSEND(6, 3) JP_DEAL_MSGSEND(6, 4) JP_DEAL_MSGSEND(6, 5) JP_DEAL_MSGSEND(6, 6) }\n    JP_IF_REAL_ARG_COUNT(7) { JP_DEAL_MSGSEND(7, 1) JP_DEAL_MSGSEND(7, 2) JP_DEAL_MSGSEND(7, 3) JP_DEAL_MSGSEND(7, 4) JP_DEAL_MSGSEND(7, 5) JP_DEAL_MSGSEND(7, 6) JP_DEAL_MSGSEND(7, 7) }\n    JP_IF_REAL_ARG_COUNT(8) { JP_DEAL_MSGSEND(8, 1) JP_DEAL_MSGSEND(8, 2) JP_DEAL_MSGSEND(8, 3) JP_DEAL_MSGSEND(8, 4) JP_DEAL_MSGSEND(8, 5) JP_DEAL_MSGSEND(8, 6) JP_DEAL_MSGSEND(8, 7) JP_DEAL_MSGSEND(8, 8) }\n    JP_IF_REAL_ARG_COUNT(9) { JP_DEAL_MSGSEND(9, 1) JP_DEAL_MSGSEND(9, 2) JP_DEAL_MSGSEND(9, 3) JP_DEAL_MSGSEND(9, 4) JP_DEAL_MSGSEND(9, 5) JP_DEAL_MSGSEND(9, 6) JP_DEAL_MSGSEND(9, 7) JP_DEAL_MSGSEND(9, 8) JP_DEAL_MSGSEND(9, 9) }\n    JP_IF_REAL_ARG_COUNT(10) { JP_DEAL_MSGSEND(10, 1) JP_DEAL_MSGSEND(10, 2) JP_DEAL_MSGSEND(10, 3) JP_DEAL_MSGSEND(10, 4) JP_DEAL_MSGSEND(10, 5) JP_DEAL_MSGSEND(10, 6) JP_DEAL_MSGSEND(10, 7) JP_DEAL_MSGSEND(10, 8) JP_DEAL_MSGSEND(10, 9) JP_DEAL_MSGSEND(10, 10) }\n    \n    return results;\n}\n\nNSMethodSignature *block_methodSignatureForSelector(id self, SEL _cmd, SEL aSelector) {\n    uint8_t *p = (uint8_t *)((__bridge void *)self);\n    p += sizeof(void *) * 2 + sizeof(int32_t) *2 + sizeof(uintptr_t) * 2;\n    const char **signature = (const char **)p;\n    return [NSMethodSignature signatureWithObjCTypes:*signature];\n}\n\n\nstatic id getArgument(id valObj){\n    if (valObj == _nilObj ||\n        ([valObj isKindOfClass:[NSNumber class]] && strcmp([valObj objCType], \"c\") == 0 && ![valObj boolValue])) {\n        return nil;\n    }\n    return valObj;\n}\n\n#pragma mark -\n\nstatic id genCallbackBlock(JSValue *jsVal)\n{\n    void (^block)(void) = ^(void){};\n    uint8_t *p = (uint8_t *)((__bridge void *)block);\n    p += sizeof(void *) + sizeof(int32_t) *2;\n    void(**invoke)(void) = (void (**)(void))p;\n    \n    p += sizeof(void *) + sizeof(uintptr_t) * 2;\n    const char **signature = (const char **)p;\n    \n    static NSMutableDictionary *typeSignatureDict;\n    if (!typeSignatureDict) {\n        typeSignatureDict  = [NSMutableDictionary new];\n        #define JP_DEFINE_TYPE_SIGNATURE(_type) \\\n        [typeSignatureDict setObject:@[[NSString stringWithUTF8String:@encode(_type)], @(sizeof(_type))] forKey:@#_type];\\\n\n        JP_DEFINE_TYPE_SIGNATURE(id);\n        JP_DEFINE_TYPE_SIGNATURE(BOOL);\n        JP_DEFINE_TYPE_SIGNATURE(int);\n        JP_DEFINE_TYPE_SIGNATURE(void);\n        JP_DEFINE_TYPE_SIGNATURE(char);\n        JP_DEFINE_TYPE_SIGNATURE(short);\n        JP_DEFINE_TYPE_SIGNATURE(unsigned short);\n        JP_DEFINE_TYPE_SIGNATURE(unsigned int);\n        JP_DEFINE_TYPE_SIGNATURE(long);\n        JP_DEFINE_TYPE_SIGNATURE(unsigned long);\n        JP_DEFINE_TYPE_SIGNATURE(long long);\n        JP_DEFINE_TYPE_SIGNATURE(unsigned long long);\n        JP_DEFINE_TYPE_SIGNATURE(float);\n        JP_DEFINE_TYPE_SIGNATURE(double);\n        JP_DEFINE_TYPE_SIGNATURE(bool);\n        JP_DEFINE_TYPE_SIGNATURE(size_t);\n        JP_DEFINE_TYPE_SIGNATURE(CGFloat);\n        JP_DEFINE_TYPE_SIGNATURE(CGSize);\n        JP_DEFINE_TYPE_SIGNATURE(CGRect);\n        JP_DEFINE_TYPE_SIGNATURE(CGPoint);\n        JP_DEFINE_TYPE_SIGNATURE(CGVector);\n        JP_DEFINE_TYPE_SIGNATURE(NSRange);\n        JP_DEFINE_TYPE_SIGNATURE(NSInteger);\n        JP_DEFINE_TYPE_SIGNATURE(Class);\n        JP_DEFINE_TYPE_SIGNATURE(SEL);\n        JP_DEFINE_TYPE_SIGNATURE(void*);\n        JP_DEFINE_TYPE_SIGNATURE(void *);\n    }\n    \n    NSString *types = [jsVal[@\"args\"] toString];\n    NSArray *lt = [types componentsSeparatedByString:@\",\"];\n    \n    NSString *funcSignature = @\"@?0\";\n    \n    NSInteger size = sizeof(void *);\n    for (NSInteger i = 1; i < lt.count;) {\n        NSString *t = trim(lt[i]);\n        NSString *tpe = typeSignatureDict[typeSignatureDict[t] ? t : @\"id\"][0];\n        if (i == 0) {\n            funcSignature  =[[NSString stringWithFormat:@\"%@%@\",tpe, [@(size) stringValue]] stringByAppendingString:funcSignature];\n            break;\n        }\n        \n        funcSignature = [funcSignature stringByAppendingString:[NSString stringWithFormat:@\"%@%@\", tpe, [@(size) stringValue]]];\n        size += [typeSignatureDict[typeSignatureDict[t] ? t : @\"id\"][1] integerValue];\n        \n        i = (i != lt.count - 1) ? i + 1 : 0;\n    }\n    \n    IMP msgForwardIMP = _objc_msgForward;\n#if !defined(__arm64__)\n    if ([funcSignature UTF8String][0] == '{') {\n        //In some cases that returns struct, we should use the '_stret' API:\n        //http://sealiesoftware.com/blog/archive/2008/10/30/objc_explain_objc_msgSend_stret.html\n        //NSMethodSignature knows the detail but has no API to return, we can only get the info from debugDescription.\n        NSMethodSignature *methodSignature = [NSMethodSignature signatureWithObjCTypes:[funcSignature UTF8String]];\n        if ([methodSignature.debugDescription rangeOfString:@\"is special struct return? YES\"].location != NSNotFound) {\n            msgForwardIMP = (IMP)_objc_msgForward_stret;\n        }\n    }\n#endif\n    *invoke = (void *)msgForwardIMP;\n    \n    const char *fs = [funcSignature UTF8String];\n    char *s = malloc(strlen(fs));\n    strcpy(s, fs);\n    *signature = s;\n    \n    objc_setAssociatedObject(block, \"_JSValue\", jsVal, OBJC_ASSOCIATION_RETAIN_NONATOMIC);\n    \n    static dispatch_once_t onceToken;\n    dispatch_once(&onceToken, ^{\n        Class cls = NSClassFromString(@\"NSBlock\");\n#define JP_HOOK_METHOD(selector, func) {Method method = class_getInstanceMethod([NSObject class], selector); \\\nBOOL success = class_addMethod(cls, selector, (IMP)func, method_getTypeEncoding(method)); \\\nif (!success) { class_replaceMethod(cls, selector, (IMP)func, method_getTypeEncoding(method));}}\n        \n        JP_HOOK_METHOD(@selector(methodSignatureForSelector:), block_methodSignatureForSelector);\n        JP_HOOK_METHOD(@selector(forwardInvocation:), JPForwardInvocation);\n    });\n    \n    return block;\n}\n\n#pragma mark - Struct\n\nstatic int sizeOfStructTypes(NSString *structTypes)\n{\n    const char *types = [structTypes cStringUsingEncoding:NSUTF8StringEncoding];\n    int index = 0;\n    int size = 0;\n    while (types[index]) {\n        switch (types[index]) {\n            #define JP_STRUCT_SIZE_CASE(_typeChar, _type)   \\\n            case _typeChar: \\\n                size += sizeof(_type);  \\\n                break;\n                \n            JP_STRUCT_SIZE_CASE('c', char)\n            JP_STRUCT_SIZE_CASE('C', unsigned char)\n            JP_STRUCT_SIZE_CASE('s', short)\n            JP_STRUCT_SIZE_CASE('S', unsigned short)\n            JP_STRUCT_SIZE_CASE('i', int)\n            JP_STRUCT_SIZE_CASE('I', unsigned int)\n            JP_STRUCT_SIZE_CASE('l', long)\n            JP_STRUCT_SIZE_CASE('L', unsigned long)\n            JP_STRUCT_SIZE_CASE('q', long long)\n            JP_STRUCT_SIZE_CASE('Q', unsigned long long)\n            JP_STRUCT_SIZE_CASE('f', float)\n            JP_STRUCT_SIZE_CASE('F', CGFloat)\n            JP_STRUCT_SIZE_CASE('N', NSInteger)\n            JP_STRUCT_SIZE_CASE('U', NSUInteger)\n            JP_STRUCT_SIZE_CASE('d', double)\n            JP_STRUCT_SIZE_CASE('B', BOOL)\n            JP_STRUCT_SIZE_CASE('*', void *)\n            JP_STRUCT_SIZE_CASE('^', void *)\n                \n            case '{': {\n                NSString *structTypeStr = [structTypes substringFromIndex:index];\n                NSUInteger end = [structTypeStr rangeOfString:@\"}\"].location;\n                if (end != NSNotFound) {\n                    NSString *subStructName = [structTypeStr substringWithRange:NSMakeRange(1, end - 1)];\n                    NSDictionary *subStructDefine = [JPExtension registeredStruct][subStructName];\n                    NSString *subStructTypes = subStructDefine[@\"types\"];\n                    size += sizeOfStructTypes(subStructTypes);\n                    index += (int)end;\n                    break;\n                }\n            }\n            \n            default:\n                break;\n        }\n        index ++;\n    }\n    return size;\n}\n\nstatic void getStructDataWithDict(void *structData, NSDictionary *dict, NSDictionary *structDefine)\n{\n    NSArray *itemKeys = structDefine[@\"keys\"];\n    const char *structTypes = [structDefine[@\"types\"] cStringUsingEncoding:NSUTF8StringEncoding];\n    int position = 0;\n    for (NSString *itemKey in itemKeys) {\n        switch(*structTypes) {\n            #define JP_STRUCT_DATA_CASE(_typeStr, _type, _transMethod) \\\n            case _typeStr: { \\\n                int size = sizeof(_type);    \\\n                _type val = [dict[itemKey] _transMethod];   \\\n                memcpy(structData + position, &val, size);  \\\n                position += size;    \\\n                break;  \\\n            }\n                \n            JP_STRUCT_DATA_CASE('c', char, charValue)\n            JP_STRUCT_DATA_CASE('C', unsigned char, unsignedCharValue)\n            JP_STRUCT_DATA_CASE('s', short, shortValue)\n            JP_STRUCT_DATA_CASE('S', unsigned short, unsignedShortValue)\n            JP_STRUCT_DATA_CASE('i', int, intValue)\n            JP_STRUCT_DATA_CASE('I', unsigned int, unsignedIntValue)\n            JP_STRUCT_DATA_CASE('l', long, longValue)\n            JP_STRUCT_DATA_CASE('L', unsigned long, unsignedLongValue)\n            JP_STRUCT_DATA_CASE('q', long long, longLongValue)\n            JP_STRUCT_DATA_CASE('Q', unsigned long long, unsignedLongLongValue)\n            JP_STRUCT_DATA_CASE('f', float, floatValue)\n            JP_STRUCT_DATA_CASE('F', CGFloat, CGFloatValue)\n            JP_STRUCT_DATA_CASE('d', double, doubleValue)\n            JP_STRUCT_DATA_CASE('B', BOOL, boolValue)\n            JP_STRUCT_DATA_CASE('N', NSInteger, integerValue)\n            JP_STRUCT_DATA_CASE('U', NSUInteger, unsignedIntegerValue)\n            \n            case '*':\n            case '^': {\n                int size = sizeof(void *);\n                void *val = [(JPBoxing *)dict[itemKey] unboxPointer];\n                memcpy(structData + position, &val, size);\n                break;\n            }\n            case '{': {\n                NSString *subStructName = [NSString stringWithCString:structTypes encoding:NSASCIIStringEncoding];\n                NSUInteger end = [subStructName rangeOfString:@\"}\"].location;\n                if (end != NSNotFound) {\n                    subStructName = [subStructName substringWithRange:NSMakeRange(1, end - 1)];\n                    NSDictionary *subStructDefine = [JPExtension registeredStruct][subStructName];\n                    NSDictionary *subDict = dict[itemKey];\n                    int size = sizeOfStructTypes(subStructDefine[@\"types\"]);\n                    getStructDataWithDict(structData + position, subDict, subStructDefine);\n                    position += size;\n                    structTypes += end;\n                    break;\n                }\n            }\n            default:\n                break;\n            \n        }\n        structTypes ++;\n    }\n}\n\nstatic NSDictionary *getDictOfStruct(void *structData, NSDictionary *structDefine)\n{\n    NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];\n    NSArray *itemKeys = structDefine[@\"keys\"];\n    const char *structTypes = [structDefine[@\"types\"] cStringUsingEncoding:NSUTF8StringEncoding];\n    int position = 0;\n    \n    for (NSString *itemKey in itemKeys) {\n        switch(*structTypes) {\n            #define JP_STRUCT_DICT_CASE(_typeName, _type)   \\\n            case _typeName: { \\\n                size_t size = sizeof(_type); \\\n                _type *val = malloc(size);   \\\n                memcpy(val, structData + position, size);   \\\n                [dict setObject:@(*val) forKey:itemKey];    \\\n                free(val);  \\\n                position += size;   \\\n                break;  \\\n            }\n            JP_STRUCT_DICT_CASE('c', char)\n            JP_STRUCT_DICT_CASE('C', unsigned char)\n            JP_STRUCT_DICT_CASE('s', short)\n            JP_STRUCT_DICT_CASE('S', unsigned short)\n            JP_STRUCT_DICT_CASE('i', int)\n            JP_STRUCT_DICT_CASE('I', unsigned int)\n            JP_STRUCT_DICT_CASE('l', long)\n            JP_STRUCT_DICT_CASE('L', unsigned long)\n            JP_STRUCT_DICT_CASE('q', long long)\n            JP_STRUCT_DICT_CASE('Q', unsigned long long)\n            JP_STRUCT_DICT_CASE('f', float)\n            JP_STRUCT_DICT_CASE('F', CGFloat)\n            JP_STRUCT_DICT_CASE('N', NSInteger)\n            JP_STRUCT_DICT_CASE('U', NSUInteger)\n            JP_STRUCT_DICT_CASE('d', double)\n            JP_STRUCT_DICT_CASE('B', BOOL)\n            \n            case '*':\n            case '^': {\n                size_t size = sizeof(void *);\n                void *val = malloc(size);\n                memcpy(val, structData + position, size);\n                [dict setObject:[JPBoxing boxPointer:val] forKey:itemKey];\n                position += size;\n                break;\n            }\n            case '{': {\n                NSString *subStructName = [NSString stringWithCString:structTypes encoding:NSASCIIStringEncoding];\n                NSUInteger end = [subStructName rangeOfString:@\"}\"].location;\n                if (end != NSNotFound) {\n                    subStructName = [subStructName substringWithRange:NSMakeRange(1, end - 1)];\n                    NSDictionary *subStructDefine = [JPExtension registeredStruct][subStructName];\n                    int size = sizeOfStructTypes(subStructDefine[@\"types\"]);\n                    NSDictionary *subDict = getDictOfStruct(structData + position, subStructDefine);\n                    [dict setObject:subDict forKey:itemKey];\n                    position += size;\n                    structTypes += end;\n                    break;\n                }\n            }\n        }\n        structTypes ++;\n    }\n    return dict;\n}\n\nstatic NSString *extractStructName(NSString *typeEncodeString)\n{\n    NSArray *array = [typeEncodeString componentsSeparatedByString:@\"=\"];\n    NSString *typeString = array[0];\n    int firstValidIndex = 0;\n    for (int i = 0; i< typeString.length; i++) {\n        char c = [typeString characterAtIndex:i];\n        if (c == '{' || c=='_') {\n            firstValidIndex++;\n        }else {\n            break;\n        }\n    }\n    return [typeString substringFromIndex:firstValidIndex];\n}\n\n#pragma mark - Utils\n\nstatic NSString *trim(NSString *string)\n{\n    return [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];\n}\n\nstatic BOOL blockTypeIsObject(NSString *typeString)\n{\n    return [typeString rangeOfString:@\"*\"].location != NSNotFound || [typeString isEqualToString:@\"id\"];\n}\n\nstatic BOOL blockTypeIsScalarPointer(NSString *typeString)\n{\n    NSUInteger location = [typeString rangeOfString:@\"*\"].location;\n    NSString *typeWithoutAsterisk = trim([typeString stringByReplacingOccurrencesOfString:@\"*\" withString:@\"\"]);\n    \n    return (location == typeString.length-1 &&\n            !NSClassFromString(typeWithoutAsterisk));\n}\n\nstatic NSString *convertJPSelectorString(NSString *selectorString)\n{\n    NSString *tmpJSMethodName = [selectorString stringByReplacingOccurrencesOfString:@\"__\" withString:@\"-\"];\n    NSString *selectorName = [tmpJSMethodName stringByReplacingOccurrencesOfString:@\"_\" withString:@\":\"];\n    return [selectorName stringByReplacingOccurrencesOfString:@\"-\" withString:@\"_\"];\n}\n\n#pragma mark - Object format\n\nstatic id formatOCToJS(id obj)\n{\n    if ([obj isKindOfClass:[NSString class]] || [obj isKindOfClass:[NSDictionary class]] || [obj isKindOfClass:[NSArray class]] || [obj isKindOfClass:[NSDate class]]) {\n        return _autoConvert ? obj: _wrapObj([JPBoxing boxObj:obj]);\n    }\n    if ([obj isKindOfClass:[NSNumber class]]) {\n        return _convertOCNumberToString ? [(NSNumber*)obj stringValue] : obj;\n    }\n    if ([obj isKindOfClass:NSClassFromString(@\"NSBlock\")] || [obj isKindOfClass:[JSValue class]]) {\n        return obj;\n    }\n    return _wrapObj(obj);\n}\n\nstatic id formatJSToOC(JSValue *jsval)\n{\n    id obj = [jsval toObject];\n    if (!obj || [obj isKindOfClass:[NSNull class]]) return _nilObj;\n    \n    if ([obj isKindOfClass:[JPBoxing class]]) return [obj unbox];\n    if ([obj isKindOfClass:[NSArray class]]) {\n        NSMutableArray *newArr = [[NSMutableArray alloc] init];\n        for (int i = 0; i < [(NSArray*)obj count]; i ++) {\n            [newArr addObject:formatJSToOC(jsval[i])];\n        }\n        return newArr;\n    }\n    if ([obj isKindOfClass:[NSDictionary class]]) {\n        if (obj[@\"__obj\"]) {\n            id ocObj = [obj objectForKey:@\"__obj\"];\n            if ([ocObj isKindOfClass:[JPBoxing class]]) return [ocObj unbox];\n            return ocObj;\n        } else if (obj[@\"__clsName\"]) {\n            return NSClassFromString(obj[@\"__clsName\"]);\n        }\n        if (obj[@\"__isBlock\"]) {\n            Class JPBlockClass = NSClassFromString(@\"JPBlock\");\n            if (JPBlockClass && ![jsval[@\"blockObj\"] isUndefined]) {\n                return [JPBlockClass performSelector:@selector(blockWithBlockObj:) withObject:[jsval[@\"blockObj\"] toObject]];\n            } else {\n                return genCallbackBlock(jsval);\n            }\n        }\n        NSMutableDictionary *newDict = [[NSMutableDictionary alloc] init];\n        for (NSString *key in [obj allKeys]) {\n            [newDict setObject:formatJSToOC(jsval[key]) forKey:key];\n        }\n        return newDict;\n    }\n    return obj;\n}\n\nstatic id _formatOCToJSList(NSArray *list)\n{\n    NSMutableArray *arr = [NSMutableArray new];\n    for (id obj in list) {\n        [arr addObject:formatOCToJS(obj)];\n    }\n    return arr;\n}\n\nstatic NSDictionary *_wrapObj(id obj)\n{\n    if (!obj || obj == _nilObj) {\n        return @{@\"__isNil\": @(YES)};\n    }\n    return @{@\"__obj\": obj, @\"__clsName\": NSStringFromClass([obj isKindOfClass:[JPBoxing class]] ? [[((JPBoxing *)obj) unbox] class]: [obj class])};\n}\n\nstatic id _unboxOCObjectToJS(id obj)\n{\n    if ([obj isKindOfClass:[NSArray class]]) {\n        NSMutableArray *newArr = [[NSMutableArray alloc] init];\n        for (int i = 0; i < [(NSArray*)obj count]; i ++) {\n            [newArr addObject:_unboxOCObjectToJS(obj[i])];\n        }\n        return newArr;\n    }\n    if ([obj isKindOfClass:[NSDictionary class]]) {\n        NSMutableDictionary *newDict = [[NSMutableDictionary alloc] init];\n        for (NSString *key in [obj allKeys]) {\n            [newDict setObject:_unboxOCObjectToJS(obj[key]) forKey:key];\n        }\n        return newDict;\n    }\n    if ([obj isKindOfClass:[NSString class]] ||[obj isKindOfClass:[NSNumber class]] || [obj isKindOfClass:NSClassFromString(@\"NSBlock\")] || [obj isKindOfClass:[NSDate class]]) {\n        return obj;\n    }\n    return _wrapObj(obj);\n}\n#pragma clang diagnostic pop\n@end\n\n\n@implementation JPExtension\n\n+ (void)main:(JSContext *)context{}\n\n+ (void *)formatPointerJSToOC:(JSValue *)val\n{\n    id obj = [val toObject];\n    if ([obj isKindOfClass:[NSDictionary class]]) {\n        if (obj[@\"__obj\"] && [obj[@\"__obj\"] isKindOfClass:[JPBoxing class]]) {\n            return [(JPBoxing *)(obj[@\"__obj\"]) unboxPointer];\n        } else {\n            return NULL;\n        }\n    } else if (![val toBool]) {\n        return NULL;\n    } else{\n        return [((JPBoxing *)[val toObject]) unboxPointer];\n    }\n}\n\n+ (id)formatRetainedCFTypeOCToJS:(CFTypeRef)CF_CONSUMED type\n{\n    return formatOCToJS([JPBoxing boxPointer:(void *)type]);\n}\n\n+ (id)formatPointerOCToJS:(void *)pointer\n{\n    return formatOCToJS([JPBoxing boxPointer:pointer]);\n}\n\n+ (id)formatJSToOC:(JSValue *)val\n{\n    if (![val toBool]) {\n        return nil;\n    }\n    return formatJSToOC(val);\n}\n\n+ (id)formatOCToJS:(id)obj\n{\n    JSContext *context = [JSContext currentContext] ? [JSContext currentContext]: _context;\n    return [context[@\"_formatOCToJS\"] callWithArguments:@[formatOCToJS(obj)]];\n}\n\n+ (int)sizeOfStructTypes:(NSString *)structTypes\n{\n    return sizeOfStructTypes(structTypes);\n}\n\n+ (void)getStructDataWidthDict:(void *)structData dict:(NSDictionary *)dict structDefine:(NSDictionary *)structDefine\n{\n    return getStructDataWithDict(structData, dict, structDefine);\n}\n\n+ (NSDictionary *)getDictOfStruct:(void *)structData structDefine:(NSDictionary *)structDefine\n{\n    return getDictOfStruct(structData, structDefine);\n}\n\n+ (NSMutableDictionary *)registeredStruct\n{\n    return _registeredStruct;\n}\n\n+ (NSDictionary *)overideMethods\n{\n    return _JSOverideMethods;\n}\n\n+ (NSMutableSet *)includedScriptPaths\n{\n    return _runnedScript;\n}\n\n@end\n"
  },
  {
    "path": "JSPatch/JSPatch.js",
    "content": "var global = this\n\n;(function() {\n\n  var _ocCls = {};\n  var _jsCls = {};\n\n  var _formatOCToJS = function(obj) {\n    if (obj === undefined || obj === null) return false\n    if (typeof obj == \"object\") {\n      if (obj.__obj) return obj\n      if (obj.__isNil) return false\n    }\n    if (obj instanceof Array) {\n      var ret = []\n      obj.forEach(function(o) {\n        ret.push(_formatOCToJS(o))\n      })\n      return ret\n    }\n    if (obj instanceof Function) {\n        return function() {\n            var args = Array.prototype.slice.call(arguments)\n            var formatedArgs = _OC_formatJSToOC(args)\n            for (var i = 0; i < args.length; i++) {\n                if (args[i] === null || args[i] === undefined || args[i] === false) {\n                formatedArgs.splice(i, 1, undefined)\n            } else if (args[i] == nsnull) {\n                formatedArgs.splice(i, 1, null)\n            }\n        }\n        return _OC_formatOCToJS(obj.apply(obj, formatedArgs))\n      }\n    }\n    if (obj instanceof Object) {\n      var ret = {}\n      for (var key in obj) {\n        ret[key] = _formatOCToJS(obj[key])\n      }\n      return ret\n    }\n    return obj\n  }\n  \n  var _methodFunc = function(instance, clsName, methodName, args, isSuper, isPerformSelector) {\n    var selectorName = methodName\n    if (!isPerformSelector) {\n      methodName = methodName.replace(/__/g, \"-\")\n      selectorName = methodName.replace(/_/g, \":\").replace(/-/g, \"_\")\n      var marchArr = selectorName.match(/:/g)\n      var numOfArgs = marchArr ? marchArr.length : 0\n      if (args.length > numOfArgs) {\n        selectorName += \":\"\n      }\n    }\n    var ret = instance ? _OC_callI(instance, selectorName, args, isSuper):\n                         _OC_callC(clsName, selectorName, args)\n    return _formatOCToJS(ret)\n  }\n\n  var _customMethods = {\n    __c: function(methodName) {\n      var slf = this\n\n      if (slf instanceof Boolean) {\n        return function() {\n          return false\n        }\n      }\n      if (slf[methodName]) {\n        return slf[methodName].bind(slf);\n      }\n\n      if (!slf.__obj && !slf.__clsName) {\n        throw new Error(slf + '.' + methodName + ' is undefined')\n      }\n      if (slf.__isSuper && slf.__clsName) {\n          slf.__clsName = _OC_superClsName(slf.__obj.__realClsName ? slf.__obj.__realClsName: slf.__clsName);\n      }\n      var clsName = slf.__clsName\n      if (clsName && _ocCls[clsName]) {\n        var methodType = slf.__obj ? 'instMethods': 'clsMethods'\n        if (_ocCls[clsName][methodType][methodName]) {\n          slf.__isSuper = 0;\n          return _ocCls[clsName][methodType][methodName].bind(slf)\n        }\n      }\n\n      return function(){\n        var args = Array.prototype.slice.call(arguments)\n        return _methodFunc(slf.__obj, slf.__clsName, methodName, args, slf.__isSuper)\n      }\n    },\n\n    super: function() {\n      var slf = this\n      if (slf.__obj) {\n        slf.__obj.__realClsName = slf.__realClsName;\n      }\n      return {__obj: slf.__obj, __clsName: slf.__clsName, __isSuper: 1}\n    },\n\n    performSelectorInOC: function() {\n      var slf = this\n      var args = Array.prototype.slice.call(arguments)\n      return {__isPerformInOC:1, obj:slf.__obj, clsName:slf.__clsName, sel: args[0], args: args[1], cb: args[2]}\n    },\n\n    performSelector: function() {\n      var slf = this\n      var args = Array.prototype.slice.call(arguments)\n      return _methodFunc(slf.__obj, slf.__clsName, args[0], args.splice(1), slf.__isSuper, true)\n    }\n  }\n\n  for (var method in _customMethods) {\n    if (_customMethods.hasOwnProperty(method)) {\n      Object.defineProperty(Object.prototype, method, {value: _customMethods[method], configurable:false, enumerable: false})\n    }\n  }\n\n  var _require = function(clsName) {\n    if (!global[clsName]) {\n      global[clsName] = {\n        __clsName: clsName\n      }\n    } \n    return global[clsName]\n  }\n\n  global.require = function() {\n    var lastRequire\n    for (var i = 0; i < arguments.length; i ++) {\n      arguments[i].split(',').forEach(function(clsName) {\n        lastRequire = _require(clsName.trim())\n      })\n    }\n    return lastRequire\n  }\n\n  var _formatDefineMethods = function(methods, newMethods, realClsName) {\n    for (var methodName in methods) {\n      if (!(methods[methodName] instanceof Function)) return;\n      (function(){\n        var originMethod = methods[methodName]\n        newMethods[methodName] = [originMethod.length, function() {\n          try {\n            var args = _formatOCToJS(Array.prototype.slice.call(arguments))\n            var lastSelf = global.self\n            global.self = args[0]\n            if (global.self) global.self.__realClsName = realClsName\n            args.splice(0,1)\n            var ret = originMethod.apply(originMethod, args)\n            global.self = lastSelf\n            return ret\n          } catch(e) {\n            _OC_catch(e.message, e.stack)\n          }\n        }]\n      })()\n    }\n  }\n\n  var _wrapLocalMethod = function(methodName, func, realClsName) {\n    return function() {\n      var lastSelf = global.self\n      global.self = this\n      this.__realClsName = realClsName\n      var ret = func.apply(this, arguments)\n      global.self = lastSelf\n      return ret\n    }\n  }\n\n  var _setupJSMethod = function(className, methods, isInst, realClsName) {\n    for (var name in methods) {\n      var key = isInst ? 'instMethods': 'clsMethods',\n          func = methods[name]\n      _ocCls[className][key][name] = _wrapLocalMethod(name, func, realClsName)\n    }\n  }\n\n  var _propertiesGetFun = function(name){\n    return function(){\n      var slf = this;\n      if (!slf.__ocProps) {\n        var props = _OC_getCustomProps(slf.__obj)\n        if (!props) {\n          props = {}\n          _OC_setCustomProps(slf.__obj, props)\n        }\n        slf.__ocProps = props;\n      }\n      return slf.__ocProps[name];\n    };\n  }\n\n  var _propertiesSetFun = function(name){\n    return function(jval){\n      var slf = this;\n      if (!slf.__ocProps) {\n        var props = _OC_getCustomProps(slf.__obj)\n        if (!props) {\n          props = {}\n          _OC_setCustomProps(slf.__obj, props)\n        }\n        slf.__ocProps = props;\n      }\n      slf.__ocProps[name] = jval;\n    };\n  }\n\n  global.defineClass = function(declaration, properties, instMethods, clsMethods) {\n    var newInstMethods = {}, newClsMethods = {}\n    if (!(properties instanceof Array)) {\n      clsMethods = instMethods\n      instMethods = properties\n      properties = null\n    }\n\n    if (properties) {\n      properties.forEach(function(name){\n        if (!instMethods[name]) {\n          instMethods[name] = _propertiesGetFun(name);\n        }\n        var nameOfSet = \"set\"+ name.substr(0,1).toUpperCase() + name.substr(1);\n        if (!instMethods[nameOfSet]) {\n          instMethods[nameOfSet] = _propertiesSetFun(name);\n        }\n      });\n    }\n\n    var realClsName = declaration.split(':')[0].trim()\n\n    _formatDefineMethods(instMethods, newInstMethods, realClsName)\n    _formatDefineMethods(clsMethods, newClsMethods, realClsName)\n\n    var ret = _OC_defineClass(declaration, newInstMethods, newClsMethods)\n    var className = ret['cls']\n    var superCls = ret['superCls']\n\n    _ocCls[className] = {\n      instMethods: {},\n      clsMethods: {},\n    }\n\n    if (superCls.length && _ocCls[superCls]) {\n      for (var funcName in _ocCls[superCls]['instMethods']) {\n        _ocCls[className]['instMethods'][funcName] = _ocCls[superCls]['instMethods'][funcName]\n      }\n      for (var funcName in _ocCls[superCls]['clsMethods']) {\n        _ocCls[className]['clsMethods'][funcName] = _ocCls[superCls]['clsMethods'][funcName]\n      }\n    }\n\n    _setupJSMethod(className, instMethods, 1, realClsName)\n    _setupJSMethod(className, clsMethods, 0, realClsName)\n\n    return require(className)\n  }\n\n  global.defineProtocol = function(declaration, instProtos , clsProtos) {\n      var ret = _OC_defineProtocol(declaration, instProtos,clsProtos);\n      return ret\n  }\n\n  global.block = function(args, cb) {\n    var that = this\n    var slf = global.self\n    if (args instanceof Function) {\n      cb = args\n      args = ''\n    }\n    var callback = function() {\n      var args = Array.prototype.slice.call(arguments)\n      global.self = slf\n      return cb.apply(that, _formatOCToJS(args))\n    }\n    var ret = {args: args, cb: callback, argCount: cb.length, __isBlock: 1}\n    if (global.__genBlock) {\n      ret['blockObj'] = global.__genBlock(args, cb)\n    }\n    return ret\n  }\n  \n  if (global.console) {\n    var jsLogger = console.log;\n    global.console.log = function() {\n      global._OC_log.apply(global, arguments);\n      if (jsLogger) {\n        jsLogger.apply(global.console, arguments);\n      }\n    }\n  } else {\n    global.console = {\n      log: global._OC_log\n    }\n  }\n\n  global.defineJSClass = function(declaration, instMethods, clsMethods) {\n    var o = function() {},\n        a = declaration.split(':'),\n        clsName = a[0].trim(),\n        superClsName = a[1] ? a[1].trim() : null\n    o.prototype = {\n      init: function() {\n        if (this.super()) this.super().init()\n        return this;\n      },\n      super: function() {\n        return superClsName ? _jsCls[superClsName].prototype : null\n      }\n    }\n    var cls = {\n      alloc: function() {\n        return new o;\n      }\n    }\n    for (var methodName in instMethods) {\n      o.prototype[methodName] = instMethods[methodName];\n    }\n    for (var methodName in clsMethods) {\n      cls[methodName] = clsMethods[methodName];\n    }\n    global[clsName] = cls\n    _jsCls[clsName] = o\n  }\n  \n  global.YES = 1\n  global.NO = 0\n  global.nsnull = _OC_null\n  global._formatOCToJS = _formatOCToJS\n  \n})()\n"
  },
  {
    "path": "JSPatch.podspec",
    "content": "Pod::Spec.new do |s|\n  s.name         = \"JSPatch\"\n  s.version      = \"1.1.3\"\n  s.summary      = \"JSPatch bridge Objective-C and JavaScript. You can call any\"  \\\n                   \" Objective-C class and method in JavaScript by just\" \\\n                   \" including a small engine.\"\n\n  s.description  = <<-DESC\n                   JSPatch bridges Objective-C and JavaScript using the\n                   Objective-C runtime. You can call any Objective-C class and\n                   method in JavaScript by just including a small engine.\n                   That makes the APP obtaining the power of script language:\n                   add modules or replacing Objective-C codes to fix bugs dynamically.\n                   DESC\n\n  s.homepage     = \"https://github.com/bang590/JSPatch\"\n  s.license      = { :type => \"MIT\", :file => \"LICENSE\" }\n  s.author             = { \"bang\" => \"bang590@gmail.com\" }\n  s.social_media_url   = \"https://twitter.com/bang590\"\n\n  s.ios.deployment_target = '6.0'\n  s.tvos.deployment_target = '9.0'\n  s.osx.deployment_target = '10.9'\n  s.source       = { :git => \"https://github.com/bang590/JSPatch.git\", :tag => s.version }\n\n  s.frameworks   = \"Foundation\"\n  s.weak_framework = \"JavaScriptCore\"\n  s.default_subspec = 'Core'\n\n  s.subspec 'Core' do |ss|\n    ss.ios.source_files = \"JSPatch/*.{h,m}\"\n    ss.tvos.source_files = \"JSPatch/*.{h,m}\"\n    ss.osx.source_files = \"JSPatch/*.{h,m}\"\n    ss.public_header_files = \"JSPatch/*.h\"\n    ss.resources    = \"JSPatch/*.js\"\n  end\n\n  s.subspec \"Extensions\" do |ss|\n    ss.ios.source_files = \"Extensions/*\" \n    ss.ios.public_header_files = \"Extensions/*.h\"\n    ss.dependency 'JSPatch/Core'\n  end\n\n  s.subspec \"JPCFunction\" do |ss|\n    ss.ios.source_files = \"Extensions/JPCFunction/**/*\", \"Extensions/JPLibffi/**/*.{h,m}\"\n    ss.ios.public_header_files = \"Extensions/JPCFunction/**/*.h\", \"Extensions/JPLibffi/**/*.h\" \n    ss.vendored_libraries = 'Extensions/JPLibffi/libffi/libffi.a'\n    ss.dependency 'JSPatch/Core'\n  end\n\n  s.subspec \"JPBlock\" do |ss|\n    ss.ios.source_files = \"Extensions/JPBlock/**/*\", \"Extensions/JPLibffi/**/*.{h,m}\" \n    ss.ios.public_header_files = \"Extensions/JPBlock/**/*.h\", \"Extensions/JPLibffi/**/*.h\" \n    ss.vendored_libraries = 'Extensions/JPLibffi/libffi/libffi.a'\n    ss.dependency 'JSPatch/Core'\n  end\n\n  s.subspec \"JPCFunctionBinder\" do |ss|\n    ss.ios.source_files = \"Extensions/JPCFunctionBinder/**/*\" \n    ss.ios.public_header_files = \"Extensions/JPCFunctionBinder/**/*.h\"\n    ss.dependency 'JSPatch/Core'\n  end\n\n  s.subspec 'Loader' do |ss|\n    ss.ios.source_files = \"Loader/**/*.{h,m,c}\"\n    ss.tvos.source_files = \"Loader/**/*.{h,m,c}\"\n    ss.ios.public_header_files = \"Loader/*.h\"\n    ss.tvos.public_header_files = \"Loader/*.h\"\n    ss.dependency 'JSPatch/Core'\n    ss.library = 'z'\n  end\nend\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 bang\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n"
  },
  {
    "path": "Loader/JPLoader.h",
    "content": "//\n//  JSPatch.h\n//  JSPatch\n//\n//  Created by bang on 15/11/14.\n//  Copyright (c) 2015 bang. All rights reserved.\n//\n\n#import <Foundation/Foundation.h>\n\nconst static NSString *rootUrl = @\"\";\nstatic NSString *publicKey = @\"-----BEGIN PUBLIC KEY-----\\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+1xcYsEE+ab/Ame1/HHAgfBRh\\nD67I9mBYCiOJqC3lJX5RKFvtOTcF5Sf5Bz3NL/2QWPLu40+yt4EvjZ3HOUAHrVgo\\n2Fjo4vpaRoEaEtaccOziPH/ASScOfL+uppNGOa0glTCZLKVZI3Go8zoutr8VDw2d\\nNT7rDM/4TvPjwMYd3QIDAQAB\\n-----END PUBLIC KEY-----\";\n\ntypedef void (^JPUpdateCallback)(NSError *error);\n\ntypedef enum {\n    JPUpdateErrorUnzipFailed = -1001,\n    JPUpdateErrorVerifyFailed = -1002,\n} JPUpdateError;\n\n@interface JPLoader : NSObject\n+ (BOOL)run;\n+ (void)updateToVersion:(NSInteger)version callback:(JPUpdateCallback)callback;\n+ (void)runTestScriptInBundle;\n+ (void)setLogger:(void(^)(NSString *log))logger;\n+ (NSInteger)currentVersion;\n@end"
  },
  {
    "path": "Loader/JPLoader.m",
    "content": "//\n//  JSPatch.m\n//  JSPatch\n//\n//  Created by bang on 15/11/14.\n//  Copyright (c) 2015 bang. All rights reserved.\n//\n\n#import \"JPLoader.h\"\n#import \"JPEngine.h\"\n#import \"ZipArchive.h\"\n#import \"RSA.h\"\n#import <CommonCrypto/CommonDigest.h>\n\n#define kJSPatchVersion(appVersion)   [NSString stringWithFormat:@\"JSPatchVersion_%@\", appVersion]\n\nvoid (^JPLogger)(NSString *log);\n\n#pragma mark - Extension\n\n@interface JPLoaderInclude : JPExtension\n\n@end\n\n@implementation JPLoaderInclude\n\n+ (void)main:(JSContext *)context\n{\n    context[@\"include\"] = ^(NSString *filePath) {\n        if (!filePath.length || [filePath rangeOfString:@\".js\"].location == NSNotFound) {\n            return;\n        }\n        NSString *appVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@\"CFBundleShortVersionString\"];\n        NSString *libraryDirectory = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) firstObject];\n        NSString *scriptPath = [libraryDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@\"JSPatch/%@/%@\", appVersion, filePath]];\n        if ([[NSFileManager defaultManager] fileExistsAtPath:scriptPath]) {\n            [JPEngine startEngine];\n            [JPEngine evaluateScriptWithPath:scriptPath];\n        }\n    };\n}\n\n@end\n\n@interface JPLoaderTestInclude : JPExtension\n\n@end\n\n@implementation JPLoaderTestInclude\n\n+ (void)main:(JSContext *)context\n{\n    context[@\"include\"] = ^(NSString *filePath) {\n        NSArray *component = [filePath componentsSeparatedByString:@\".\"];\n        if (component.count > 1) {\n            NSString *testPath = [[NSBundle bundleForClass:[self class]] pathForResource:component[0] ofType:component[1]];\n            [JPEngine evaluateScriptWithPath:testPath];\n        }\n    };\n}\n\n@end\n\n#pragma mark - Loader\n\n@implementation JPLoader\n\n+ (BOOL)run\n{\n    if (JPLogger) JPLogger(@\"JSPatch: runScript\");\n    \n    NSString *scriptDirectory = [self fetchScriptDirectory];\n    NSString *scriptPath = [scriptDirectory stringByAppendingPathComponent:@\"main.js\"];\n    \n    if ([[NSFileManager defaultManager] fileExistsAtPath:scriptPath]) {\n        [JPEngine startEngine];\n        [JPEngine addExtensions:@[@\"JPLoaderInclude\"]];\n        [JPEngine evaluateScriptWithPath:scriptPath];\n        if (JPLogger) JPLogger([NSString stringWithFormat:@\"JSPatch: evaluated script %@\", scriptPath]);\n        return YES;\n    } else {\n        return NO;\n    }\n}\n\n+ (void)updateToVersion:(NSInteger)version callback:(JPUpdateCallback)callback\n{\n    NSString *appVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@\"CFBundleShortVersionString\"];\n    \n    if (JPLogger) JPLogger([NSString stringWithFormat:@\"JSPatch: updateToVersion: %@\", @(version)]);\n    \n    // create url request\n    NSString *downloadKey = [NSString stringWithFormat:@\"/%@/v%@.zip\", appVersion, @(version)];\n    NSURL *downloadURL = [NSURL URLWithString:[rootUrl stringByAppendingString:downloadKey]];\n    NSURLRequest *request = [NSURLRequest requestWithURL:downloadURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:20.0];\n    \n    if (JPLogger) JPLogger([NSString stringWithFormat:@\"JSPatch: request file %@\", downloadURL]);\n    \n    // create task\n    NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {\n        if (!error) {\n            if (JPLogger) JPLogger([NSString stringWithFormat:@\"JSPatch: request file success, data length:%@\", @(data.length)]);\n            \n            // script directory\n            NSString *scriptDirectory = [self fetchScriptDirectory];\n            \n            // temporary files and directories\n            NSString *downloadTmpPath = [NSString stringWithFormat:@\"%@patch_%@_%@\", NSTemporaryDirectory(), appVersion, @(version)];\n            NSString *unzipVerifyDirectory = [NSString stringWithFormat:@\"%@patch_%@_%@_unzipTest/\", NSTemporaryDirectory(), appVersion, @(version)];\n            NSString *unzipTmpDirectory = [NSString stringWithFormat:@\"%@patch_%@_%@_unzip/\", NSTemporaryDirectory(), appVersion, @(version)];\n            \n            // save data\n            [data writeToFile:downloadTmpPath atomically:YES];\n            \n            // is the processing flow failed\n            BOOL isFailed = NO;\n            \n            // 1. unzip encrypted md5 file and script file\n            NSString *keyFilePath;\n            NSString *scriptZipFilePath;\n            ZipArchive *verifyZipArchive = [[ZipArchive alloc] init];\n            [verifyZipArchive UnzipOpenFile:downloadTmpPath];\n            BOOL verifyUnzipSucc = [verifyZipArchive UnzipFileTo:unzipVerifyDirectory overWrite:YES];\n            if (verifyUnzipSucc) {\n                for (NSString *filePath in verifyZipArchive.unzippedFiles) {\n                    NSString *filename = [filePath lastPathComponent];\n                    if ([filename isEqualToString:@\"key\"]) {\n                        // encrypted md5 file\n                        keyFilePath = filePath;\n                    } else if ([[filename pathExtension] isEqualToString:@\"zip\"]) {\n                        // script file\n                        scriptZipFilePath = filePath;\n                    }\n                }\n            } else {\n                if (JPLogger) JPLogger(@\"JSPatch: fail to unzip file\");\n                isFailed = YES;\n                \n                if (callback) {\n                    callback([NSError errorWithDomain:@\"org.jspatch\" code:JPUpdateErrorUnzipFailed userInfo:nil]);\n                }\n            }\n            \n            // 2. decrypt and verify md5 file\n            if (!isFailed) {\n                NSData *md5Data = [RSA decryptData:[NSData dataWithContentsOfFile:keyFilePath] publicKey:publicKey];\n                NSString *decryptMD5 = [[NSString alloc] initWithData:md5Data encoding:NSUTF8StringEncoding];\n                NSString *md5 = [self fileMD5:scriptZipFilePath];\n                if (![decryptMD5 isEqualToString:md5]) {\n                    if (JPLogger) JPLogger([NSString stringWithFormat:@\"JSPatch: decompress error, md5 didn't match, decrypt:%@ md5:%@\", decryptMD5, md5]);\n                    isFailed = YES;\n                    \n                    if (callback) {\n                        callback([NSError errorWithDomain:@\"org.jspatch\" code:JPUpdateErrorVerifyFailed userInfo:nil]);\n                    }\n                }\n            }\n            \n            // 3. unzip script file and save\n            if (!isFailed) {\n                ZipArchive *zipArchive = [[ZipArchive alloc] init];\n                [zipArchive UnzipOpenFile:scriptZipFilePath];\n                BOOL unzipSucc = [zipArchive UnzipFileTo:unzipTmpDirectory overWrite:YES];\n                if (unzipSucc) {\n                    for (NSString *filePath in zipArchive.unzippedFiles) {\n                        NSString *filename = [filePath lastPathComponent];\n                        if ([[filename pathExtension] isEqualToString:@\"js\"]) {\n                            [[NSFileManager defaultManager] createDirectoryAtPath:scriptDirectory withIntermediateDirectories:YES attributes:nil error:nil];\n                            NSString *newFilePath = [scriptDirectory stringByAppendingPathComponent:filename];\n                            [[NSData dataWithContentsOfFile:filePath] writeToFile:newFilePath atomically:YES];\n                        }\n                    }\n                }\n                else\n                {\n                    if (JPLogger) JPLogger(@\"JSPatch: fail to unzip script file\");\n                    isFailed = YES;\n                    \n                    if (callback) {\n                        callback([NSError errorWithDomain:@\"org.jspatch\" code:JPUpdateErrorUnzipFailed userInfo:nil]);\n                    }\n                }\n            }\n            \n            // success\n            if (!isFailed) {\n                if (JPLogger) JPLogger([NSString stringWithFormat:@\"JSPatch: updateToVersion: %@ success\", @(version)]);\n                \n                [[NSUserDefaults standardUserDefaults] setInteger:version forKey:kJSPatchVersion(appVersion)];\n                [[NSUserDefaults standardUserDefaults] synchronize];\n                \n                if (callback) callback(nil);\n            }\n            \n            // clear temporary files\n            [[NSFileManager defaultManager] removeItemAtPath:downloadTmpPath error:nil];\n            [[NSFileManager defaultManager] removeItemAtPath:unzipVerifyDirectory error:nil];\n            [[NSFileManager defaultManager] removeItemAtPath:unzipTmpDirectory error:nil];\n        } else {\n            if (JPLogger) JPLogger([NSString stringWithFormat:@\"JSPatch: request error %@\", error]);\n            \n            if (callback) callback(error);\n        }\n    }];\n    [task resume];\n}\n\n+ (void)runTestScriptInBundle\n{\n    [JPEngine startEngine];\n    [JPEngine addExtensions:@[@\"JPLoaderTestInclude\"]];\n    \n    NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@\"main\" ofType:@\"js\"];\n    NSAssert(path, @\"can't find main.js\");\n    NSString *script = [[NSString alloc] initWithData:[[NSFileManager defaultManager] contentsAtPath:path] encoding:NSUTF8StringEncoding];\n    [JPEngine evaluateScript:script];\n}\n\n+ (void)setLogger:(void (^)(NSString *))logger {\n    JPLogger = [logger copy];\n}\n\n+ (NSInteger)currentVersion\n{\n    NSString *appVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@\"CFBundleShortVersionString\"];\n    return [[NSUserDefaults standardUserDefaults] integerForKey:kJSPatchVersion(appVersion)];\n}\n\n+ (NSString *)fetchScriptDirectory\n{\n    NSString *appVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@\"CFBundleShortVersionString\"];\n    NSString *libraryDirectory = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) firstObject];\n    NSString *scriptDirectory = [libraryDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@\"JSPatch/%@/\", appVersion]];\n    return scriptDirectory;\n}\n\n#pragma mark utils\n\n+ (NSString *)fileMD5:(NSString *)filePath\n{\n    NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:filePath];\n    if(!handle)\n    {\n        return nil;\n    }\n    \n    CC_MD5_CTX md5;\n    CC_MD5_Init(&md5);\n    BOOL done = NO;\n    while (!done)\n    {\n        NSData *fileData = [handle readDataOfLength:256];\n        CC_MD5_Update(&md5, [fileData bytes], (CC_LONG)[fileData length]);\n        if([fileData length] == 0)\n            done = YES;\n    }\n    \n    unsigned char digest[CC_MD5_DIGEST_LENGTH];\n    CC_MD5_Final(digest, &md5);\n    \n    NSString *result = [NSString stringWithFormat:@\"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\",\n                        digest[0], digest[1],\n                        digest[2], digest[3],\n                        digest[4], digest[5],\n                        digest[6], digest[7],\n                        digest[8], digest[9],\n                        digest[10], digest[11],\n                        digest[12], digest[13],\n                        digest[14], digest[15]];\n    return result;\n}\n\n@end"
  },
  {
    "path": "Loader/libs/RSA.h",
    "content": "/*\n @author: ideawu\n @link: https://github.com/ideawu/Objective-C-RSA\n*/\n\n#import <Foundation/Foundation.h>\n\n@interface RSA : NSObject\n\n// return base64 encoded string\n+ (NSString *)encryptString:(NSString *)str publicKey:(NSString *)pubKey;\n// return raw data\n+ (NSData *)encryptData:(NSData *)data publicKey:(NSString *)pubKey;\n\n// decrypt base64 encoded string, convert result to string(not base64 encoded)\n+ (NSString *)decryptString:(NSString *)str publicKey:(NSString *)pubKey;\n+ (NSData *)decryptData:(NSData *)data publicKey:(NSString *)pubKey;\n\n@end\n"
  },
  {
    "path": "Loader/libs/RSA.m",
    "content": "/*\n @author: ideawu\n @link: https://github.com/ideawu/Objective-C-RSA\n */\n\n#import \"RSA.h\"\n#import <Security/Security.h>\n\n@implementation RSA\n\n\nstatic NSString *base64_encode_data(NSData *data){\n    data = [data base64EncodedDataWithOptions:0];\n    NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];\n    return ret;\n}\n\nstatic NSData *base64_decode(NSString *str){\n    NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];\n    return data;\n}\n\n+ (NSData *)stripPublicKeyHeader:(NSData *)d_key{\n    // Skip ASN.1 public key header\n    if (d_key == nil) return(nil);\n    \n    unsigned long len = [d_key length];\n    if (!len) return(nil);\n    \n    unsigned char *c_key = (unsigned char *)[d_key bytes];\n    unsigned int  idx\t= 0;\n    \n    if (c_key[idx++] != 0x30) return(nil);\n    \n    if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;\n    else idx++;\n    \n    // PKCS #1 rsaEncryption szOID_RSA_RSA\n    static unsigned char seqiod[] =\n    { 0x30,   0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,\n        0x01, 0x05, 0x00 };\n    if (memcmp(&c_key[idx], seqiod, 15)) return(nil);\n    \n    idx += 15;\n    \n    if (c_key[idx++] != 0x03) return(nil);\n    \n    if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;\n    else idx++;\n    \n    if (c_key[idx++] != '\\0') return(nil);\n    \n    // Now make a new NSData from this buffer\n    return([NSData dataWithBytes:&c_key[idx] length:len - idx]);\n}\n\n+ (SecKeyRef)addPublicKey:(NSString *)key{\n    NSRange spos = [key rangeOfString:@\"-----BEGIN PUBLIC KEY-----\"];\n    NSRange epos = [key rangeOfString:@\"-----END PUBLIC KEY-----\"];\n    if(spos.location != NSNotFound && epos.location != NSNotFound){\n        NSUInteger s = spos.location + spos.length;\n        NSUInteger e = epos.location;\n        NSRange range = NSMakeRange(s, e-s);\n        key = [key substringWithRange:range];\n    }\n    key = [key stringByReplacingOccurrencesOfString:@\"\\r\" withString:@\"\"];\n    key = [key stringByReplacingOccurrencesOfString:@\"\\n\" withString:@\"\"];\n    key = [key stringByReplacingOccurrencesOfString:@\"\\t\" withString:@\"\"];\n    key = [key stringByReplacingOccurrencesOfString:@\" \"  withString:@\"\"];\n    \n    // This will be base64 encoded, decode it.\n    NSData *data = base64_decode(key);\n    data = [RSA stripPublicKeyHeader:data];\n    if(!data){\n        return nil;\n    }\n    \n    NSString *tag = @\"what_the_fuck_is_this\";\n    NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];\n    \n    // Delete any old lingering key with the same tag\n    NSMutableDictionary *publicKey = [[NSMutableDictionary alloc] init];\n    [publicKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];\n    [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];\n    [publicKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];\n    SecItemDelete((__bridge CFDictionaryRef)publicKey);\n    \n    // Add persistent version of the key to system keychain\n    [publicKey setObject:data forKey:(__bridge id)kSecValueData];\n    [publicKey setObject:(__bridge id) kSecAttrKeyClassPublic forKey:(__bridge id)\n     kSecAttrKeyClass];\n    [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)\n     kSecReturnPersistentRef];\n    \n    CFTypeRef persistKey = nil;\n    OSStatus status = SecItemAdd((__bridge CFDictionaryRef)publicKey, &persistKey);\n    if (persistKey != nil){\n        CFRelease(persistKey);\n    }\n    if ((status != noErr) && (status != errSecDuplicateItem)) {\n        return nil;\n    }\n    \n    [publicKey removeObjectForKey:(__bridge id)kSecValueData];\n    [publicKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];\n    [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];\n    [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];\n    \n    // Now fetch the SecKeyRef version of the key\n    SecKeyRef keyRef = nil;\n    status = SecItemCopyMatching((__bridge CFDictionaryRef)publicKey, (CFTypeRef *)&keyRef);\n    if(status != noErr){\n        return nil;\n    }\n    return keyRef;\n}\n\n+ (NSString *)encryptString:(NSString *)str publicKey:(NSString *)pubKey{\n    NSData *data = [RSA encryptData:[str dataUsingEncoding:NSUTF8StringEncoding] publicKey:pubKey];\n    NSString *ret = base64_encode_data(data);\n    return ret;\n}\n\n+ (NSData *)encryptData:(NSData *)data publicKey:(NSString *)pubKey{\n    if(!data || !pubKey){\n        return nil;\n    }\n    SecKeyRef keyRef = [RSA addPublicKey:pubKey];\n    if(!keyRef){\n        return nil;\n    }\n    \n    const uint8_t *srcbuf = (const uint8_t *)[data bytes];\n    size_t srclen = (size_t)data.length;\n    \n    size_t outlen = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t);\n    if(srclen > outlen - 11){\n        CFRelease(keyRef);\n        return nil;\n    }\n    void *outbuf = malloc(outlen);\n    \n    OSStatus status = noErr;\n    status = SecKeyEncrypt(keyRef,\n                           kSecPaddingPKCS1,\n                           srcbuf,\n                           srclen,\n                           outbuf,\n                           &outlen\n                           );\n    NSData *ret = nil;\n    if (status != 0) {\n        //NSLog(@\"SecKeyEncrypt fail. Error Code: %ld\", status);\n    }else{\n        ret = [NSData dataWithBytes:outbuf length:outlen];\n    }\n    free(outbuf);\n    CFRelease(keyRef);\n    return ret;\n}\n\n+ (NSString *)decryptString:(NSString *)str publicKey:(NSString *)pubKey{\n    NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];\n    data = [RSA decryptData:data publicKey:pubKey];\n    NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];\n    return ret;\n}\n\n+ (NSData *)decryptData:(NSData *)data publicKey:(NSString *)pubKey{\n    if(!data || !pubKey){\n        return nil;\n    }\n    SecKeyRef keyRef = [RSA addPublicKey:pubKey];\n    if(!keyRef){\n        return nil;\n    }\n    \n    const uint8_t *srcbuf = (const uint8_t *)[data bytes];\n    size_t srclen = (size_t)data.length;\n    \n    size_t outlen = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t);\n//    if(srclen != outlen){\n//        //TODO currently we are able to decrypt only one block!\n//        CFRelease(keyRef);\n//        return nil;\n//    }\n    UInt8 *outbuf = malloc(outlen);\n    \n    //use kSecPaddingNone in decryption mode\n    OSStatus status = noErr;\n    status = SecKeyDecrypt(keyRef,\n                           kSecPaddingNone,\n                           srcbuf,\n                           srclen,\n                           outbuf,\n                           &outlen\n                           );\n    NSData *result = nil;\n    if (status != 0) {\n        //NSLog(@\"SecKeyEncrypt fail. Error Code: %ld\", status);\n    }else{\n        //the actual decrypted data is in the middle, locate it!\n        int idxFirstZero = -1;\n        int idxNextZero = (int)outlen;\n        for ( int i = 0; i < outlen; i++ ) {\n            if ( outbuf[i] == 0 ) {\n                if ( idxFirstZero < 0 ) {\n                    idxFirstZero = i;\n                } else {\n                    idxNextZero = i;\n                    break;\n                }\n            }\n        }\n        \n        result = [NSData dataWithBytes:&outbuf[idxFirstZero+1] length:idxNextZero-idxFirstZero-1];\n    }\n    free(outbuf);\n    CFRelease(keyRef);\n    return result;\n}\n\n@end\n"
  },
  {
    "path": "Loader/libs/ZipArchive.h",
    "content": "/**\n//  @header ZipArchive.h\n//  \n//  An objective C wrapper for minizip and libz for creating and exanding ZIP files.\n//\n//  @author Created by aish on 08-9-11.\n//  acsolu@gmail.com\n//  @copyright Copyright 2008  Inc. All rights reserved.\n//\n*/\n\n#import <Foundation/Foundation.h>\n\n\n/**\n a block that is called from UnzipFileTo:overwrite:withProgressBlock: where the percentage of\n files processed (as an integer from 0 to 100), the number of files processed so far and the\n total number of files in the archive is called after each file is processed.\n */\ntypedef void(^ZipArchiveProgressUpdateBlock)(int percentage, int filesProcessed, unsigned long numFiles);\n\t\n/**\n    @protocol\n    @discussion  methods for a delegate to receive error notifications and control overwriting of files\n*/\n\n@protocol ZipArchiveDelegate <NSObject>\n@optional\n\n/**\n    @brief   Delegate method to be notified of errors\n    \n    ZipArchive calls this selector on the delegate when errors are encountered.\n    \n    @param      msg     a string describing the error.\n    @result     void\n*/\n\n-(void) ErrorMessage:(NSString*) msg;\n\n/**\n    @brief   Delegate method to determine if a file should be replaced\n    \n    When an zip file is being expanded and a file is about to be replaced, this selector\n    is called on the delegate to notify that file is about to be replaced. The delegate method\n    should return YES to overwrite the file, or NO to skip it.\n \n    @param      file - path to the file to be overwritten.\n    @result     a BOOL - YES to replace, NO to skip\n*/\n\n-(BOOL) OverWriteOperation:(NSString*) file;\n\n@end\n\n/**\n    @class\n    @brief      An object that can create zip files and expand existing ones.\n    This class provides methods to create a zip file (optionally with a password) and\n    add files to that zip archive. \n                 \n    It also provides methods to expand an existing archive file (optionally with a password),\n    and extract the files.\n*/\n\n@interface ZipArchive : NSObject {\n@private\n\tvoid*           _zipFile;\n\tvoid*           _unzFile;\n\t\n    unsigned long   _numFiles;\n\tNSString*       _password;\n\t__weak id       _delegate;\n    ZipArchiveProgressUpdateBlock _progressBlock;\n    \n    NSArray*    _unzippedFiles;\n    \n    NSFileManager* _fileManager;\n    NSStringEncoding _stringEncoding;\n}\n\n/** a delegate object conforming to ZipArchiveDelegate protocol */\n@property (nonatomic, weak) id<ZipArchiveDelegate> delegate;\n@property (nonatomic, readonly) unsigned long numFiles;\n@property (nonatomic, copy) ZipArchiveProgressUpdateBlock progressBlock;\n\n/**\n    @brief      String encoding to be used when interpreting file names in the zip file.\n*/\n@property (nonatomic, assign) NSStringEncoding stringEncoding;\n\n/** an array of files that were successfully expanded. Available after calling UnzipFileTo:overWrite: */\n@property (nonatomic, readonly,strong) NSArray *unzippedFiles;\n\n-(id) initWithFileManager:(NSFileManager*) fileManager;\n\n-(BOOL) CreateZipFile2:(NSString*) zipFile;\n-(BOOL) CreateZipFile2:(NSString*) zipFile Password:(NSString*) password;\n-(BOOL) addFileToZip:(NSString*) file newname:(NSString*) newname;\n-(BOOL) CloseZipFile2;\n\n-(BOOL) UnzipOpenFile:(NSString*) zipFile;\n-(BOOL) UnzipOpenFile:(NSString*) zipFile Password:(NSString*) password;\n-(BOOL) UnzipFileTo:(NSString*) path overWrite:(BOOL) overwrite;\n-(BOOL) UnzipCloseFile;\n-(NSArray*) getZipFileContents;     // list the contents of the zip archive. must be called after UnzipOpenFile\n\n@end\n"
  },
  {
    "path": "Loader/libs/ZipArchive.m",
    "content": "/**\n//  ZipArchive.m\n//  \n//\n//  Created by aish on 08-9-11.\n//  acsolu@gmail.com\n//  Copyright 2008  Inc. All rights reserved.\n//\n*/\n\n#import \"ZipArchive.h\"\n#import \"zlib.h\"\n#import \"zconf.h\"\n#include \"zip.h\"\n#include \"unzip.h\"\n\n\n@interface NSFileManager(ZipArchive)\n- (NSDictionary *)_attributesOfItemAtPath:(NSString *)path followingSymLinks:(BOOL)followingSymLinks error:(NSError **)error;\n@end\n\n@interface ZipArchive ()\n\n-(void) OutputErrorMessage:(NSString*) msg;\n-(BOOL) OverWrite:(NSString*) file;\n-(NSDate*) Date1980;\n\n@property (nonatomic,copy) NSString* password;\n@end\n\n\n\n@implementation ZipArchive\n@synthesize delegate = _delegate;\n@synthesize numFiles = _numFiles;\n@synthesize password = _password;\n@synthesize unzippedFiles = _unzippedFiles;\n@synthesize progressBlock = _progressBlock;\n@synthesize stringEncoding = _stringEncoding;\n\n-(id) init\n{\n    return [self initWithFileManager:[NSFileManager defaultManager]];\n}\n\n-(id) initWithFileManager:(NSFileManager*) fileManager\n{\n\tif( self=[super init] )\n\t{\n\t\t_zipFile = NULL;\n        _fileManager = fileManager;\n        self.stringEncoding = NSUTF8StringEncoding;\n\t}\n\treturn self;\n}\n\n-(void) dealloc\n{\n    // close any open file operations\n\t[self CloseZipFile2];\n    [self UnzipCloseFile];\n    \n    // release retained/copied properties.\n    \n}\n\n/**\n * Create a new zip file at the specified path, ready for new files to be added.\n *\n * @param zipFile     the path of the zip file to create\n * @returns BOOL YES on success\n */\n\n-(BOOL) CreateZipFile2:(NSString*) zipFile\n{\n\t_zipFile = zipOpen( (const char*)[zipFile UTF8String], 0 );\n\tif( !_zipFile ) \n\t\treturn NO;\n\treturn YES;\n}\n\n/**\n * Create a new zip file at the specified path, ready for new files to be added.\n *\n * @param zipFile     the path of the zip file to create\n * @param password    a password used to encrypt the zip file\n * @returns BOOL YES on success\n */\n\n-(BOOL) CreateZipFile2:(NSString*) zipFile Password:(NSString*) password\n{\n\tself.password = password;\n\treturn [self CreateZipFile2:zipFile];\n}\n\n/**\n * add an existing file on disk to the zip archive, compressing it.\n *\n * @param file    the path to the file to compress\n * @param newname the name of the file in the zip archive, ie: path relative to the zip archive root.\n * @returns BOOL YES on success\n */\n\n-(BOOL) addFileToZip:(NSString*) file newname:(NSString*) newname;\n{\n\tif( !_zipFile )\n\t\treturn NO;\n//\ttm_zip filetime;\n\t\n\tzip_fileinfo zipInfo = {{0}};\n\n\tNSDate* fileDate = nil;\n    \n    NSError* error = nil;\n\tNSDictionary* attr = [_fileManager _attributesOfItemAtPath:file followingSymLinks:YES error:&error];\n\tif( attr )\n\t\tfileDate = (NSDate*)[attr objectForKey:NSFileModificationDate];\n\n\tif( fileDate == nil )\n        fileDate = [NSDate date];\n\n    \n    NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];\n    NSDateComponents* components = [gregorianCalendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay |\n                                    NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond fromDate:fileDate];\n    \n    zipInfo.tmz_date.tm_sec = (uInt)components.second;\n    zipInfo.tmz_date.tm_min = (uInt)components.minute;\n    zipInfo.tmz_date.tm_hour = (uInt)components.hour;\n    zipInfo.tmz_date.tm_mday = (uInt)components.day;\n    zipInfo.tmz_date.tm_mon = (uInt)components.month;\n    zipInfo.tmz_date.tm_year = (uInt)components.year;\n    \n\t\n\tint ret ;\n\tNSData* data = nil;\n\tif( [_password length] == 0 )\n\t{\n\t\tret = zipOpenNewFileInZip( _zipFile,\n\t\t\t\t\t\t\t\t  (const char*) [newname cStringUsingEncoding:self.stringEncoding],\n\t\t\t\t\t\t\t\t  &zipInfo,\n\t\t\t\t\t\t\t\t  NULL,0,\n\t\t\t\t\t\t\t\t  NULL,0,\n\t\t\t\t\t\t\t\t  NULL,//comment\n\t\t\t\t\t\t\t\t  Z_DEFLATED,\n\t\t\t\t\t\t\t\t  Z_DEFAULT_COMPRESSION );\n\t}\n\telse\n\t{\n\t\tdata = [ NSData dataWithContentsOfFile:file];\n\t\tuLong crcValue = crc32( 0L,NULL, 0L );\n\t\tcrcValue = crc32( crcValue, (const Bytef*)[data bytes], (unsigned int)[data length] );\n\t\tret = zipOpenNewFileInZip3( _zipFile,\n\t\t\t\t\t\t\t\t  (const char*) [newname cStringUsingEncoding:self.stringEncoding],\n\t\t\t\t\t\t\t\t  &zipInfo,\n\t\t\t\t\t\t\t\t  NULL,0,\n\t\t\t\t\t\t\t\t  NULL,0,\n\t\t\t\t\t\t\t\t  NULL,//comment\n\t\t\t\t\t\t\t\t  Z_DEFLATED,\n\t\t\t\t\t\t\t\t  Z_DEFAULT_COMPRESSION,\n\t\t\t\t\t\t\t\t  0,\n\t\t\t\t\t\t\t\t  15,\n\t\t\t\t\t\t\t\t  8,\n\t\t\t\t\t\t\t\t  Z_DEFAULT_STRATEGY,\n\t\t\t\t\t\t\t\t  [_password cStringUsingEncoding:NSASCIIStringEncoding],\n\t\t\t\t\t\t\t\t  crcValue );\n\t}\n\tif( ret!=Z_OK )\n\t{\n\t\treturn NO;\n\t}\n\tif( data==nil )\n\t{\n\t\tdata = [ NSData dataWithContentsOfFile:file];\n\t}\n\tunsigned int dataLen = (unsigned int)[data length];\n\tret = zipWriteInFileInZip( _zipFile, (const void*)[data bytes], dataLen);\n\tif( ret!=Z_OK )\n\t{\n\t\treturn NO;\n\t}\n\tret = zipCloseFileInZip( _zipFile );\n\tif( ret!=Z_OK )\n\t\treturn NO;\n\treturn YES;\n}\n\n/**\n * Close a zip file after creating and added files to it.\n *\n * @returns BOOL YES on success\n */\n\n-(BOOL) CloseZipFile2\n{\n\tself.password = nil;\n\tif( _zipFile==NULL )\n\t\treturn NO;\n\tBOOL ret =  zipClose( _zipFile,NULL )==Z_OK?YES:NO;\n\t_zipFile = NULL;\n\treturn ret;\n}\n\n/**\n * open an existing zip file ready for expanding.\n *\n * @param zipFile     the path to a zip file to be opened.\n * @returns BOOL YES on success\n */\n\n-(BOOL) UnzipOpenFile:(NSString*) zipFile\n{\n    // create an array to receive the list of unzipped files.\n    _unzippedFiles = [[NSMutableArray alloc] initWithCapacity:1];\n    \n\t_unzFile = unzOpen( (const char*)[zipFile UTF8String] );\n\tif( _unzFile )\n\t{\n\t\tunz_global_info  globalInfo = {0};\n\t\tif( unzGetGlobalInfo(_unzFile, &globalInfo )==UNZ_OK )\n\t\t{\n            _numFiles = globalInfo.number_entry;\n\t\t\tNSLog(@\"%lu entries in the zip file\", globalInfo.number_entry);\n\t\t}\n\t}\n\treturn _unzFile!=NULL;\n}\n\n/**\n * open an existing zip file with a password ready for expanding.\n *\n * @param zipFile     the path to a zip file to be opened.\n * @param password    the password to use decrpyting the file.\n * @returns BOOL YES on success\n */\n\n-(BOOL) UnzipOpenFile:(NSString*) zipFile Password:(NSString*) password\n{\n\tself.password = password;\n\treturn [self UnzipOpenFile:zipFile];\n}\n\n/**\n * Expand all files in the zip archive into the specified directory.\n *\n * If a delegate has been set and responds to OverWriteOperation: it can\n * return YES to overwrite a file, or NO to skip that file.\n *\n * On completion, the property `unzippedFiles` will be an array populated\n * with the full paths of each file that was successfully expanded.\n *\n * @param path    the directory where expanded files will be created\n * @param overwrite    should existing files be overwritten\n * @returns BOOL YES on success\n */\n\n-(BOOL) UnzipFileTo:(NSString*) path overWrite:(BOOL) overwrite\n{\n\tBOOL success = YES;\n    int index = 0;\n    int progress = -1;\n\tint ret = unzGoToFirstFile( _unzFile );\n\tunsigned char\t\tbuffer[4096] = {0};\n\tif( ret!=UNZ_OK )\n\t{\n\t\t[self OutputErrorMessage:@\"Failed\"];\n\t}\n    \n\tconst char* password = [_password cStringUsingEncoding:NSASCIIStringEncoding];\n\t\n\tdo{\n        @autoreleasepool {\n            if( [_password length]==0 )\n                ret = unzOpenCurrentFile( _unzFile );\n            else\n                ret = unzOpenCurrentFilePassword( _unzFile, password );\n            if( ret!=UNZ_OK )\n            {\n                [self OutputErrorMessage:@\"Error occurs\"];\n                success = NO;\n                break;\n            }\n            // reading data and write to file\n            int read ;\n            unz_file_info\tfileInfo ={0};\n            ret = unzGetCurrentFileInfo(_unzFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0);\n            if( ret!=UNZ_OK )\n            {\n                [self OutputErrorMessage:@\"Error occurs while getting file info\"];\n                success = NO;\n                unzCloseCurrentFile( _unzFile );\n                break;\n            }\n            char* filename = (char*) malloc( fileInfo.size_filename +1 );\n            unzGetCurrentFileInfo(_unzFile, &fileInfo, filename, fileInfo.size_filename + 1, NULL, 0, NULL, 0);\n            filename[fileInfo.size_filename] = '\\0';\n            \n            // check if it contains directory\n            NSString * strPath = [NSString stringWithCString:filename encoding:self.stringEncoding];\n            BOOL isDirectory = NO;\n            if( filename[fileInfo.size_filename-1]=='/' || filename[fileInfo.size_filename-1]=='\\\\')\n                isDirectory = YES;\n            free( filename );\n            if( [strPath rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@\"/\\\\\"]].location!=NSNotFound )\n            {// contains a path\n                strPath = [strPath stringByReplacingOccurrencesOfString:@\"\\\\\" withString:@\"/\"];\n            }\n            NSString* fullPath = [path stringByAppendingPathComponent:strPath];\n            \n            if( isDirectory )\n                [_fileManager createDirectoryAtPath:fullPath withIntermediateDirectories:YES attributes:nil error:nil];\n            else\n                [_fileManager createDirectoryAtPath:[fullPath stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:nil];\n            \n            FILE* fp = NULL;\n            do\n            {\n                read = unzReadCurrentFile(_unzFile, buffer, 4096);\n                if (read >= 0)\n                {\n                    if (fp == NULL) {\n                        if( [_fileManager fileExistsAtPath:fullPath] && !isDirectory && !overwrite )\n                        {\n                            if( ![self OverWrite:fullPath] )\n                            {\n                                // don't process any more of the file, but continue\n                                break;\n                            }\n                        }\n                        if (!isDirectory) {\n                            fp = fopen( (const char*)[fullPath UTF8String], \"wb\");\n                            if (fp == NULL) {\n                                [self OutputErrorMessage:@\"Failed to open output file for writing\"];\n                                break;\n                            }\n                        }\n                    }\n                    fwrite(buffer, read, 1, fp );\n                }\n                else // if (read < 0)\n                {\n                    ret = read; // result will be an error code\n                    success = NO;\n                    [self OutputErrorMessage:@\"Failed to read zip file\"];\n                }\n            } while (read > 0);\n            \n            if (fp)\n            {\n                fclose( fp );\n                \n                // add the full path of this file to the output array\n                [(NSMutableArray*)_unzippedFiles addObject:fullPath];\n                \n                // set the orignal datetime property\n                if( fileInfo.tmu_date.tm_year!=0 )\n                {\n                    NSDateComponents* components = [[NSDateComponents alloc] init];\n                    components.second = fileInfo.tmu_date.tm_sec;\n                    components.minute = fileInfo.tmu_date.tm_min;\n                    components.hour = fileInfo.tmu_date.tm_hour;\n                    components.day = fileInfo.tmu_date.tm_mday;\n                    components.month = fileInfo.tmu_date.tm_mon;\n                    components.year = fileInfo.tmu_date.tm_year;\n                    \n                    NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];\n                    NSDate* orgDate = [gregorianCalendar dateFromComponents:components];\n                    \n                    NSDictionary* attr = [NSDictionary dictionaryWithObject:orgDate forKey:NSFileModificationDate]; //[_fileManager fileAttributesAtPath:fullPath traverseLink:YES];\n                    if( attr )\n                    {\n                        //\t[attr  setValue:orgDate forKey:NSFileCreationDate];\n                        if( ![_fileManager setAttributes:attr ofItemAtPath:fullPath error:nil] )\n                        {\n                            // cann't set attributes \n                            NSLog(@\"Failed to set attributes\");\n                        }\n                        \n                    }\n                    orgDate = nil;\n                }\n                \n            }\n            \n            if (ret == UNZ_OK) {\n                ret = unzCloseCurrentFile( _unzFile );\n                if (ret != UNZ_OK) {\n                    [self OutputErrorMessage:@\"file was unzipped but failed crc check\"];\n                    success = NO;\n                }\n            }\n            \n            if (ret == UNZ_OK) {\n                ret = unzGoToNextFile( _unzFile );\n            }\n            \n            if (_progressBlock && _numFiles) {\n                index++;\n                int p = index*100/_numFiles;\n                progress = p;\n                _progressBlock(progress, index, _numFiles);\n            }\n        }\n\t} while (ret==UNZ_OK && ret!=UNZ_END_OF_LIST_OF_FILE);\n\treturn success;\n}\n\n/**\n * Close the zip file.\n *\n * @returns BOOL YES on success\n */\n\n-(BOOL) UnzipCloseFile\n{\n\tself.password = nil;\n\tif( _unzFile ) {\n\t\tint err = unzClose( _unzFile );\n        _unzFile = nil;\n        return err ==UNZ_OK;\n    }\n\treturn YES;\n}\n\n\n/**\n * Return a list of filenames that are in the zip archive. \n * No path information is available as this can be called before the zip is expanded.\n *\n * @returns NSArray list of filenames in the zip archive. \n */\n\n-(NSArray*) getZipFileContents     // list the contents of the zip archive. must be called after UnzipOpenFile\n{\n    int ret = unzGoToFirstFile( _unzFile );\n    NSMutableArray * allFilenames = [NSMutableArray arrayWithCapacity:40];\n    \n    if( ret!=UNZ_OK )\n    {\n        [self OutputErrorMessage:@\"Failed\"];\n    }\n    \n    const char* password = [_password cStringUsingEncoding:NSASCIIStringEncoding];\n    \n    do{\n        if( [_password length]==0 )\n            ret = unzOpenCurrentFile( _unzFile );\n        else\n            ret = unzOpenCurrentFilePassword( _unzFile, password );\n        if( ret!=UNZ_OK )\n        {\n            [self OutputErrorMessage:@\"Error occured\"];\n            break;\n        }\n        \n        // reading data and write to file\n        unz_file_info   fileInfo ={0};\n        ret = unzGetCurrentFileInfo(_unzFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0);\n        if( ret!=UNZ_OK )\n        {\n            [self OutputErrorMessage:@\"Error occurs while getting file info\"];\n            unzCloseCurrentFile( _unzFile );\n            break;\n        }\n        char* filename = (char*) malloc( fileInfo.size_filename +1 );\n        unzGetCurrentFileInfo(_unzFile, &fileInfo, filename, fileInfo.size_filename + 1, NULL, 0, NULL, 0);\n        filename[fileInfo.size_filename] = '\\0';\n        \n        // check if it contains directory\n        NSString * strPath = [NSString stringWithCString:filename encoding:NSASCIIStringEncoding];\n        free( filename );\n        if( [strPath rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@\"/\\\\\"]].location!=NSNotFound )\n        {// contains a path\n            strPath = [strPath stringByReplacingOccurrencesOfString:@\"\\\\\" withString:@\"/\"];\n        }\n        \n        // Copy name to array\n        [allFilenames addObject:strPath];\n        \n        unzCloseCurrentFile( _unzFile );\n        ret = unzGoToNextFile( _unzFile );\n    }  while( ret==UNZ_OK && UNZ_OK!=UNZ_END_OF_LIST_OF_FILE );\n    \n    // return an immutable array.\n    return [NSArray arrayWithArray:allFilenames];\n}\n\n\n#pragma mark wrapper for delegate\n\n/**\n * send the ErrorMessage: to the delegate if it responds to it.\n */\n-(void) OutputErrorMessage:(NSString*) msg\n{\n\tif( _delegate && [_delegate respondsToSelector:@selector(ErrorMessage:)] )\n\t\t[_delegate ErrorMessage:msg];\n}\n\n/**\n * send the OverWriteOperation: selector to the delegate if it responds to it,\n * returning the result, or YES by default.\n */\n\n-(BOOL) OverWrite:(NSString*) file\n{\n\tif( _delegate && [_delegate respondsToSelector:@selector(OverWriteOperation:)] )\n\t\treturn [_delegate OverWriteOperation:file];\n\treturn YES;\n}\n\n#pragma mark get NSDate object for 1980-01-01\n-(NSDate*) Date1980\n{\n\tNSDateComponents *comps = [[NSDateComponents alloc] init];\n\t[comps setDay:1];\n\t[comps setMonth:1];\n\t[comps setYear:1980];\n\tNSCalendar *gregorian = [[NSCalendar alloc]\n\t\t\t\t\t\t\t initWithCalendarIdentifier:NSCalendarIdentifierGregorian];\n\tNSDate *date = [gregorian dateFromComponents:comps];\n\t\n\treturn date;\n}\n\n\n@end\n\n\n@implementation NSFileManager(ZipArchive)\n\n- (NSDictionary *)_attributesOfItemAtPath:(NSString *)path followingSymLinks:(BOOL)followingSymLinks error:(NSError **)error\n{\n    // call file manager default action, which is to not follow symlinks\n    NSDictionary* results = [self attributesOfItemAtPath:path error:error];\n    if (followingSymLinks && results && (error ? *error == nil : YES)) {\n        if ([[results fileType] isEqualToString:NSFileTypeSymbolicLink]) {\n            // follow the symlink\n            NSString* realPath = [self destinationOfSymbolicLinkAtPath:path error:error];\n            if (realPath && (error ? *error == nil : YES)) {\n                return [self _attributesOfItemAtPath:realPath followingSymLinks:followingSymLinks error:error];\n            } else {\n                // failure to resolve symlink should be an error returning nil and error will already be set.\n                return nil;\n            }\n        }\n    }\n    return results;\n}\n\n@end\n\n"
  },
  {
    "path": "Loader/libs/minizip/crypt.h",
    "content": "/* crypt.h -- base code for crypt/uncrypt ZIPfile\n\n\n   Version 1.01e, February 12th, 2005\n\n   Copyright (C) 1998-2005 Gilles Vollant\n\n   This code is a modified version of crypting code in Infozip distribution\n\n   The encryption/decryption parts of this source code (as opposed to the\n   non-echoing password parts) were originally written in Europe.  The\n   whole source package can be freely distributed, including from the USA.\n   (Prior to January 2000, re-export from the US was a violation of US law.)\n\n   This encryption code is a direct transcription of the algorithm from\n   Roger Schlafly, described by Phil Katz in the file appnote.txt.  This\n   file (appnote.txt) is distributed with the PKZIP program (even in the\n   version without encryption capabilities).\n\n   If you don't need crypting in your application, just define symbols\n   NOCRYPT and NOUNCRYPT.\n\n   This code support the \"Traditional PKWARE Encryption\".\n\n   The new AES encryption added on Zip format by Winzip (see the page\n   http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong\n   Encryption is not supported.\n*/\n\n#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))\n\n/***********************************************************************\n * Return the next byte in the pseudo-random sequence\n */\nstatic int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)\n{\n    unsigned temp;  /* POTENTIAL BUG:  temp*(temp^1) may overflow in an\n                     * unpredictable manner on 16-bit systems; not a problem\n                     * with any known compiler so far, though */\n\n    temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;\n    return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);\n}\n\n/***********************************************************************\n * Update the encryption keys with the next byte of plain text\n */\nstatic int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c)\n{\n    (*(pkeys+0)) = CRC32((*(pkeys+0)), c);\n    (*(pkeys+1)) += (*(pkeys+0)) & 0xff;\n    (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;\n    {\n      register int keyshift = (int)((*(pkeys+1)) >> 24);\n      (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);\n    }\n    return c;\n}\n\n\n/***********************************************************************\n * Initialize the encryption keys and the random header according to\n * the given password.\n */\nstatic void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab)\n{\n    *(pkeys+0) = 305419896L;\n    *(pkeys+1) = 591751049L;\n    *(pkeys+2) = 878082192L;\n    while (*passwd != '\\0') {\n        update_keys(pkeys,pcrc_32_tab,(int)*passwd);\n        passwd++;\n    }\n}\n\n#define zdecode(pkeys,pcrc_32_tab,c) \\\n    (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))\n\n#define zencode(pkeys,pcrc_32_tab,c,t) \\\n    (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c))\n\n#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED\n\n#define RAND_HEAD_LEN  12\n   /* \"last resort\" source for second part of crypt seed pattern */\n#  ifndef ZCR_SEED2\n#    define ZCR_SEED2 3141592654UL     /* use PI as default pattern */\n#  endif\n\nstatic int crypthead(const char* passwd,      /* password string */\n                     unsigned char* buf,      /* where to write header */\n                     int bufSize,\n                     unsigned long* pkeys,\n                     const unsigned long* pcrc_32_tab,\n                     unsigned long crcForCrypting)\n{\n    int n;                       /* index in random header */\n    int t;                       /* temporary */\n    int c;                       /* random byte */\n    unsigned char header[RAND_HEAD_LEN-2]; /* random header */\n    static unsigned calls = 0;   /* ensure different random header each time */\n\n    if (bufSize<RAND_HEAD_LEN)\n      return 0;\n\n    /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the\n     * output of rand() to get less predictability, since rand() is\n     * often poorly implemented.\n     */\n    if (++calls == 1)\n    {\n        srand((unsigned)(time(NULL) ^ ZCR_SEED2));\n    }\n    init_keys(passwd, pkeys, pcrc_32_tab);\n    for (n = 0; n < RAND_HEAD_LEN-2; n++)\n    {\n        c = (rand() >> 7) & 0xff;\n        header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t);\n    }\n    /* Encrypt random header (last two bytes is high word of crc) */\n    init_keys(passwd, pkeys, pcrc_32_tab);\n    for (n = 0; n < RAND_HEAD_LEN-2; n++)\n    {\n        buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t);\n    }\n    buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t);\n    buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t);\n    return n;\n}\n\n#endif\n"
  },
  {
    "path": "Loader/libs/minizip/ioapi.c",
    "content": "/* ioapi.h -- IO base function header for compress/uncompress .zip\n   part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )\n\n         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )\n\n         Modifications for Zip64 support\n         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )\n\n         For more info read MiniZip_info.txt\n\n*/\n\n#if (defined(_WIN32))\n        #define _CRT_SECURE_NO_WARNINGS\n#endif\n\n#include \"ioapi.h\"\n\nvoidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode)\n{\n    if (pfilefunc->zfile_func64.zopen64_file != NULL)\n        return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode);\n    else\n    {\n        return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode);\n    }\n}\n\nlong call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin)\n{\n    if (pfilefunc->zfile_func64.zseek64_file != NULL)\n        return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin);\n    else\n    {\n        uLong offsetTruncated = (uLong)offset;\n        if (offsetTruncated != offset)\n            return -1;\n        else\n            return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin);\n    }\n}\n\nZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream)\n{\n    if (pfilefunc->zfile_func64.zseek64_file != NULL)\n        return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream);\n    else\n    {\n        uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream);\n        if ((tell_uLong) == ((uLong)-1))\n            return (ZPOS64_T)-1;\n        else\n            return tell_uLong;\n    }\n}\n\nvoid fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32)\n{\n    p_filefunc64_32->zfile_func64.zopen64_file = NULL;\n    p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file;\n    p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;\n    p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file;\n    p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file;\n    p_filefunc64_32->zfile_func64.ztell64_file = NULL;\n    p_filefunc64_32->zfile_func64.zseek64_file = NULL;\n    p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file;\n    p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;\n    p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque;\n    p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file;\n    p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file;\n}\n\n\n\nstatic voidpf  ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode));\nstatic uLong   ZCALLBACK fread_file_func OF((voidpf opaque, voidpf stream, void* buf, uLong size));\nstatic uLong   ZCALLBACK fwrite_file_func OF((voidpf opaque, voidpf stream, const void* buf,uLong size));\nstatic ZPOS64_T ZCALLBACK ftell64_file_func OF((voidpf opaque, voidpf stream));\nstatic long    ZCALLBACK fseek64_file_func OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));\nstatic int     ZCALLBACK fclose_file_func OF((voidpf opaque, voidpf stream));\nstatic int     ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream));\n\nstatic voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode)\n{\n    FILE* file = NULL;\n    const char* mode_fopen = NULL;\n    if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)\n        mode_fopen = \"rb\";\n    else\n    if (mode & ZLIB_FILEFUNC_MODE_EXISTING)\n        mode_fopen = \"r+b\";\n    else\n    if (mode & ZLIB_FILEFUNC_MODE_CREATE)\n        mode_fopen = \"wb\";\n\n    if ((filename!=NULL) && (mode_fopen != NULL))\n        file = fopen(filename, mode_fopen);\n    return file;\n}\n\nstatic voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode)\n{\n    FILE* file = NULL;\n    const char* mode_fopen = NULL;\n    if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)\n        mode_fopen = \"rb\";\n    else\n    if (mode & ZLIB_FILEFUNC_MODE_EXISTING)\n        mode_fopen = \"r+b\";\n    else\n    if (mode & ZLIB_FILEFUNC_MODE_CREATE)\n        mode_fopen = \"wb\";\n\n    if ((filename!=NULL) && (mode_fopen != NULL))\n        file = fopen((const char*)filename, mode_fopen);\n    return file;\n}\n\n\nstatic uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size)\n{\n    uLong ret;\n    ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);\n    return ret;\n}\n\nstatic uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size)\n{\n    uLong ret;\n    ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);\n    return ret;\n}\n\nstatic long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream)\n{\n    long ret;\n    ret = ftell((FILE *)stream);\n    return ret;\n}\n\n\nstatic ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream)\n{\n    ZPOS64_T ret;\n    ret = ftello((FILE *)stream);\n    return ret;\n}\n\nstatic long ZCALLBACK fseek_file_func (voidpf  opaque, voidpf stream, uLong offset, int origin)\n{\n    int fseek_origin=0;\n    long ret;\n    switch (origin)\n    {\n    case ZLIB_FILEFUNC_SEEK_CUR :\n        fseek_origin = SEEK_CUR;\n        break;\n    case ZLIB_FILEFUNC_SEEK_END :\n        fseek_origin = SEEK_END;\n        break;\n    case ZLIB_FILEFUNC_SEEK_SET :\n        fseek_origin = SEEK_SET;\n        break;\n    default: return -1;\n    }\n    ret = 0;\n    if (fseek((FILE *)stream, offset, fseek_origin) != 0)\n        ret = -1;\n    return ret;\n}\n\nstatic long ZCALLBACK fseek64_file_func (voidpf  opaque, voidpf stream, ZPOS64_T offset, int origin)\n{\n    int fseek_origin=0;\n    long ret;\n    switch (origin)\n    {\n    case ZLIB_FILEFUNC_SEEK_CUR :\n        fseek_origin = SEEK_CUR;\n        break;\n    case ZLIB_FILEFUNC_SEEK_END :\n        fseek_origin = SEEK_END;\n        break;\n    case ZLIB_FILEFUNC_SEEK_SET :\n        fseek_origin = SEEK_SET;\n        break;\n    default: return -1;\n    }\n    ret = 0;\n\n    if(fseeko((FILE *)stream, offset, fseek_origin) != 0)\n                        ret = -1;\n\n    return ret;\n}\n\n\nstatic int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream)\n{\n    int ret;\n    ret = fclose((FILE *)stream);\n    return ret;\n}\n\nstatic int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream)\n{\n    int ret;\n    ret = ferror((FILE *)stream);\n    return ret;\n}\n\nvoid fill_fopen_filefunc (pzlib_filefunc_def)\n  zlib_filefunc_def* pzlib_filefunc_def;\n{\n    pzlib_filefunc_def->zopen_file = fopen_file_func;\n    pzlib_filefunc_def->zread_file = fread_file_func;\n    pzlib_filefunc_def->zwrite_file = fwrite_file_func;\n    pzlib_filefunc_def->ztell_file = ftell_file_func;\n    pzlib_filefunc_def->zseek_file = fseek_file_func;\n    pzlib_filefunc_def->zclose_file = fclose_file_func;\n    pzlib_filefunc_def->zerror_file = ferror_file_func;\n    pzlib_filefunc_def->opaque = NULL;\n}\n\nvoid fill_fopen64_filefunc (zlib_filefunc64_def*  pzlib_filefunc_def)\n{\n    pzlib_filefunc_def->zopen64_file = fopen64_file_func;\n    pzlib_filefunc_def->zread_file = fread_file_func;\n    pzlib_filefunc_def->zwrite_file = fwrite_file_func;\n    pzlib_filefunc_def->ztell64_file = ftell64_file_func;\n    pzlib_filefunc_def->zseek64_file = fseek64_file_func;\n    pzlib_filefunc_def->zclose_file = fclose_file_func;\n    pzlib_filefunc_def->zerror_file = ferror_file_func;\n    pzlib_filefunc_def->opaque = NULL;\n}\n"
  },
  {
    "path": "Loader/libs/minizip/ioapi.h",
    "content": "/* ioapi.h -- IO base function header for compress/uncompress .zip\n   part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )\n\n         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )\n\n         Modifications for Zip64 support\n         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )\n\n         For more info read MiniZip_info.txt\n\n         Changes\n\n    Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this)\n    Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux.\n               More if/def section may be needed to support other platforms\n    Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows.\n                          (but you should use iowin32.c for windows instead)\n\n*/\n\n#ifndef _ZLIBIOAPI64_H\n#define _ZLIBIOAPI64_H\n\n#if (!defined(_WIN32)) && (!defined(WIN32))\n\n  // Linux needs this to support file operation on files larger then 4+GB\n  // But might need better if/def to select just the platforms that needs them.\n\n        #ifndef __USE_FILE_OFFSET64\n                #define __USE_FILE_OFFSET64\n        #endif\n        #ifndef __USE_LARGEFILE64\n                #define __USE_LARGEFILE64\n        #endif\n        #ifndef _LARGEFILE64_SOURCE\n                #define _LARGEFILE64_SOURCE\n        #endif\n        #ifndef _FILE_OFFSET_BIT\n                #define _FILE_OFFSET_BIT 64\n        #endif\n#endif\n\n#include <stdio.h>\n#include <stdlib.h>\n#include \"zlib.h\"\n\n#if defined(USE_FILE32API)\n#define fopen64 fopen\n#define ftello64 ftell\n#define fseeko64 fseek\n#else\n#ifdef _MSC_VER\n #define fopen64 fopen\n #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC)))\n  #define ftello64 _ftelli64\n  #define fseeko64 _fseeki64\n #else // old MSC\n  #define ftello64 ftell\n  #define fseeko64 fseek\n #endif\n#endif\n#endif\n\n/*\n#ifndef ZPOS64_T\n  #ifdef _WIN32\n                #define ZPOS64_T fpos_t\n  #else\n    #include <stdint.h>\n    #define ZPOS64_T uint64_t\n  #endif\n#endif\n*/\n\n#ifdef HAVE_MINIZIP64_CONF_H\n#include \"mz64conf.h\"\n#endif\n\n/* a type choosen by DEFINE */\n#ifdef HAVE_64BIT_INT_CUSTOM\ntypedef  64BIT_INT_CUSTOM_TYPE ZPOS64_T;\n#else\n#ifdef HAS_STDINT_H\n#include \"stdint.h\"\ntypedef uint64_t ZPOS64_T;\n#else\n\n\n#if defined(_MSC_VER) || defined(__BORLANDC__)\ntypedef unsigned __int64 ZPOS64_T;\n#else\ntypedef unsigned long long int ZPOS64_T;\n#endif\n#endif\n#endif\n\n\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n\n#define ZLIB_FILEFUNC_SEEK_CUR (1)\n#define ZLIB_FILEFUNC_SEEK_END (2)\n#define ZLIB_FILEFUNC_SEEK_SET (0)\n\n#define ZLIB_FILEFUNC_MODE_READ      (1)\n#define ZLIB_FILEFUNC_MODE_WRITE     (2)\n#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)\n\n#define ZLIB_FILEFUNC_MODE_EXISTING (4)\n#define ZLIB_FILEFUNC_MODE_CREATE   (8)\n\n\n#ifndef ZCALLBACK\n #if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)\n   #define ZCALLBACK CALLBACK\n #else\n   #define ZCALLBACK\n #endif\n#endif\n\n\n\n\ntypedef voidpf   (ZCALLBACK *open_file_func)      OF((voidpf opaque, const char* filename, int mode));\ntypedef uLong    (ZCALLBACK *read_file_func)      OF((voidpf opaque, voidpf stream, void* buf, uLong size));\ntypedef uLong    (ZCALLBACK *write_file_func)     OF((voidpf opaque, voidpf stream, const void* buf, uLong size));\ntypedef int      (ZCALLBACK *close_file_func)     OF((voidpf opaque, voidpf stream));\ntypedef int      (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));\n\ntypedef long     (ZCALLBACK *tell_file_func)      OF((voidpf opaque, voidpf stream));\ntypedef long     (ZCALLBACK *seek_file_func)      OF((voidpf opaque, voidpf stream, uLong offset, int origin));\n\n\n/* here is the \"old\" 32 bits structure structure */\ntypedef struct zlib_filefunc_def_s\n{\n    open_file_func      zopen_file;\n    read_file_func      zread_file;\n    write_file_func     zwrite_file;\n    tell_file_func      ztell_file;\n    seek_file_func      zseek_file;\n    close_file_func     zclose_file;\n    testerror_file_func zerror_file;\n    voidpf              opaque;\n} zlib_filefunc_def;\n\ntypedef ZPOS64_T (ZCALLBACK *tell64_file_func)    OF((voidpf opaque, voidpf stream));\ntypedef long     (ZCALLBACK *seek64_file_func)    OF((voidpf opaque, voidpf stream, ZPOS64_T offset, int origin));\ntypedef voidpf   (ZCALLBACK *open64_file_func)    OF((voidpf opaque, const void* filename, int mode));\n\ntypedef struct zlib_filefunc64_def_s\n{\n    open64_file_func    zopen64_file;\n    read_file_func      zread_file;\n    write_file_func     zwrite_file;\n    tell64_file_func    ztell64_file;\n    seek64_file_func    zseek64_file;\n    close_file_func     zclose_file;\n    testerror_file_func zerror_file;\n    voidpf              opaque;\n} zlib_filefunc64_def;\n\nvoid fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def));\nvoid fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));\n\n/* now internal definition, only for zip.c and unzip.h */\ntypedef struct zlib_filefunc64_32_def_s\n{\n    zlib_filefunc64_def zfile_func64;\n    open_file_func      zopen32_file;\n    tell_file_func      ztell32_file;\n    seek_file_func      zseek32_file;\n} zlib_filefunc64_32_def;\n\n\n#define ZREAD64(filefunc,filestream,buf,size)     ((*((filefunc).zfile_func64.zread_file))   ((filefunc).zfile_func64.opaque,filestream,buf,size))\n#define ZWRITE64(filefunc,filestream,buf,size)    ((*((filefunc).zfile_func64.zwrite_file))  ((filefunc).zfile_func64.opaque,filestream,buf,size))\n//#define ZTELL64(filefunc,filestream)            ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream))\n//#define ZSEEK64(filefunc,filestream,pos,mode)   ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode))\n#define ZCLOSE64(filefunc,filestream)             ((*((filefunc).zfile_func64.zclose_file))  ((filefunc).zfile_func64.opaque,filestream))\n#define ZERROR64(filefunc,filestream)             ((*((filefunc).zfile_func64.zerror_file))  ((filefunc).zfile_func64.opaque,filestream))\n\nvoidpf call_zopen64 OF((const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode));\nlong    call_zseek64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin));\nZPOS64_T call_ztell64 OF((const zlib_filefunc64_32_def* pfilefunc,voidpf filestream));\n\nvoid    fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32);\n\n#define ZOPEN64(filefunc,filename,mode)         (call_zopen64((&(filefunc)),(filename),(mode)))\n#define ZTELL64(filefunc,filestream)            (call_ztell64((&(filefunc)),(filestream)))\n#define ZSEEK64(filefunc,filestream,pos,mode)   (call_zseek64((&(filefunc)),(filestream),(pos),(mode)))\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "Loader/libs/minizip/mztools.c",
    "content": "/*\n  Additional tools for Minizip\n  Code: Xavier Roche '2004\n  License: Same as ZLIB (www.gzip.org)\n*/\n\n/* Code */\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include \"zlib.h\"\n#include \"unzip.h\"\n\n#define READ_8(adr)  ((unsigned char)*(adr))\n#define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) )\n#define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) )\n\n#define WRITE_8(buff, n) do { \\\n  *((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \\\n} while(0)\n#define WRITE_16(buff, n) do { \\\n  WRITE_8((unsigned char*)(buff), n); \\\n  WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \\\n} while(0)\n#define WRITE_32(buff, n) do { \\\n  WRITE_16((unsigned char*)(buff), (n) & 0xffff); \\\n  WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \\\n} while(0)\n\nextern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered)\nconst char* file;\nconst char* fileOut;\nconst char* fileOutTmp;\nuLong* nRecovered;\nuLong* bytesRecovered;\n{\n  int err = Z_OK;\n  FILE* fpZip = fopen(file, \"rb\");\n  FILE* fpOut = fopen(fileOut, \"wb\");\n  FILE* fpOutCD = fopen(fileOutTmp, \"wb\");\n  if (fpZip != NULL &&  fpOut != NULL) {\n    int entries = 0;\n    uLong totalBytes = 0;\n    char header[30];\n    char filename[256];\n    char extra[1024];\n    int offset = 0;\n    int offsetCD = 0;\n    while ( fread(header, 1, 30, fpZip) == 30 ) {\n      int currentOffset = offset;\n\n      /* File entry */\n      if (READ_32(header) == 0x04034b50) {\n        unsigned int version = READ_16(header + 4);\n        unsigned int gpflag = READ_16(header + 6);\n        unsigned int method = READ_16(header + 8);\n        unsigned int filetime = READ_16(header + 10);\n        unsigned int filedate = READ_16(header + 12);\n        unsigned int crc = READ_32(header + 14); /* crc */\n        unsigned int cpsize = READ_32(header + 18); /* compressed size */\n        unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */\n        unsigned int fnsize = READ_16(header + 26); /* file name length */\n        unsigned int extsize = READ_16(header + 28); /* extra field length */\n        filename[0] = extra[0] = '\\0';\n\n        /* Header */\n        if (fwrite(header, 1, 30, fpOut) == 30) {\n          offset += 30;\n        } else {\n          err = Z_ERRNO;\n          break;\n        }\n\n        /* Filename */\n        if (fnsize > 0) {\n          if (fread(filename, 1, fnsize, fpZip) == fnsize) {\n            if (fwrite(filename, 1, fnsize, fpOut) == fnsize) {\n              offset += fnsize;\n            } else {\n              err = Z_ERRNO;\n              break;\n            }\n          } else {\n            err = Z_ERRNO;\n            break;\n          }\n        } else {\n          err = Z_STREAM_ERROR;\n          break;\n        }\n\n        /* Extra field */\n        if (extsize > 0) {\n          if (fread(extra, 1, extsize, fpZip) == extsize) {\n            if (fwrite(extra, 1, extsize, fpOut) == extsize) {\n              offset += extsize;\n            } else {\n              err = Z_ERRNO;\n              break;\n            }\n          } else {\n            err = Z_ERRNO;\n            break;\n          }\n        }\n\n        /* Data */\n        {\n          int dataSize = cpsize;\n          if (dataSize == 0) {\n            dataSize = uncpsize;\n          }\n          if (dataSize > 0) {\n            char* data = malloc(dataSize);\n            if (data != NULL) {\n              if ((int)fread(data, 1, dataSize, fpZip) == dataSize) {\n                if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) {\n                  offset += dataSize;\n                  totalBytes += dataSize;\n                } else {\n                  err = Z_ERRNO;\n                }\n              } else {\n                err = Z_ERRNO;\n              }\n              free(data);\n              if (err != Z_OK) {\n                break;\n              }\n            } else {\n              err = Z_MEM_ERROR;\n              break;\n            }\n          }\n        }\n\n        /* Central directory entry */\n        {\n          char header[46];\n          char* comment = \"\";\n          int comsize = (int) strlen(comment);\n          WRITE_32(header, 0x02014b50);\n          WRITE_16(header + 4, version);\n          WRITE_16(header + 6, version);\n          WRITE_16(header + 8, gpflag);\n          WRITE_16(header + 10, method);\n          WRITE_16(header + 12, filetime);\n          WRITE_16(header + 14, filedate);\n          WRITE_32(header + 16, crc);\n          WRITE_32(header + 20, cpsize);\n          WRITE_32(header + 24, uncpsize);\n          WRITE_16(header + 28, fnsize);\n          WRITE_16(header + 30, extsize);\n          WRITE_16(header + 32, comsize);\n          WRITE_16(header + 34, 0);     /* disk # */\n          WRITE_16(header + 36, 0);     /* int attrb */\n          WRITE_32(header + 38, 0);     /* ext attrb */\n          WRITE_32(header + 42, currentOffset);\n          /* Header */\n          if (fwrite(header, 1, 46, fpOutCD) == 46) {\n            offsetCD += 46;\n\n            /* Filename */\n            if (fnsize > 0) {\n              if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) {\n                offsetCD += fnsize;\n              } else {\n                err = Z_ERRNO;\n                break;\n              }\n            } else {\n              err = Z_STREAM_ERROR;\n              break;\n            }\n\n            /* Extra field */\n            if (extsize > 0) {\n              if (fwrite(extra, 1, extsize, fpOutCD) == extsize) {\n                offsetCD += extsize;\n              } else {\n                err = Z_ERRNO;\n                break;\n              }\n            }\n\n            /* Comment field */\n            if (comsize > 0) {\n              if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) {\n                offsetCD += comsize;\n              } else {\n                err = Z_ERRNO;\n                break;\n              }\n            }\n\n\n          } else {\n            err = Z_ERRNO;\n            break;\n          }\n        }\n\n        /* Success */\n        entries++;\n\n      } else {\n        break;\n      }\n    }\n\n    /* Final central directory  */\n    {\n      int entriesZip = entries;\n      char header[22];\n      char* comment = \"\"; // \"ZIP File recovered by zlib/minizip/mztools\";\n      int comsize = (int) strlen(comment);\n      if (entriesZip > 0xffff) {\n        entriesZip = 0xffff;\n      }\n      WRITE_32(header, 0x06054b50);\n      WRITE_16(header + 4, 0);    /* disk # */\n      WRITE_16(header + 6, 0);    /* disk # */\n      WRITE_16(header + 8, entriesZip);   /* hack */\n      WRITE_16(header + 10, entriesZip);  /* hack */\n      WRITE_32(header + 12, offsetCD);    /* size of CD */\n      WRITE_32(header + 16, offset);      /* offset to CD */\n      WRITE_16(header + 20, comsize);     /* comment */\n\n      /* Header */\n      if (fwrite(header, 1, 22, fpOutCD) == 22) {\n\n        /* Comment field */\n        if (comsize > 0) {\n          if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) {\n            err = Z_ERRNO;\n          }\n        }\n\n      } else {\n        err = Z_ERRNO;\n      }\n    }\n\n    /* Final merge (file + central directory) */\n    fclose(fpOutCD);\n    if (err == Z_OK) {\n      fpOutCD = fopen(fileOutTmp, \"rb\");\n      if (fpOutCD != NULL) {\n        int nRead;\n        char buffer[8192];\n        while ( (nRead = (int)fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) {\n          if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) {\n            err = Z_ERRNO;\n            break;\n          }\n        }\n        fclose(fpOutCD);\n      }\n    }\n\n    /* Close */\n    fclose(fpZip);\n    fclose(fpOut);\n\n    /* Wipe temporary file */\n    (void)remove(fileOutTmp);\n\n    /* Number of recovered entries */\n    if (err == Z_OK) {\n      if (nRecovered != NULL) {\n        *nRecovered = entries;\n      }\n      if (bytesRecovered != NULL) {\n        *bytesRecovered = totalBytes;\n      }\n    }\n  } else {\n    err = Z_STREAM_ERROR;\n  }\n  return err;\n}\n"
  },
  {
    "path": "Loader/libs/minizip/mztools.h",
    "content": "/*\n  Additional tools for Minizip\n  Code: Xavier Roche '2004\n  License: Same as ZLIB (www.gzip.org)\n*/\n\n#ifndef _zip_tools_H\n#define _zip_tools_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifndef _ZLIB_H\n#include \"zlib.h\"\n#endif\n\n#include \"unzip.h\"\n\n/* Repair a ZIP file (missing central directory)\n   file: file to recover\n   fileOut: output file after recovery\n   fileOutTmp: temporary file name used for recovery\n*/\nextern int ZEXPORT unzRepair(const char* file,\n                             const char* fileOut,\n                             const char* fileOutTmp,\n                             uLong* nRecovered,\n                             uLong* bytesRecovered);\n\n#endif\n"
  },
  {
    "path": "Loader/libs/minizip/unzip.c",
    "content": "/* unzip.c -- IO for uncompress .zip files using zlib\n   Version 1.1, February 14h, 2010\n   part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )\n\n         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )\n\n         Modifications of Unzip for Zip64\n         Copyright (C) 2007-2008 Even Rouault\n\n         Modifications for Zip64 support on both zip and unzip\n         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )\n\n         For more info read MiniZip_info.txt\n\n\n  ------------------------------------------------------------------------------------\n  Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of\n  compatibility with older software. The following is from the original crypt.c.\n  Code woven in by Terry Thorsen 1/2003.\n\n  Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.\n\n  See the accompanying file LICENSE, version 2000-Apr-09 or later\n  (the contents of which are also included in zip.h) for terms of use.\n  If, for some reason, all these files are missing, the Info-ZIP license\n  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html\n\n        crypt.c (full version) by Info-ZIP.      Last revised:  [see crypt.h]\n\n  The encryption/decryption parts of this source code (as opposed to the\n  non-echoing password parts) were originally written in Europe.  The\n  whole source package can be freely distributed, including from the USA.\n  (Prior to January 2000, re-export from the US was a violation of US law.)\n\n        This encryption code is a direct transcription of the algorithm from\n  Roger Schlafly, described by Phil Katz in the file appnote.txt.  This\n  file (appnote.txt) is distributed with the PKZIP program (even in the\n  version without encryption capabilities).\n\n        ------------------------------------------------------------------------------------\n\n        Changes in unzip.c\n\n        2007-2008 - Even Rouault - Addition of cpl_unzGetCurrentFileZStreamPos\n  2007-2008 - Even Rouault - Decoration of symbol names unz* -> cpl_unz*\n  2007-2008 - Even Rouault - Remove old C style function prototypes\n  2007-2008 - Even Rouault - Add unzip support for ZIP64\n\n        Copyright (C) 2007-2008 Even Rouault\n\n\n        Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again).\n  Oct-2009 - Mathias Svensson - Fixed problem if uncompressed size was > 4G and compressed size was <4G\n                                should only read the compressed/uncompressed size from the Zip64 format if\n                                the size from normal header was 0xFFFFFFFF\n  Oct-2009 - Mathias Svensson - Applied some bug fixes from paches recived from Gilles Vollant\n        Oct-2009 - Mathias Svensson - Applied support to unzip files with compression mathod BZIP2 (bzip2 lib is required)\n                                Patch created by Daniel Borca\n\n  Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer\n\n  Copyright (C) 1998 - 2010 Gilles Vollant, Even Rouault, Mathias Svensson\n\n*/\n\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n// Matt Connolly 2013-09-12: this was defined in minizip 1.1.\n// @see http://www.winimage.com/zLibDll/minizip.html\n// Defining it defeats the ability to unzip password protected zip files, so this\n// is commented out so that existing tests pass.\n\n//#ifndef NOUNCRYPT\n//        #define NOUNCRYPT\n//#endif\n\n#include \"zlib.h\"\n#include \"unzip.h\"\n\n#ifdef STDC\n#  include <stddef.h>\n#  include <string.h>\n#  include <stdlib.h>\n#endif\n#ifdef NO_ERRNO_H\n    extern int errno;\n#else\n#   include <errno.h>\n#endif\n\n\n#ifndef local\n#  define local static\n#endif\n/* compile with -Dlocal if your debugger can't find static symbols */\n\n\n#ifndef CASESENSITIVITYDEFAULT_NO\n#  if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)\n#    define CASESENSITIVITYDEFAULT_NO\n#  endif\n#endif\n\n\n#ifndef UNZ_BUFSIZE\n#define UNZ_BUFSIZE (16384)\n#endif\n\n#ifndef UNZ_MAXFILENAMEINZIP\n#define UNZ_MAXFILENAMEINZIP (256)\n#endif\n\n#ifndef ALLOC\n# define ALLOC(size) (malloc(size))\n#endif\n#ifndef TRYFREE\n# define TRYFREE(p) {if (p) free(p);}\n#endif\n\n#define SIZECENTRALDIRITEM (0x2e)\n#define SIZEZIPLOCALHEADER (0x1e)\n\n\nconst char unz_copyright[] =\n   \" unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll\";\n\n/* unz_file_info_interntal contain internal info about a file in zipfile*/\ntypedef struct unz_file_info64_internal_s\n{\n    ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */\n} unz_file_info64_internal;\n\n\n/* file_in_zip_read_info_s contain internal information about a file in zipfile,\n    when reading and decompress it */\ntypedef struct\n{\n    char  *read_buffer;         /* internal buffer for compressed data */\n    z_stream stream;            /* zLib stream structure for inflate */\n\n#ifdef HAVE_BZIP2\n    bz_stream bstream;          /* bzLib stream structure for bziped */\n#endif\n\n    ZPOS64_T pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/\n    uLong stream_initialised;   /* flag set if stream structure is initialised*/\n\n    ZPOS64_T offset_local_extrafield;/* offset of the local extra field */\n    uInt  size_local_extrafield;/* size of the local extra field */\n    ZPOS64_T pos_local_extrafield;   /* position in the local extra field in read*/\n    ZPOS64_T total_out_64;\n\n    uLong crc32;                /* crc32 of all data uncompressed */\n    uLong crc32_wait;           /* crc32 we must obtain after decompress all */\n    ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */\n    ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/\n    zlib_filefunc64_32_def z_filefunc;\n    voidpf filestream;        /* io structore of the zipfile */\n    uLong compression_method;   /* compression method (0==store) */\n    ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/\n    int   raw;\n} file_in_zip64_read_info_s;\n\n\n/* unz64_s contain internal information about the zipfile\n*/\ntypedef struct\n{\n    zlib_filefunc64_32_def z_filefunc;\n    int is64bitOpenFunction;\n    voidpf filestream;        /* io structore of the zipfile */\n    unz_global_info64 gi;       /* public global information */\n    ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/\n    ZPOS64_T num_file;             /* number of the current file in the zipfile*/\n    ZPOS64_T pos_in_central_dir;   /* pos of the current file in the central dir*/\n    ZPOS64_T current_file_ok;      /* flag about the usability of the current file*/\n    ZPOS64_T central_pos;          /* position of the beginning of the central dir*/\n\n    ZPOS64_T size_central_dir;     /* size of the central directory  */\n    ZPOS64_T offset_central_dir;   /* offset of start of central directory with\n                                   respect to the starting disk number */\n\n    unz_file_info64 cur_file_info; /* public info about the current file in zip*/\n    unz_file_info64_internal cur_file_info_internal; /* private info about it*/\n    file_in_zip64_read_info_s* pfile_in_zip_read; /* structure about the current\n                                        file if we are decompressing it */\n    int encrypted;\n\n    int isZip64;\n\n#    ifndef NOUNCRYPT\n    unsigned long keys[3];     /* keys defining the pseudo-random sequence */\n    const unsigned long* pcrc_32_tab;\n#    endif\n} unz64_s;\n\n\n#ifndef NOUNCRYPT\n#include \"crypt.h\"\n#endif\n\n/* ===========================================================================\n     Read a byte from a gz_stream; update next_in and avail_in. Return EOF\n   for end of file.\n   IN assertion: the stream s has been sucessfully opened for reading.\n*/\n\n\nlocal int unz64local_getByte OF((\n    const zlib_filefunc64_32_def* pzlib_filefunc_def,\n    voidpf filestream,\n    int *pi));\n\nlocal int unz64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi)\n{\n    unsigned char c;\n    int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1);\n    if (err==1)\n    {\n        *pi = (int)c;\n        return UNZ_OK;\n    }\n    else\n    {\n        if (ZERROR64(*pzlib_filefunc_def,filestream))\n            return UNZ_ERRNO;\n        else\n            return UNZ_EOF;\n    }\n}\n\n\n/* ===========================================================================\n   Reads a long in LSB order from the given gz_stream. Sets\n*/\nlocal int unz64local_getShort OF((\n    const zlib_filefunc64_32_def* pzlib_filefunc_def,\n    voidpf filestream,\n    uLong *pX));\n\nlocal int unz64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def,\n                             voidpf filestream,\n                             uLong *pX)\n{\n    uLong x ;\n    int i = 0;\n    int err;\n\n    err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);\n    x = (uLong)i;\n\n    if (err==UNZ_OK)\n        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);\n    x |= ((uLong)i)<<8;\n\n    if (err==UNZ_OK)\n        *pX = x;\n    else\n        *pX = 0;\n    return err;\n}\n\nlocal int unz64local_getLong OF((\n    const zlib_filefunc64_32_def* pzlib_filefunc_def,\n    voidpf filestream,\n    uLong *pX));\n\nlocal int unz64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def,\n                            voidpf filestream,\n                            uLong *pX)\n{\n    uLong x ;\n    int i = 0;\n    int err;\n\n    err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);\n    x = (uLong)i;\n\n    if (err==UNZ_OK)\n        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);\n    x |= ((uLong)i)<<8;\n\n    if (err==UNZ_OK)\n        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);\n    x |= ((uLong)i)<<16;\n\n    if (err==UNZ_OK)\n        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);\n    x += ((uLong)i)<<24;\n\n    if (err==UNZ_OK)\n        *pX = x;\n    else\n        *pX = 0;\n    return err;\n}\n\nlocal int unz64local_getLong64 OF((\n    const zlib_filefunc64_32_def* pzlib_filefunc_def,\n    voidpf filestream,\n    ZPOS64_T *pX));\n\n\nlocal int unz64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def,\n                            voidpf filestream,\n                            ZPOS64_T *pX)\n{\n    ZPOS64_T x ;\n    int i = 0;\n    int err;\n\n    err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);\n    x = (ZPOS64_T)i;\n\n    if (err==UNZ_OK)\n        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);\n    x |= ((ZPOS64_T)i)<<8;\n\n    if (err==UNZ_OK)\n        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);\n    x |= ((ZPOS64_T)i)<<16;\n\n    if (err==UNZ_OK)\n        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);\n    x |= ((ZPOS64_T)i)<<24;\n\n    if (err==UNZ_OK)\n        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);\n    x |= ((ZPOS64_T)i)<<32;\n\n    if (err==UNZ_OK)\n        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);\n    x |= ((ZPOS64_T)i)<<40;\n\n    if (err==UNZ_OK)\n        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);\n    x |= ((ZPOS64_T)i)<<48;\n\n    if (err==UNZ_OK)\n        err = unz64local_getByte(pzlib_filefunc_def,filestream,&i);\n    x |= ((ZPOS64_T)i)<<56;\n\n    if (err==UNZ_OK)\n        *pX = x;\n    else\n        *pX = 0;\n    return err;\n}\n\n/* My own strcmpi / strcasecmp */\nlocal int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2)\n{\n    for (;;)\n    {\n        char c1=*(fileName1++);\n        char c2=*(fileName2++);\n        if ((c1>='a') && (c1<='z'))\n            c1 -= 0x20;\n        if ((c2>='a') && (c2<='z'))\n            c2 -= 0x20;\n        if (c1=='\\0')\n            return ((c2=='\\0') ? 0 : -1);\n        if (c2=='\\0')\n            return 1;\n        if (c1<c2)\n            return -1;\n        if (c1>c2)\n            return 1;\n    }\n}\n\n\n#ifdef  CASESENSITIVITYDEFAULT_NO\n#define CASESENSITIVITYDEFAULTVALUE 2\n#else\n#define CASESENSITIVITYDEFAULTVALUE 1\n#endif\n\n#ifndef STRCMPCASENOSENTIVEFUNCTION\n#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal\n#endif\n\n/*\n   Compare two filename (fileName1,fileName2).\n   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)\n   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi\n                                                                or strcasecmp)\n   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system\n        (like 1 on Unix, 2 on Windows)\n\n*/\nextern int ZEXPORT unzStringFileNameCompare (const char*  fileName1,\n                                                 const char*  fileName2,\n                                                 int iCaseSensitivity)\n\n{\n    if (iCaseSensitivity==0)\n        iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;\n\n    if (iCaseSensitivity==1)\n        return strcmp(fileName1,fileName2);\n\n    return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);\n}\n\n#ifndef BUFREADCOMMENT\n#define BUFREADCOMMENT (0x400)\n#endif\n\n/*\n  Locate the Central directory of a zipfile (at the end, just before\n    the global comment)\n*/\nlocal ZPOS64_T unz64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream));\nlocal ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)\n{\n    unsigned char* buf;\n    ZPOS64_T uSizeFile;\n    ZPOS64_T uBackRead;\n    ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */\n    ZPOS64_T uPosFound=0;\n\n    if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)\n        return 0;\n\n\n    uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);\n\n    if (uMaxBack>uSizeFile)\n        uMaxBack = uSizeFile;\n\n    buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);\n    if (buf==NULL)\n        return 0;\n\n    uBackRead = 4;\n    while (uBackRead<uMaxBack)\n    {\n        uLong uReadSize;\n        ZPOS64_T uReadPos ;\n        int i;\n        if (uBackRead+BUFREADCOMMENT>uMaxBack)\n            uBackRead = uMaxBack;\n        else\n            uBackRead+=BUFREADCOMMENT;\n        uReadPos = uSizeFile-uBackRead ;\n\n        uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?\n                     (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);\n        if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)\n            break;\n\n        if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)\n            break;\n\n        for (i=(int)uReadSize-3; (i--)>0;)\n            if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&\n                ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))\n            {\n                uPosFound = uReadPos+i;\n                break;\n            }\n\n        if (uPosFound!=0)\n            break;\n    }\n    TRYFREE(buf);\n    return uPosFound;\n}\n\n\n/*\n  Locate the Central directory 64 of a zipfile (at the end, just before\n    the global comment)\n*/\nlocal ZPOS64_T unz64local_SearchCentralDir64 OF((\n    const zlib_filefunc64_32_def* pzlib_filefunc_def,\n    voidpf filestream));\n\nlocal ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def,\n                                      voidpf filestream)\n{\n    unsigned char* buf;\n    ZPOS64_T uSizeFile;\n    ZPOS64_T uBackRead;\n    ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */\n    ZPOS64_T uPosFound=0;\n    uLong uL;\n                ZPOS64_T relativeOffset;\n\n    if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)\n        return 0;\n\n\n    uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);\n\n    if (uMaxBack>uSizeFile)\n        uMaxBack = uSizeFile;\n\n    buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);\n    if (buf==NULL)\n        return 0;\n\n    uBackRead = 4;\n    while (uBackRead<uMaxBack)\n    {\n        uLong uReadSize;\n        ZPOS64_T uReadPos;\n        int i;\n        if (uBackRead+BUFREADCOMMENT>uMaxBack)\n            uBackRead = uMaxBack;\n        else\n            uBackRead+=BUFREADCOMMENT;\n        uReadPos = uSizeFile-uBackRead ;\n\n        uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?\n                     (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);\n        if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)\n            break;\n\n        if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)\n            break;\n\n        for (i=(int)uReadSize-3; (i--)>0;)\n            if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&\n                ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07))\n            {\n                uPosFound = uReadPos+i;\n                break;\n            }\n\n        if (uPosFound!=0)\n            break;\n    }\n    TRYFREE(buf);\n    if (uPosFound == 0)\n        return 0;\n\n    /* Zip64 end of central directory locator */\n    if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0)\n        return 0;\n\n    /* the signature, already checked */\n    if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)\n        return 0;\n\n    /* number of the disk with the start of the zip64 end of  central directory */\n    if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)\n        return 0;\n    if (uL != 0)\n        return 0;\n\n    /* relative offset of the zip64 end of central directory record */\n    if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK)\n        return 0;\n\n    /* total number of disks */\n    if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)\n        return 0;\n    if (uL != 1)\n        return 0;\n\n    /* Goto end of central directory record */\n    if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0)\n        return 0;\n\n     /* the signature */\n    if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)\n        return 0;\n\n    if (uL != 0x06064b50)\n        return 0;\n\n    return relativeOffset;\n}\n\n/*\n  Open a Zip file. path contain the full pathname (by example,\n     on a Windows NT computer \"c:\\\\test\\\\zlib114.zip\" or on an Unix computer\n     \"zlib/zlib114.zip\".\n     If the zipfile cannot be opened (file doesn't exist or in not valid), the\n       return value is NULL.\n     Else, the return value is a unzFile Handle, usable with other function\n       of this unzip package.\n*/\nlocal unzFile unzOpenInternal (const void *path,\n                               zlib_filefunc64_32_def* pzlib_filefunc64_32_def,\n                               int is64bitOpenFunction)\n{\n    unz64_s us;\n    unz64_s *s;\n    ZPOS64_T central_pos;\n    uLong   uL;\n\n    uLong number_disk;          /* number of the current dist, used for\n                                   spaning ZIP, unsupported, always 0*/\n    uLong number_disk_with_CD;  /* number the the disk with central dir, used\n                                   for spaning ZIP, unsupported, always 0*/\n    ZPOS64_T number_entry_CD;      /* total number of entries in\n                                   the central dir\n                                   (same than number_entry on nospan) */\n\n    int err=UNZ_OK;\n\n    if (unz_copyright[0]!=' ')\n        return NULL;\n\n    us.z_filefunc.zseek32_file = NULL;\n    us.z_filefunc.ztell32_file = NULL;\n    if (pzlib_filefunc64_32_def==NULL)\n        fill_fopen64_filefunc(&us.z_filefunc.zfile_func64);\n    else\n        us.z_filefunc = *pzlib_filefunc64_32_def;\n    us.is64bitOpenFunction = is64bitOpenFunction;\n\n\n\n    us.filestream = ZOPEN64(us.z_filefunc,\n                                                 path,\n                                                 ZLIB_FILEFUNC_MODE_READ |\n                                                 ZLIB_FILEFUNC_MODE_EXISTING);\n    if (us.filestream==NULL)\n        return NULL;\n\n    central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream);\n    if (central_pos)\n    {\n        uLong uS;\n        ZPOS64_T uL64;\n\n        us.isZip64 = 1;\n\n        if (ZSEEK64(us.z_filefunc, us.filestream,\n                                      central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)\n        err=UNZ_ERRNO;\n\n        /* the signature, already checked */\n        if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)\n            err=UNZ_ERRNO;\n\n        /* size of zip64 end of central directory record */\n        if (unz64local_getLong64(&us.z_filefunc, us.filestream,&uL64)!=UNZ_OK)\n            err=UNZ_ERRNO;\n\n        /* version made by */\n        if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK)\n            err=UNZ_ERRNO;\n\n        /* version needed to extract */\n        if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK)\n            err=UNZ_ERRNO;\n\n        /* number of this disk */\n        if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)\n            err=UNZ_ERRNO;\n\n        /* number of the disk with the start of the central directory */\n        if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)\n            err=UNZ_ERRNO;\n\n        /* total number of entries in the central directory on this disk */\n        if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)\n            err=UNZ_ERRNO;\n\n        /* total number of entries in the central directory */\n        if (unz64local_getLong64(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)\n            err=UNZ_ERRNO;\n\n        if ((number_entry_CD!=us.gi.number_entry) ||\n            (number_disk_with_CD!=0) ||\n            (number_disk!=0))\n            err=UNZ_BADZIPFILE;\n\n        /* size of the central directory */\n        if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)\n            err=UNZ_ERRNO;\n\n        /* offset of start of central directory with respect to the\n          starting disk number */\n        if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)\n            err=UNZ_ERRNO;\n\n        us.gi.size_comment = 0;\n    }\n    else\n    {\n        central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream);\n        if (central_pos==0)\n            err=UNZ_ERRNO;\n\n        us.isZip64 = 0;\n\n        if (ZSEEK64(us.z_filefunc, us.filestream,\n                                        central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)\n            err=UNZ_ERRNO;\n\n        /* the signature, already checked */\n        if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)\n            err=UNZ_ERRNO;\n\n        /* number of this disk */\n        if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)\n            err=UNZ_ERRNO;\n\n        /* number of the disk with the start of the central directory */\n        if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)\n            err=UNZ_ERRNO;\n\n        /* total number of entries in the central dir on this disk */\n        if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)\n            err=UNZ_ERRNO;\n        us.gi.number_entry = uL;\n\n        /* total number of entries in the central dir */\n        if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)\n            err=UNZ_ERRNO;\n        number_entry_CD = uL;\n\n        if ((number_entry_CD!=us.gi.number_entry) ||\n            (number_disk_with_CD!=0) ||\n            (number_disk!=0))\n            err=UNZ_BADZIPFILE;\n\n        /* size of the central directory */\n        if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)\n            err=UNZ_ERRNO;\n        us.size_central_dir = uL;\n\n        /* offset of start of central directory with respect to the\n            starting disk number */\n        if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)\n            err=UNZ_ERRNO;\n        us.offset_central_dir = uL;\n\n        /* zipfile comment length */\n        if (unz64local_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)\n            err=UNZ_ERRNO;\n    }\n\n    if ((central_pos<us.offset_central_dir+us.size_central_dir) &&\n        (err==UNZ_OK))\n        err=UNZ_BADZIPFILE;\n\n    if (err!=UNZ_OK)\n    {\n        ZCLOSE64(us.z_filefunc, us.filestream);\n        return NULL;\n    }\n\n    us.byte_before_the_zipfile = central_pos -\n                            (us.offset_central_dir+us.size_central_dir);\n    us.central_pos = central_pos;\n    us.pfile_in_zip_read = NULL;\n    us.encrypted = 0;\n\n\n    s=(unz64_s*)ALLOC(sizeof(unz64_s));\n    if( s != NULL)\n    {\n        *s=us;\n        unzGoToFirstFile((unzFile)s);\n    }\n    return (unzFile)s;\n}\n\n\nextern unzFile ZEXPORT unzOpen2 (const char *path,\n                                        zlib_filefunc_def* pzlib_filefunc32_def)\n{\n    if (pzlib_filefunc32_def != NULL)\n    {\n        zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;\n        fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def);\n        return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 0);\n    }\n    else\n        return unzOpenInternal(path, NULL, 0);\n}\n\nextern unzFile ZEXPORT unzOpen2_64 (const void *path,\n                                     zlib_filefunc64_def* pzlib_filefunc_def)\n{\n    if (pzlib_filefunc_def != NULL)\n    {\n        zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;\n        zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def;\n        zlib_filefunc64_32_def_fill.ztell32_file = NULL;\n        zlib_filefunc64_32_def_fill.zseek32_file = NULL;\n        return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 1);\n    }\n    else\n        return unzOpenInternal(path, NULL, 1);\n}\n\nextern unzFile ZEXPORT unzOpen (const char *path)\n{\n    return unzOpenInternal(path, NULL, 0);\n}\n\nextern unzFile ZEXPORT unzOpen64 (const void *path)\n{\n    return unzOpenInternal(path, NULL, 1);\n}\n\n/*\n  Close a ZipFile opened with unzipOpen.\n  If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),\n    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.\n  return UNZ_OK if there is no problem. */\nextern int ZEXPORT unzClose (unzFile file)\n{\n    unz64_s* s;\n    if (file==NULL)\n        return UNZ_PARAMERROR;\n    s=(unz64_s*)file;\n\n    if (s->pfile_in_zip_read!=NULL)\n        unzCloseCurrentFile(file);\n\n    ZCLOSE64(s->z_filefunc, s->filestream);\n    TRYFREE(s);\n    return UNZ_OK;\n}\n\n\n/*\n  Write info about the ZipFile in the *pglobal_info structure.\n  No preparation of the structure is needed\n  return UNZ_OK if there is no problem. */\nextern int ZEXPORT unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_info)\n{\n    unz64_s* s;\n    if (file==NULL)\n        return UNZ_PARAMERROR;\n    s=(unz64_s*)file;\n    *pglobal_info=s->gi;\n    return UNZ_OK;\n}\n\nextern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info32)\n{\n    unz64_s* s;\n    if (file==NULL)\n        return UNZ_PARAMERROR;\n    s=(unz64_s*)file;\n    /* to do : check if number_entry is not truncated */\n    pglobal_info32->number_entry = (uLong)s->gi.number_entry;\n    pglobal_info32->size_comment = s->gi.size_comment;\n    return UNZ_OK;\n}\n/*\n   Translate date/time from Dos format to tm_unz (readable more easilty)\n*/\nlocal void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm)\n{\n    ZPOS64_T uDate;\n    uDate = (ZPOS64_T)(ulDosDate>>16);\n    ptm->tm_mday = (uInt)(uDate&0x1f) ;\n    ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;\n    ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;\n\n    ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);\n    ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;\n    ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;\n}\n\n/*\n  Get Info about the current file in the zipfile, with internal only info\n*/\nlocal int unz64local_GetCurrentFileInfoInternal OF((unzFile file,\n                                                  unz_file_info64 *pfile_info,\n                                                  unz_file_info64_internal\n                                                  *pfile_info_internal,\n                                                  char *szFileName,\n                                                  uLong fileNameBufferSize,\n                                                  void *extraField,\n                                                  uLong extraFieldBufferSize,\n                                                  char *szComment,\n                                                  uLong commentBufferSize));\n\nlocal int unz64local_GetCurrentFileInfoInternal (unzFile file,\n                                                  unz_file_info64 *pfile_info,\n                                                  unz_file_info64_internal\n                                                  *pfile_info_internal,\n                                                  char *szFileName,\n                                                  uLong fileNameBufferSize,\n                                                  void *extraField,\n                                                  uLong extraFieldBufferSize,\n                                                  char *szComment,\n                                                  uLong commentBufferSize)\n{\n    unz64_s* s;\n    unz_file_info64 file_info;\n    unz_file_info64_internal file_info_internal;\n    int err=UNZ_OK;\n    uLong uMagic;\n    long lSeek=0;\n    uLong uL;\n\n    if (file==NULL)\n        return UNZ_PARAMERROR;\n    s=(unz64_s*)file;\n    if (ZSEEK64(s->z_filefunc, s->filestream,\n              s->pos_in_central_dir+s->byte_before_the_zipfile,\n              ZLIB_FILEFUNC_SEEK_SET)!=0)\n        err=UNZ_ERRNO;\n\n\n    /* we check the magic */\n    if (err==UNZ_OK)\n    {\n        if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)\n            err=UNZ_ERRNO;\n        else if (uMagic!=0x02014b50)\n            err=UNZ_BADZIPFILE;\n    }\n\n    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)\n        err=UNZ_ERRNO;\n\n    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)\n        err=UNZ_ERRNO;\n\n    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)\n        err=UNZ_ERRNO;\n\n    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)\n        err=UNZ_ERRNO;\n\n    if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)\n        err=UNZ_ERRNO;\n\n    unz64local_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);\n\n    if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)\n        err=UNZ_ERRNO;\n\n    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)\n        err=UNZ_ERRNO;\n    file_info.compressed_size = uL;\n\n    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)\n        err=UNZ_ERRNO;\n    file_info.uncompressed_size = uL;\n\n    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)\n        err=UNZ_ERRNO;\n\n    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)\n        err=UNZ_ERRNO;\n\n    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)\n        err=UNZ_ERRNO;\n\n    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)\n        err=UNZ_ERRNO;\n\n    if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)\n        err=UNZ_ERRNO;\n\n    if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)\n        err=UNZ_ERRNO;\n\n                // relative offset of local header\n    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)\n        err=UNZ_ERRNO;\n    file_info_internal.offset_curfile = uL;\n\n    lSeek+=file_info.size_filename;\n    if ((err==UNZ_OK) && (szFileName!=NULL))\n    {\n        uLong uSizeRead ;\n        if (file_info.size_filename<fileNameBufferSize)\n        {\n            *(szFileName+file_info.size_filename)='\\0';\n            uSizeRead = file_info.size_filename;\n        }\n        else\n            uSizeRead = fileNameBufferSize;\n\n        if ((file_info.size_filename>0) && (fileNameBufferSize>0))\n            if (ZREAD64(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)\n                err=UNZ_ERRNO;\n        lSeek -= uSizeRead;\n    }\n\n    // Read extrafield\n    if ((err==UNZ_OK) && (extraField!=NULL))\n    {\n        ZPOS64_T uSizeRead ;\n        if (file_info.size_file_extra<extraFieldBufferSize)\n            uSizeRead = file_info.size_file_extra;\n        else\n            uSizeRead = extraFieldBufferSize;\n\n        if (lSeek!=0)\n        {\n            if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)\n                lSeek=0;\n            else\n                err=UNZ_ERRNO;\n        }\n\n        if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))\n            if (ZREAD64(s->z_filefunc, s->filestream,extraField,(uLong)uSizeRead)!=uSizeRead)\n                err=UNZ_ERRNO;\n\n        lSeek += file_info.size_file_extra - (uLong)uSizeRead;\n    }\n    else\n        lSeek += file_info.size_file_extra;\n\n\n    if ((err==UNZ_OK) && (file_info.size_file_extra != 0))\n    {\n                                uLong acc = 0;\n\n        // since lSeek now points to after the extra field we need to move back\n        lSeek -= file_info.size_file_extra;\n\n        if (lSeek!=0)\n        {\n            if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)\n                lSeek=0;\n            else\n                err=UNZ_ERRNO;\n        }\n\n        while(acc < file_info.size_file_extra)\n        {\n            uLong headerId;\n                                                uLong dataSize;\n\n            if (unz64local_getShort(&s->z_filefunc, s->filestream,&headerId) != UNZ_OK)\n                err=UNZ_ERRNO;\n\n            if (unz64local_getShort(&s->z_filefunc, s->filestream,&dataSize) != UNZ_OK)\n                err=UNZ_ERRNO;\n\n            /* ZIP64 extra fields */\n            if (headerId == 0x0001)\n            {\n                                                        uLong uL;\n\n                                                                if(file_info.uncompressed_size == (ZPOS64_T)(unsigned long)-1)\n                                                                {\n                                                                        if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)\n                                                                                        err=UNZ_ERRNO;\n                                                                }\n\n                                                                if(file_info.compressed_size == (ZPOS64_T)(unsigned long)-1)\n                                                                {\n                                                                        if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)\n                                                                                  err=UNZ_ERRNO;\n                                                                }\n\n                                                                if(file_info_internal.offset_curfile == (ZPOS64_T)(unsigned long)-1)\n                                                                {\n                                                                        /* Relative Header offset */\n                                                                        if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)\n                                                                                err=UNZ_ERRNO;\n                                                                }\n\n                                                                if(file_info.disk_num_start == (unsigned long)-1)\n                                                                {\n                                                                        /* Disk Start Number */\n                                                                        if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)\n                                                                                err=UNZ_ERRNO;\n                                                                }\n\n            }\n            else\n            {\n                if (ZSEEK64(s->z_filefunc, s->filestream,dataSize,ZLIB_FILEFUNC_SEEK_CUR)!=0)\n                    err=UNZ_ERRNO;\n            }\n\n            acc += 2 + 2 + dataSize;\n        }\n    }\n\n    if ((err==UNZ_OK) && (szComment!=NULL))\n    {\n        uLong uSizeRead ;\n        if (file_info.size_file_comment<commentBufferSize)\n        {\n            *(szComment+file_info.size_file_comment)='\\0';\n            uSizeRead = file_info.size_file_comment;\n        }\n        else\n            uSizeRead = commentBufferSize;\n\n        if (lSeek!=0)\n        {\n            if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)\n                lSeek=0;\n            else\n                err=UNZ_ERRNO;\n        }\n\n        if ((file_info.size_file_comment>0) && (commentBufferSize>0))\n            if (ZREAD64(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)\n                err=UNZ_ERRNO;\n        lSeek+=file_info.size_file_comment - uSizeRead;\n    }\n    else\n        lSeek+=file_info.size_file_comment;\n\n\n    if ((err==UNZ_OK) && (pfile_info!=NULL))\n        *pfile_info=file_info;\n\n    if ((err==UNZ_OK) && (pfile_info_internal!=NULL))\n        *pfile_info_internal=file_info_internal;\n\n    return err;\n}\n\n\n\n/*\n  Write info about the ZipFile in the *pglobal_info structure.\n  No preparation of the structure is needed\n  return UNZ_OK if there is no problem.\n*/\nextern int ZEXPORT unzGetCurrentFileInfo64 (unzFile file,\n                                          unz_file_info64 * pfile_info,\n                                          char * szFileName, uLong fileNameBufferSize,\n                                          void *extraField, uLong extraFieldBufferSize,\n                                          char* szComment,  uLong commentBufferSize)\n{\n    return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL,\n                                                szFileName,fileNameBufferSize,\n                                                extraField,extraFieldBufferSize,\n                                                szComment,commentBufferSize);\n}\n\nextern int ZEXPORT unzGetCurrentFileInfo (unzFile file,\n                                          unz_file_info * pfile_info,\n                                          char * szFileName, uLong fileNameBufferSize,\n                                          void *extraField, uLong extraFieldBufferSize,\n                                          char* szComment,  uLong commentBufferSize)\n{\n    int err;\n    unz_file_info64 file_info64;\n    err = unz64local_GetCurrentFileInfoInternal(file,&file_info64,NULL,\n                                                szFileName,fileNameBufferSize,\n                                                extraField,extraFieldBufferSize,\n                                                szComment,commentBufferSize);\n    if (err==UNZ_OK)\n    {\n        pfile_info->version = file_info64.version;\n        pfile_info->version_needed = file_info64.version_needed;\n        pfile_info->flag = file_info64.flag;\n        pfile_info->compression_method = file_info64.compression_method;\n        pfile_info->dosDate = file_info64.dosDate;\n        pfile_info->crc = file_info64.crc;\n\n        pfile_info->size_filename = file_info64.size_filename;\n        pfile_info->size_file_extra = file_info64.size_file_extra;\n        pfile_info->size_file_comment = file_info64.size_file_comment;\n\n        pfile_info->disk_num_start = file_info64.disk_num_start;\n        pfile_info->internal_fa = file_info64.internal_fa;\n        pfile_info->external_fa = file_info64.external_fa;\n\n        pfile_info->tmu_date = file_info64.tmu_date,\n\n\n        pfile_info->compressed_size = (uLong)file_info64.compressed_size;\n        pfile_info->uncompressed_size = (uLong)file_info64.uncompressed_size;\n\n    }\n    return err;\n}\n/*\n  Set the current file of the zipfile to the first file.\n  return UNZ_OK if there is no problem\n*/\nextern int ZEXPORT unzGoToFirstFile (unzFile file)\n{\n    int err=UNZ_OK;\n    unz64_s* s;\n    if (file==NULL)\n        return UNZ_PARAMERROR;\n    s=(unz64_s*)file;\n    s->pos_in_central_dir=s->offset_central_dir;\n    s->num_file=0;\n    err=unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,\n                                             &s->cur_file_info_internal,\n                                             NULL,0,NULL,0,NULL,0);\n    s->current_file_ok = (err == UNZ_OK);\n    return err;\n}\n\n/*\n  Set the current file of the zipfile to the next file.\n  return UNZ_OK if there is no problem\n  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.\n*/\nextern int ZEXPORT unzGoToNextFile (unzFile  file)\n{\n    unz64_s* s;\n    int err;\n\n    if (file==NULL)\n        return UNZ_PARAMERROR;\n    s=(unz64_s*)file;\n    if (!s->current_file_ok)\n        return UNZ_END_OF_LIST_OF_FILE;\n    if (s->gi.number_entry != 0xffff)    /* 2^16 files overflow hack */\n      if (s->num_file+1==s->gi.number_entry)\n        return UNZ_END_OF_LIST_OF_FILE;\n\n    s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +\n            s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;\n    s->num_file++;\n    err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,\n                                               &s->cur_file_info_internal,\n                                               NULL,0,NULL,0,NULL,0);\n    s->current_file_ok = (err == UNZ_OK);\n    return err;\n}\n\n\n/*\n  Try locate the file szFileName in the zipfile.\n  For the iCaseSensitivity signification, see unzipStringFileNameCompare\n\n  return value :\n  UNZ_OK if the file is found. It becomes the current file.\n  UNZ_END_OF_LIST_OF_FILE if the file is not found\n*/\nextern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity)\n{\n    unz64_s* s;\n    int err;\n\n    /* We remember the 'current' position in the file so that we can jump\n     * back there if we fail.\n     */\n    unz_file_info64 cur_file_infoSaved;\n    unz_file_info64_internal cur_file_info_internalSaved;\n    ZPOS64_T num_fileSaved;\n    ZPOS64_T pos_in_central_dirSaved;\n\n\n    if (file==NULL)\n        return UNZ_PARAMERROR;\n\n    if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)\n        return UNZ_PARAMERROR;\n\n    s=(unz64_s*)file;\n    if (!s->current_file_ok)\n        return UNZ_END_OF_LIST_OF_FILE;\n\n    /* Save the current state */\n    num_fileSaved = s->num_file;\n    pos_in_central_dirSaved = s->pos_in_central_dir;\n    cur_file_infoSaved = s->cur_file_info;\n    cur_file_info_internalSaved = s->cur_file_info_internal;\n\n    err = unzGoToFirstFile(file);\n\n    while (err == UNZ_OK)\n    {\n        char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];\n        err = unzGetCurrentFileInfo64(file,NULL,\n                                    szCurrentFileName,sizeof(szCurrentFileName)-1,\n                                    NULL,0,NULL,0);\n        if (err == UNZ_OK)\n        {\n            if (unzStringFileNameCompare(szCurrentFileName,\n                                            szFileName,iCaseSensitivity)==0)\n                return UNZ_OK;\n            err = unzGoToNextFile(file);\n        }\n    }\n\n    /* We failed, so restore the state of the 'current file' to where we\n     * were.\n     */\n    s->num_file = num_fileSaved ;\n    s->pos_in_central_dir = pos_in_central_dirSaved ;\n    s->cur_file_info = cur_file_infoSaved;\n    s->cur_file_info_internal = cur_file_info_internalSaved;\n    return err;\n}\n\n\n/*\n///////////////////////////////////////////\n// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)\n// I need random access\n//\n// Further optimization could be realized by adding an ability\n// to cache the directory in memory. The goal being a single\n// comprehensive file read to put the file I need in a memory.\n*/\n\n/*\ntypedef struct unz_file_pos_s\n{\n    ZPOS64_T pos_in_zip_directory;   // offset in file\n    ZPOS64_T num_of_file;            // # of file\n} unz_file_pos;\n*/\n\nextern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos*  file_pos)\n{\n    unz64_s* s;\n\n    if (file==NULL || file_pos==NULL)\n        return UNZ_PARAMERROR;\n    s=(unz64_s*)file;\n    if (!s->current_file_ok)\n        return UNZ_END_OF_LIST_OF_FILE;\n\n    file_pos->pos_in_zip_directory  = s->pos_in_central_dir;\n    file_pos->num_of_file           = s->num_file;\n\n    return UNZ_OK;\n}\n\nextern int ZEXPORT unzGetFilePos(\n    unzFile file,\n    unz_file_pos* file_pos)\n{\n    unz64_file_pos file_pos64;\n    int err = unzGetFilePos64(file,&file_pos64);\n    if (err==UNZ_OK)\n    {\n        file_pos->pos_in_zip_directory = (uLong)file_pos64.pos_in_zip_directory;\n        file_pos->num_of_file = (uLong)file_pos64.num_of_file;\n    }\n    return err;\n}\n\nextern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos)\n{\n    unz64_s* s;\n    int err;\n\n    if (file==NULL || file_pos==NULL)\n        return UNZ_PARAMERROR;\n    s=(unz64_s*)file;\n\n    /* jump to the right spot */\n    s->pos_in_central_dir = file_pos->pos_in_zip_directory;\n    s->num_file           = file_pos->num_of_file;\n\n    /* set the current file */\n    err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,\n                                               &s->cur_file_info_internal,\n                                               NULL,0,NULL,0,NULL,0);\n    /* return results */\n    s->current_file_ok = (err == UNZ_OK);\n    return err;\n}\n\nextern int ZEXPORT unzGoToFilePos(\n    unzFile file,\n    unz_file_pos* file_pos)\n{\n    unz64_file_pos file_pos64;\n    if (file_pos == NULL)\n        return UNZ_PARAMERROR;\n\n    file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory;\n    file_pos64.num_of_file = file_pos->num_of_file;\n    return unzGoToFilePos64(file,&file_pos64);\n}\n\n/*\n// Unzip Helper Functions - should be here?\n///////////////////////////////////////////\n*/\n\n/*\n  Read the local header of the current zipfile\n  Check the coherency of the local header and info in the end of central\n        directory about this file\n  store in *piSizeVar the size of extra info in local header\n        (filename and size of extra field data)\n*/\nlocal int unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* piSizeVar,\n                                                    ZPOS64_T * poffset_local_extrafield,\n                                                    uInt  * psize_local_extrafield)\n{\n    uLong uMagic,uData,uFlags;\n    uLong size_filename;\n    uLong size_extra_field;\n    int err=UNZ_OK;\n\n    *piSizeVar = 0;\n    *poffset_local_extrafield = 0;\n    *psize_local_extrafield = 0;\n\n    if (ZSEEK64(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +\n                                s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)\n        return UNZ_ERRNO;\n\n\n    if (err==UNZ_OK)\n    {\n        if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)\n            err=UNZ_ERRNO;\n        else if (uMagic!=0x04034b50)\n            err=UNZ_BADZIPFILE;\n    }\n\n    if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)\n        err=UNZ_ERRNO;\n/*\n    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))\n        err=UNZ_BADZIPFILE;\n*/\n    if (unz64local_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)\n        err=UNZ_ERRNO;\n\n    if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)\n        err=UNZ_ERRNO;\n    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))\n        err=UNZ_BADZIPFILE;\n\n    if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&\n/* #ifdef HAVE_BZIP2 */\n                         (s->cur_file_info.compression_method!=Z_BZIP2ED) &&\n/* #endif */\n                         (s->cur_file_info.compression_method!=Z_DEFLATED))\n        err=UNZ_BADZIPFILE;\n\n    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */\n        err=UNZ_ERRNO;\n\n    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */\n        err=UNZ_ERRNO;\n    else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && ((uFlags & 8)==0))\n        err=UNZ_BADZIPFILE;\n\n    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */\n        err=UNZ_ERRNO;\n    else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && ((uFlags & 8)==0))\n        err=UNZ_BADZIPFILE;\n\n    if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */\n        err=UNZ_ERRNO;\n    else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && ((uFlags & 8)==0))\n        err=UNZ_BADZIPFILE;\n\n    if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)\n        err=UNZ_ERRNO;\n    else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))\n        err=UNZ_BADZIPFILE;\n\n    *piSizeVar += (uInt)size_filename;\n\n    if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)\n        err=UNZ_ERRNO;\n    *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +\n                                    SIZEZIPLOCALHEADER + size_filename;\n    *psize_local_extrafield = (uInt)size_extra_field;\n\n    *piSizeVar += (uInt)size_extra_field;\n\n    return err;\n}\n\n/*\n  Open for reading data the current file in the zipfile.\n  If there is no error and the file is opened, the return value is UNZ_OK.\n*/\nextern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method,\n                                            int* level, int raw, const char* password)\n{\n    int err=UNZ_OK;\n    uInt iSizeVar;\n    unz64_s* s;\n    file_in_zip64_read_info_s* pfile_in_zip_read_info;\n    ZPOS64_T offset_local_extrafield;  /* offset of the local extra field */\n    uInt  size_local_extrafield;    /* size of the local extra field */\n#    ifndef NOUNCRYPT\n    char source[12];\n#    else\n    if (password != NULL)\n        return UNZ_PARAMERROR;\n#    endif\n\n    if (file==NULL)\n        return UNZ_PARAMERROR;\n    s=(unz64_s*)file;\n    if (!s->current_file_ok)\n        return UNZ_PARAMERROR;\n\n    if (s->pfile_in_zip_read != NULL)\n        unzCloseCurrentFile(file);\n\n    if (unz64local_CheckCurrentFileCoherencyHeader(s,&iSizeVar, &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)\n        return UNZ_BADZIPFILE;\n\n    pfile_in_zip_read_info = (file_in_zip64_read_info_s*)ALLOC(sizeof(file_in_zip64_read_info_s));\n    if (pfile_in_zip_read_info==NULL)\n        return UNZ_INTERNALERROR;\n\n    pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);\n    pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;\n    pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;\n    pfile_in_zip_read_info->pos_local_extrafield=0;\n    pfile_in_zip_read_info->raw=raw;\n\n    if (pfile_in_zip_read_info->read_buffer==NULL)\n    {\n        TRYFREE(pfile_in_zip_read_info);\n        return UNZ_INTERNALERROR;\n    }\n\n    pfile_in_zip_read_info->stream_initialised=0;\n\n    if (method!=NULL)\n        *method = (int)s->cur_file_info.compression_method;\n\n    if (level!=NULL)\n    {\n        *level = 6;\n        switch (s->cur_file_info.flag & 0x06)\n        {\n          case 6 : *level = 1; break;\n          case 4 : *level = 2; break;\n          case 2 : *level = 9; break;\n        }\n    }\n\n    if ((s->cur_file_info.compression_method!=0) &&\n/* #ifdef HAVE_BZIP2 */\n        (s->cur_file_info.compression_method!=Z_BZIP2ED) &&\n/* #endif */\n        (s->cur_file_info.compression_method!=Z_DEFLATED))\n\n        err=UNZ_BADZIPFILE;\n\n    pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;\n    pfile_in_zip_read_info->crc32=0;\n    pfile_in_zip_read_info->total_out_64=0;\n    pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method;\n    pfile_in_zip_read_info->filestream=s->filestream;\n    pfile_in_zip_read_info->z_filefunc=s->z_filefunc;\n    pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;\n\n    pfile_in_zip_read_info->stream.total_out = 0;\n\n    if ((s->cur_file_info.compression_method==Z_BZIP2ED) && (!raw))\n    {\n#ifdef HAVE_BZIP2\n      pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0;\n      pfile_in_zip_read_info->bstream.bzfree = (free_func)0;\n      pfile_in_zip_read_info->bstream.opaque = (voidpf)0;\n      pfile_in_zip_read_info->bstream.state = (voidpf)0;\n\n      pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;\n      pfile_in_zip_read_info->stream.zfree = (free_func)0;\n      pfile_in_zip_read_info->stream.opaque = (voidpf)0;\n      pfile_in_zip_read_info->stream.next_in = (voidpf)0;\n      pfile_in_zip_read_info->stream.avail_in = 0;\n\n      err=BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0);\n      if (err == Z_OK)\n        pfile_in_zip_read_info->stream_initialised=Z_BZIP2ED;\n      else\n      {\n        TRYFREE(pfile_in_zip_read_info);\n        return err;\n      }\n#else\n      pfile_in_zip_read_info->raw=1;\n#endif\n    }\n    else if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw))\n    {\n      pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;\n      pfile_in_zip_read_info->stream.zfree = (free_func)0;\n      pfile_in_zip_read_info->stream.opaque = (voidpf)0;\n      pfile_in_zip_read_info->stream.next_in = NULL;\n      pfile_in_zip_read_info->stream.avail_in = 0;\n\n      err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);\n      if (err == Z_OK)\n        pfile_in_zip_read_info->stream_initialised=Z_DEFLATED;\n      else\n      {\n        TRYFREE(pfile_in_zip_read_info);\n        return err;\n      }\n        /* windowBits is passed < 0 to tell that there is no zlib header.\n         * Note that in this case inflate *requires* an extra \"dummy\" byte\n         * after the compressed stream in order to complete decompression and\n         * return Z_STREAM_END.\n         * In unzip, i don't wait absolutely Z_STREAM_END because I known the\n         * size of both compressed and uncompressed data\n         */\n    }\n    pfile_in_zip_read_info->rest_read_compressed =\n            s->cur_file_info.compressed_size ;\n    pfile_in_zip_read_info->rest_read_uncompressed =\n            s->cur_file_info.uncompressed_size ;\n\n\n    pfile_in_zip_read_info->pos_in_zipfile =\n            s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +\n              iSizeVar;\n\n    pfile_in_zip_read_info->stream.avail_in = (uInt)0;\n\n    s->pfile_in_zip_read = pfile_in_zip_read_info;\n                s->encrypted = 0;\n\n#    ifndef NOUNCRYPT\n    if (password != NULL)\n    {\n        int i;\n        s->pcrc_32_tab = get_crc_table();\n        init_keys(password,s->keys,s->pcrc_32_tab);\n        if (ZSEEK64(s->z_filefunc, s->filestream,\n                  s->pfile_in_zip_read->pos_in_zipfile +\n                     s->pfile_in_zip_read->byte_before_the_zipfile,\n                  SEEK_SET)!=0)\n            return UNZ_INTERNALERROR;\n        if(ZREAD64(s->z_filefunc, s->filestream,source, 12)<12)\n            return UNZ_INTERNALERROR;\n\n        for (i = 0; i<12; i++)\n            zdecode(s->keys,s->pcrc_32_tab,source[i]);\n\n        s->pfile_in_zip_read->pos_in_zipfile+=12;\n        s->encrypted=1;\n    }\n#    endif\n\n\n    return UNZ_OK;\n}\n\nextern int ZEXPORT unzOpenCurrentFile (unzFile file)\n{\n    return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);\n}\n\nextern int ZEXPORT unzOpenCurrentFilePassword (unzFile file, const char*  password)\n{\n    return unzOpenCurrentFile3(file, NULL, NULL, 0, password);\n}\n\nextern int ZEXPORT unzOpenCurrentFile2 (unzFile file, int* method, int* level, int raw)\n{\n    return unzOpenCurrentFile3(file, method, level, raw, NULL);\n}\n\n/** Addition for GDAL : START */\n\nextern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64( unzFile file)\n{\n    unz64_s* s;\n    file_in_zip64_read_info_s* pfile_in_zip_read_info;\n    s=(unz64_s*)file;\n    if (file==NULL)\n        return 0; //UNZ_PARAMERROR;\n    pfile_in_zip_read_info=s->pfile_in_zip_read;\n    if (pfile_in_zip_read_info==NULL)\n        return 0; //UNZ_PARAMERROR;\n    return pfile_in_zip_read_info->pos_in_zipfile +\n                         pfile_in_zip_read_info->byte_before_the_zipfile;\n}\n\n/** Addition for GDAL : END */\n\n/*\n  Read bytes from the current file.\n  buf contain buffer where data must be copied\n  len the size of buf.\n\n  return the number of byte copied if somes bytes are copied\n  return 0 if the end of file was reached\n  return <0 with error code if there is an error\n    (UNZ_ERRNO for IO error, or zLib error for uncompress error)\n*/\nextern int ZEXPORT unzReadCurrentFile  (unzFile file, voidp buf, unsigned len)\n{\n    int err=UNZ_OK;\n    uInt iRead = 0;\n    unz64_s* s;\n    file_in_zip64_read_info_s* pfile_in_zip_read_info;\n    if (file==NULL)\n        return UNZ_PARAMERROR;\n    s=(unz64_s*)file;\n    pfile_in_zip_read_info=s->pfile_in_zip_read;\n\n    if (pfile_in_zip_read_info==NULL)\n        return UNZ_PARAMERROR;\n\n\n    if (pfile_in_zip_read_info->read_buffer == NULL)        return UNZ_END_OF_LIST_OF_FILE;\n    if (len==0)\n        return 0;\n\n    pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;\n\n    pfile_in_zip_read_info->stream.avail_out = (uInt)len;\n\n    if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&\n        (!(pfile_in_zip_read_info->raw)))\n        pfile_in_zip_read_info->stream.avail_out =\n            (uInt)pfile_in_zip_read_info->rest_read_uncompressed;\n\n    if ((len>pfile_in_zip_read_info->rest_read_compressed+\n           pfile_in_zip_read_info->stream.avail_in) &&\n         (pfile_in_zip_read_info->raw))\n        pfile_in_zip_read_info->stream.avail_out =\n            (uInt)pfile_in_zip_read_info->rest_read_compressed+\n            pfile_in_zip_read_info->stream.avail_in;\n\n    while (pfile_in_zip_read_info->stream.avail_out>0)\n    {\n        if ((pfile_in_zip_read_info->stream.avail_in==0) &&\n            (pfile_in_zip_read_info->rest_read_compressed>0))\n        {\n            uInt uReadThis = UNZ_BUFSIZE;\n            if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)\n                uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;\n            if (uReadThis == 0)\n                return UNZ_EOF;\n            if (ZSEEK64(pfile_in_zip_read_info->z_filefunc,\n                      pfile_in_zip_read_info->filestream,\n                      pfile_in_zip_read_info->pos_in_zipfile +\n                         pfile_in_zip_read_info->byte_before_the_zipfile,\n                         ZLIB_FILEFUNC_SEEK_SET)!=0)\n                return UNZ_ERRNO;\n            if (ZREAD64(pfile_in_zip_read_info->z_filefunc,\n                      pfile_in_zip_read_info->filestream,\n                      pfile_in_zip_read_info->read_buffer,\n                      uReadThis)!=uReadThis)\n                return UNZ_ERRNO;\n\n\n#            ifndef NOUNCRYPT\n            if(s->encrypted)\n            {\n                uInt i;\n                for(i=0;i<uReadThis;i++)\n                  pfile_in_zip_read_info->read_buffer[i] =\n                      zdecode(s->keys,s->pcrc_32_tab,\n                              pfile_in_zip_read_info->read_buffer[i]);\n            }\n#            endif\n\n\n            pfile_in_zip_read_info->pos_in_zipfile += uReadThis;\n\n            pfile_in_zip_read_info->rest_read_compressed-=uReadThis;\n\n            pfile_in_zip_read_info->stream.next_in =\n                (Bytef*)pfile_in_zip_read_info->read_buffer;\n            pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;\n        }\n\n        if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))\n        {\n            uInt uDoCopy,i ;\n\n            if ((pfile_in_zip_read_info->stream.avail_in == 0) &&\n                (pfile_in_zip_read_info->rest_read_compressed == 0))\n                return (iRead==0) ? UNZ_EOF : iRead;\n\n            if (pfile_in_zip_read_info->stream.avail_out <\n                            pfile_in_zip_read_info->stream.avail_in)\n                uDoCopy = pfile_in_zip_read_info->stream.avail_out ;\n            else\n                uDoCopy = pfile_in_zip_read_info->stream.avail_in ;\n\n            for (i=0;i<uDoCopy;i++)\n                *(pfile_in_zip_read_info->stream.next_out+i) =\n                        *(pfile_in_zip_read_info->stream.next_in+i);\n\n            pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uDoCopy;\n\n            pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,\n                                pfile_in_zip_read_info->stream.next_out,\n                                uDoCopy);\n            pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;\n            pfile_in_zip_read_info->stream.avail_in -= uDoCopy;\n            pfile_in_zip_read_info->stream.avail_out -= uDoCopy;\n            pfile_in_zip_read_info->stream.next_out += uDoCopy;\n            pfile_in_zip_read_info->stream.next_in += uDoCopy;\n            pfile_in_zip_read_info->stream.total_out += uDoCopy;\n            iRead += uDoCopy;\n        }\n        else if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED)\n        {\n#ifdef HAVE_BZIP2\n            uLong uTotalOutBefore,uTotalOutAfter;\n            const Bytef *bufBefore;\n            uLong uOutThis;\n\n            pfile_in_zip_read_info->bstream.next_in        = (char*)pfile_in_zip_read_info->stream.next_in;\n            pfile_in_zip_read_info->bstream.avail_in       = pfile_in_zip_read_info->stream.avail_in;\n            pfile_in_zip_read_info->bstream.total_in_lo32  = pfile_in_zip_read_info->stream.total_in;\n            pfile_in_zip_read_info->bstream.total_in_hi32  = 0;\n            pfile_in_zip_read_info->bstream.next_out       = (char*)pfile_in_zip_read_info->stream.next_out;\n            pfile_in_zip_read_info->bstream.avail_out      = pfile_in_zip_read_info->stream.avail_out;\n            pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out;\n            pfile_in_zip_read_info->bstream.total_out_hi32 = 0;\n\n            uTotalOutBefore = pfile_in_zip_read_info->bstream.total_out_lo32;\n            bufBefore = (const Bytef *)pfile_in_zip_read_info->bstream.next_out;\n\n            err=BZ2_bzDecompress(&pfile_in_zip_read_info->bstream);\n\n            uTotalOutAfter = pfile_in_zip_read_info->bstream.total_out_lo32;\n            uOutThis = uTotalOutAfter-uTotalOutBefore;\n\n            pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis;\n\n            pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,bufBefore, (uInt)(uOutThis));\n            pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis;\n            iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);\n\n            pfile_in_zip_read_info->stream.next_in   = (Bytef*)pfile_in_zip_read_info->bstream.next_in;\n            pfile_in_zip_read_info->stream.avail_in  = pfile_in_zip_read_info->bstream.avail_in;\n            pfile_in_zip_read_info->stream.total_in  = pfile_in_zip_read_info->bstream.total_in_lo32;\n            pfile_in_zip_read_info->stream.next_out  = (Bytef*)pfile_in_zip_read_info->bstream.next_out;\n            pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out;\n            pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32;\n\n            if (err==BZ_STREAM_END)\n              return (iRead==0) ? UNZ_EOF : iRead;\n            if (err!=BZ_OK)\n              break;\n#endif\n        } // end Z_BZIP2ED\n        else\n        {\n            ZPOS64_T uTotalOutBefore,uTotalOutAfter;\n            const Bytef *bufBefore;\n            ZPOS64_T uOutThis;\n            int flush=Z_SYNC_FLUSH;\n\n            uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;\n            bufBefore = pfile_in_zip_read_info->stream.next_out;\n\n            /*\n            if ((pfile_in_zip_read_info->rest_read_uncompressed ==\n                     pfile_in_zip_read_info->stream.avail_out) &&\n                (pfile_in_zip_read_info->rest_read_compressed == 0))\n                flush = Z_FINISH;\n            */\n            err=inflate(&pfile_in_zip_read_info->stream,flush);\n\n            if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))\n              err = Z_DATA_ERROR;\n\n            uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;\n            uOutThis = uTotalOutAfter-uTotalOutBefore;\n\n            pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis;\n\n            pfile_in_zip_read_info->crc32 =\n                crc32(pfile_in_zip_read_info->crc32,bufBefore,\n                        (uInt)(uOutThis));\n\n            pfile_in_zip_read_info->rest_read_uncompressed -=\n                uOutThis;\n\n            iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);\n\n            if (err==Z_STREAM_END)\n                return (iRead==0) ? UNZ_EOF : iRead;\n            if (err!=Z_OK)\n                break;\n        }\n    }\n\n    if (err==Z_OK)\n        return iRead;\n    return err;\n}\n\n\n/*\n  Give the current position in uncompressed data\n*/\nextern z_off_t ZEXPORT unztell (unzFile file)\n{\n    unz64_s* s;\n    file_in_zip64_read_info_s* pfile_in_zip_read_info;\n    if (file==NULL)\n        return UNZ_PARAMERROR;\n    s=(unz64_s*)file;\n    pfile_in_zip_read_info=s->pfile_in_zip_read;\n\n    if (pfile_in_zip_read_info==NULL)\n        return UNZ_PARAMERROR;\n\n    return (z_off_t)pfile_in_zip_read_info->stream.total_out;\n}\n\nextern ZPOS64_T ZEXPORT unztell64 (unzFile file)\n{\n\n    unz64_s* s;\n    file_in_zip64_read_info_s* pfile_in_zip_read_info;\n    if (file==NULL)\n        return (ZPOS64_T)-1;\n    s=(unz64_s*)file;\n    pfile_in_zip_read_info=s->pfile_in_zip_read;\n\n    if (pfile_in_zip_read_info==NULL)\n        return (ZPOS64_T)-1;\n\n    return pfile_in_zip_read_info->total_out_64;\n}\n\n\n/*\n  return 1 if the end of file was reached, 0 elsewhere\n*/\nextern int ZEXPORT unzeof (unzFile file)\n{\n    unz64_s* s;\n    file_in_zip64_read_info_s* pfile_in_zip_read_info;\n    if (file==NULL)\n        return UNZ_PARAMERROR;\n    s=(unz64_s*)file;\n    pfile_in_zip_read_info=s->pfile_in_zip_read;\n\n    if (pfile_in_zip_read_info==NULL)\n        return UNZ_PARAMERROR;\n\n    if (pfile_in_zip_read_info->rest_read_uncompressed == 0)\n        return 1;\n    else\n        return 0;\n}\n\n\n\n/*\nRead extra field from the current file (opened by unzOpenCurrentFile)\nThis is the local-header version of the extra field (sometimes, there is\nmore info in the local-header version than in the central-header)\n\n  if buf==NULL, it return the size of the local extra field that can be read\n\n  if buf!=NULL, len is the size of the buffer, the extra header is copied in\n    buf.\n  the return value is the number of bytes copied in buf, or (if <0)\n    the error code\n*/\nextern int ZEXPORT unzGetLocalExtrafield (unzFile file, voidp buf, unsigned len)\n{\n    unz64_s* s;\n    file_in_zip64_read_info_s* pfile_in_zip_read_info;\n    uInt read_now;\n    ZPOS64_T size_to_read;\n\n    if (file==NULL)\n        return UNZ_PARAMERROR;\n    s=(unz64_s*)file;\n    pfile_in_zip_read_info=s->pfile_in_zip_read;\n\n    if (pfile_in_zip_read_info==NULL)\n        return UNZ_PARAMERROR;\n\n    size_to_read = (pfile_in_zip_read_info->size_local_extrafield -\n                pfile_in_zip_read_info->pos_local_extrafield);\n\n    if (buf==NULL)\n        return (int)size_to_read;\n\n    if (len>size_to_read)\n        read_now = (uInt)size_to_read;\n    else\n        read_now = (uInt)len ;\n\n    if (read_now==0)\n        return 0;\n\n    if (ZSEEK64(pfile_in_zip_read_info->z_filefunc,\n              pfile_in_zip_read_info->filestream,\n              pfile_in_zip_read_info->offset_local_extrafield +\n              pfile_in_zip_read_info->pos_local_extrafield,\n              ZLIB_FILEFUNC_SEEK_SET)!=0)\n        return UNZ_ERRNO;\n\n    if (ZREAD64(pfile_in_zip_read_info->z_filefunc,\n              pfile_in_zip_read_info->filestream,\n              buf,read_now)!=read_now)\n        return UNZ_ERRNO;\n\n    return (int)read_now;\n}\n\n/*\n  Close the file in zip opened with unzipOpenCurrentFile\n  Return UNZ_CRCERROR if all the file was read but the CRC is not good\n*/\nextern int ZEXPORT unzCloseCurrentFile (unzFile file)\n{\n    int err=UNZ_OK;\n\n    unz64_s* s;\n    file_in_zip64_read_info_s* pfile_in_zip_read_info;\n    if (file==NULL)\n        return UNZ_PARAMERROR;\n    s=(unz64_s*)file;\n    pfile_in_zip_read_info=s->pfile_in_zip_read;\n\n    if (pfile_in_zip_read_info==NULL)\n        return UNZ_PARAMERROR;\n\n\n    if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&\n        (!pfile_in_zip_read_info->raw))\n    {\n        if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)\n            err=UNZ_CRCERROR;\n    }\n\n\n    TRYFREE(pfile_in_zip_read_info->read_buffer);\n    pfile_in_zip_read_info->read_buffer = NULL;\n    if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED)\n        inflateEnd(&pfile_in_zip_read_info->stream);\n#ifdef HAVE_BZIP2\n    else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED)\n        BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream);\n#endif\n\n\n    pfile_in_zip_read_info->stream_initialised = 0;\n    TRYFREE(pfile_in_zip_read_info);\n\n    s->pfile_in_zip_read=NULL;\n\n    return err;\n}\n\n\n/*\n  Get the global comment string of the ZipFile, in the szComment buffer.\n  uSizeBuf is the size of the szComment buffer.\n  return the number of byte copied or an error code <0\n*/\nextern int ZEXPORT unzGetGlobalComment (unzFile file, char * szComment, uLong uSizeBuf)\n{\n    unz64_s* s;\n    uLong uReadThis ;\n    if (file==NULL)\n        return (int)UNZ_PARAMERROR;\n    s=(unz64_s*)file;\n\n    uReadThis = uSizeBuf;\n    if (uReadThis>s->gi.size_comment)\n        uReadThis = s->gi.size_comment;\n\n    if (ZSEEK64(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)\n        return UNZ_ERRNO;\n\n    if (uReadThis>0)\n    {\n      *szComment='\\0';\n      if (ZREAD64(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)\n        return UNZ_ERRNO;\n    }\n\n    if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))\n        *(szComment+s->gi.size_comment)='\\0';\n    return (int)uReadThis;\n}\n\n/* Additions by RX '2004 */\nextern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file)\n{\n    unz64_s* s;\n\n    if (file==NULL)\n          return 0; //UNZ_PARAMERROR;\n    s=(unz64_s*)file;\n    if (!s->current_file_ok)\n      return 0;\n    if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)\n      if (s->num_file==s->gi.number_entry)\n         return 0;\n    return s->pos_in_central_dir;\n}\n\nextern uLong ZEXPORT unzGetOffset (unzFile file)\n{\n    ZPOS64_T offset64;\n\n    if (file==NULL)\n          return 0; //UNZ_PARAMERROR;\n    offset64 = unzGetOffset64(file);\n    return (uLong)offset64;\n}\n\nextern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos)\n{\n    unz64_s* s;\n    int err;\n\n    if (file==NULL)\n        return UNZ_PARAMERROR;\n    s=(unz64_s*)file;\n\n    s->pos_in_central_dir = pos;\n    s->num_file = s->gi.number_entry;      /* hack */\n    err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,\n                                              &s->cur_file_info_internal,\n                                              NULL,0,NULL,0,NULL,0);\n    s->current_file_ok = (err == UNZ_OK);\n    return err;\n}\n\nextern int ZEXPORT unzSetOffset (unzFile file, uLong pos)\n{\n    return unzSetOffset64(file,pos);\n}\n"
  },
  {
    "path": "Loader/libs/minizip/unzip.h",
    "content": "/* unzip.h -- IO for uncompress .zip files using zlib\n   Version 1.1, February 14h, 2010\n   part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )\n\n         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )\n\n         Modifications of Unzip for Zip64\n         Copyright (C) 2007-2008 Even Rouault\n\n         Modifications for Zip64 support on both zip and unzip\n         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )\n\n         For more info read MiniZip_info.txt\n\n         ---------------------------------------------------------------------------------\n\n        Condition of use and distribution are the same than zlib :\n\n  This software is provided 'as-is', without any express or implied\n  warranty.  In no event will the authors be held liable for any damages\n  arising from the use of this software.\n\n  Permission is granted to anyone to use this software for any purpose,\n  including commercial applications, and to alter it and redistribute it\n  freely, subject to the following restrictions:\n\n  1. The origin of this software must not be misrepresented; you must not\n     claim that you wrote the original software. If you use this software\n     in a product, an acknowledgment in the product documentation would be\n     appreciated but is not required.\n  2. Altered source versions must be plainly marked as such, and must not be\n     misrepresented as being the original software.\n  3. This notice may not be removed or altered from any source distribution.\n\n  ---------------------------------------------------------------------------------\n\n        Changes\n\n        See header of unzip64.c\n\n*/\n\n#ifndef _unz64_H\n#define _unz64_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#ifndef _ZLIB_H\n#include \"zlib.h\"\n#endif\n\n#ifndef  _ZLIBIOAPI_H\n#include \"ioapi.h\"\n#endif\n\n#ifdef HAVE_BZIP2\n#include \"bzlib.h\"\n#endif\n\n#define Z_BZIP2ED 12\n\n#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)\n/* like the STRICT of WIN32, we define a pointer that cannot be converted\n    from (void*) without cast */\ntypedef struct TagunzFile__ { int unused; } unzFile__;\ntypedef unzFile__ *unzFile;\n#else\ntypedef voidp unzFile;\n#endif\n\n\n#define UNZ_OK                          (0)\n#define UNZ_END_OF_LIST_OF_FILE         (-100)\n#define UNZ_ERRNO                       (Z_ERRNO)\n#define UNZ_EOF                         (0)\n#define UNZ_PARAMERROR                  (-102)\n#define UNZ_BADZIPFILE                  (-103)\n#define UNZ_INTERNALERROR               (-104)\n#define UNZ_CRCERROR                    (-105)\n\n/* tm_unz contain date/time info */\ntypedef struct tm_unz_s\n{\n    uInt tm_sec;            /* seconds after the minute - [0,59] */\n    uInt tm_min;            /* minutes after the hour - [0,59] */\n    uInt tm_hour;           /* hours since midnight - [0,23] */\n    uInt tm_mday;           /* day of the month - [1,31] */\n    uInt tm_mon;            /* months since January - [0,11] */\n    uInt tm_year;           /* years - [1980..2044] */\n} tm_unz;\n\n/* unz_global_info structure contain global data about the ZIPfile\n   These data comes from the end of central dir */\ntypedef struct unz_global_info64_s\n{\n    ZPOS64_T number_entry;         /* total number of entries in\n                                     the central dir on this disk */\n    uLong size_comment;         /* size of the global comment of the zipfile */\n} unz_global_info64;\n\ntypedef struct unz_global_info_s\n{\n    uLong number_entry;         /* total number of entries in\n                                     the central dir on this disk */\n    uLong size_comment;         /* size of the global comment of the zipfile */\n} unz_global_info;\n\n/* unz_file_info contain information about a file in the zipfile */\ntypedef struct unz_file_info64_s\n{\n    uLong version;              /* version made by                 2 bytes */\n    uLong version_needed;       /* version needed to extract       2 bytes */\n    uLong flag;                 /* general purpose bit flag        2 bytes */\n    uLong compression_method;   /* compression method              2 bytes */\n    uLong dosDate;              /* last mod file date in Dos fmt   4 bytes */\n    uLong crc;                  /* crc-32                          4 bytes */\n    ZPOS64_T compressed_size;   /* compressed size                 8 bytes */\n    ZPOS64_T uncompressed_size; /* uncompressed size               8 bytes */\n    uLong size_filename;        /* filename length                 2 bytes */\n    uLong size_file_extra;      /* extra field length              2 bytes */\n    uLong size_file_comment;    /* file comment length             2 bytes */\n\n    uLong disk_num_start;       /* disk number start               2 bytes */\n    uLong internal_fa;          /* internal file attributes        2 bytes */\n    uLong external_fa;          /* external file attributes        4 bytes */\n\n    tm_unz tmu_date;\n} unz_file_info64;\n\ntypedef struct unz_file_info_s\n{\n    uLong version;              /* version made by                 2 bytes */\n    uLong version_needed;       /* version needed to extract       2 bytes */\n    uLong flag;                 /* general purpose bit flag        2 bytes */\n    uLong compression_method;   /* compression method              2 bytes */\n    uLong dosDate;              /* last mod file date in Dos fmt   4 bytes */\n    uLong crc;                  /* crc-32                          4 bytes */\n    uLong compressed_size;      /* compressed size                 4 bytes */\n    uLong uncompressed_size;    /* uncompressed size               4 bytes */\n    uLong size_filename;        /* filename length                 2 bytes */\n    uLong size_file_extra;      /* extra field length              2 bytes */\n    uLong size_file_comment;    /* file comment length             2 bytes */\n\n    uLong disk_num_start;       /* disk number start               2 bytes */\n    uLong internal_fa;          /* internal file attributes        2 bytes */\n    uLong external_fa;          /* external file attributes        4 bytes */\n\n    tm_unz tmu_date;\n} unz_file_info;\n\nextern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,\n                                                 const char* fileName2,\n                                                 int iCaseSensitivity));\n/*\n   Compare two filename (fileName1,fileName2).\n   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)\n   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi\n                                or strcasecmp)\n   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system\n    (like 1 on Unix, 2 on Windows)\n*/\n\n\nextern unzFile ZEXPORT unzOpen OF((const char *path));\nextern unzFile ZEXPORT unzOpen64 OF((const void *path));\n/*\n  Open a Zip file. path contain the full pathname (by example,\n     on a Windows XP computer \"c:\\\\zlib\\\\zlib113.zip\" or on an Unix computer\n     \"zlib/zlib113.zip\".\n     If the zipfile cannot be opened (file don't exist or in not valid), the\n       return value is NULL.\n     Else, the return value is a unzFile Handle, usable with other function\n       of this unzip package.\n     the \"64\" function take a const void* pointer, because the path is just the\n       value passed to the open64_file_func callback.\n     Under Windows, if UNICODE is defined, using fill_fopen64_filefunc, the path\n       is a pointer to a wide unicode string (LPCTSTR is LPCWSTR), so const char*\n       does not describe the reality\n*/\n\n\nextern unzFile ZEXPORT unzOpen2 OF((const char *path,\n                                    zlib_filefunc_def* pzlib_filefunc_def));\n/*\n   Open a Zip file, like unzOpen, but provide a set of file low level API\n      for read/write the zip file (see ioapi.h)\n*/\n\nextern unzFile ZEXPORT unzOpen2_64 OF((const void *path,\n                                    zlib_filefunc64_def* pzlib_filefunc_def));\n/*\n   Open a Zip file, like unz64Open, but provide a set of file low level API\n      for read/write the zip file (see ioapi.h)\n*/\n\nextern int ZEXPORT unzClose OF((unzFile file));\n/*\n  Close a ZipFile opened with unzipOpen.\n  If there is files inside the .Zip opened with unzOpenCurrentFile (see later),\n    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.\n  return UNZ_OK if there is no problem. */\n\nextern int ZEXPORT unzGetGlobalInfo OF((unzFile file,\n                                        unz_global_info *pglobal_info));\n\nextern int ZEXPORT unzGetGlobalInfo64 OF((unzFile file,\n                                        unz_global_info64 *pglobal_info));\n/*\n  Write info about the ZipFile in the *pglobal_info structure.\n  No preparation of the structure is needed\n  return UNZ_OK if there is no problem. */\n\n\nextern int ZEXPORT unzGetGlobalComment OF((unzFile file,\n                                           char *szComment,\n                                           uLong uSizeBuf));\n/*\n  Get the global comment string of the ZipFile, in the szComment buffer.\n  uSizeBuf is the size of the szComment buffer.\n  return the number of byte copied or an error code <0\n*/\n\n\n/***************************************************************************/\n/* Unzip package allow you browse the directory of the zipfile */\n\nextern int ZEXPORT unzGoToFirstFile OF((unzFile file));\n/*\n  Set the current file of the zipfile to the first file.\n  return UNZ_OK if there is no problem\n*/\n\nextern int ZEXPORT unzGoToNextFile OF((unzFile file));\n/*\n  Set the current file of the zipfile to the next file.\n  return UNZ_OK if there is no problem\n  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.\n*/\n\nextern int ZEXPORT unzLocateFile OF((unzFile file,\n                     const char *szFileName,\n                     int iCaseSensitivity));\n/*\n  Try locate the file szFileName in the zipfile.\n  For the iCaseSensitivity signification, see unzStringFileNameCompare\n\n  return value :\n  UNZ_OK if the file is found. It becomes the current file.\n  UNZ_END_OF_LIST_OF_FILE if the file is not found\n*/\n\n\n/* ****************************************** */\n/* Ryan supplied functions */\n/* unz_file_info contain information about a file in the zipfile */\ntypedef struct unz_file_pos_s\n{\n    uLong pos_in_zip_directory;   /* offset in zip file directory */\n    uLong num_of_file;            /* # of file */\n} unz_file_pos;\n\nextern int ZEXPORT unzGetFilePos(\n    unzFile file,\n    unz_file_pos* file_pos);\n\nextern int ZEXPORT unzGoToFilePos(\n    unzFile file,\n    unz_file_pos* file_pos);\n\ntypedef struct unz64_file_pos_s\n{\n    ZPOS64_T pos_in_zip_directory;   /* offset in zip file directory */\n    ZPOS64_T num_of_file;            /* # of file */\n} unz64_file_pos;\n\nextern int ZEXPORT unzGetFilePos64(\n    unzFile file,\n    unz64_file_pos* file_pos);\n\nextern int ZEXPORT unzGoToFilePos64(\n    unzFile file,\n    const unz64_file_pos* file_pos);\n\n/* ****************************************** */\n\nextern int ZEXPORT unzGetCurrentFileInfo64 OF((unzFile file,\n                         unz_file_info64 *pfile_info,\n                         char *szFileName,\n                         uLong fileNameBufferSize,\n                         void *extraField,\n                         uLong extraFieldBufferSize,\n                         char *szComment,\n                         uLong commentBufferSize));\n\nextern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,\n                         unz_file_info *pfile_info,\n                         char *szFileName,\n                         uLong fileNameBufferSize,\n                         void *extraField,\n                         uLong extraFieldBufferSize,\n                         char *szComment,\n                         uLong commentBufferSize));\n/*\n  Get Info about the current file\n  if pfile_info!=NULL, the *pfile_info structure will contain somes info about\n        the current file\n  if szFileName!=NULL, the filemane string will be copied in szFileName\n            (fileNameBufferSize is the size of the buffer)\n  if extraField!=NULL, the extra field information will be copied in extraField\n            (extraFieldBufferSize is the size of the buffer).\n            This is the Central-header version of the extra field\n  if szComment!=NULL, the comment string of the file will be copied in szComment\n            (commentBufferSize is the size of the buffer)\n*/\n\n\n/** Addition for GDAL : START */\n\nextern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64 OF((unzFile file));\n\n/** Addition for GDAL : END */\n\n\n/***************************************************************************/\n/* for reading the content of the current zipfile, you can open it, read data\n   from it, and close it (you can close it before reading all the file)\n   */\n\nextern int ZEXPORT unzOpenCurrentFile OF((unzFile file));\n/*\n  Open for reading data the current file in the zipfile.\n  If there is no error, the return value is UNZ_OK.\n*/\n\nextern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file,\n                                                  const char* password));\n/*\n  Open for reading data the current file in the zipfile.\n  password is a crypting password\n  If there is no error, the return value is UNZ_OK.\n*/\n\nextern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file,\n                                           int* method,\n                                           int* level,\n                                           int raw));\n/*\n  Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)\n    if raw==1\n  *method will receive method of compression, *level will receive level of\n     compression\n  note : you can set level parameter as NULL (if you did not want known level,\n         but you CANNOT set method parameter as NULL\n*/\n\nextern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file,\n                                           int* method,\n                                           int* level,\n                                           int raw,\n                                           const char* password));\n/*\n  Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)\n    if raw==1\n  *method will receive method of compression, *level will receive level of\n     compression\n  note : you can set level parameter as NULL (if you did not want known level,\n         but you CANNOT set method parameter as NULL\n*/\n\n\nextern int ZEXPORT unzCloseCurrentFile OF((unzFile file));\n/*\n  Close the file in zip opened with unzOpenCurrentFile\n  Return UNZ_CRCERROR if all the file was read but the CRC is not good\n*/\n\nextern int ZEXPORT unzReadCurrentFile OF((unzFile file,\n                      voidp buf,\n                      unsigned len));\n/*\n  Read bytes from the current file (opened by unzOpenCurrentFile)\n  buf contain buffer where data must be copied\n  len the size of buf.\n\n  return the number of byte copied if somes bytes are copied\n  return 0 if the end of file was reached\n  return <0 with error code if there is an error\n    (UNZ_ERRNO for IO error, or zLib error for uncompress error)\n*/\n\nextern z_off_t ZEXPORT unztell OF((unzFile file));\n\nextern ZPOS64_T ZEXPORT unztell64 OF((unzFile file));\n/*\n  Give the current position in uncompressed data\n*/\n\nextern int ZEXPORT unzeof OF((unzFile file));\n/*\n  return 1 if the end of file was reached, 0 elsewhere\n*/\n\nextern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,\n                                             voidp buf,\n                                             unsigned len));\n/*\n  Read extra field from the current file (opened by unzOpenCurrentFile)\n  This is the local-header version of the extra field (sometimes, there is\n    more info in the local-header version than in the central-header)\n\n  if buf==NULL, it return the size of the local extra field\n\n  if buf!=NULL, len is the size of the buffer, the extra header is copied in\n    buf.\n  the return value is the number of bytes copied in buf, or (if <0)\n    the error code\n*/\n\n/***************************************************************************/\n\n/* Get the current file offset */\nextern ZPOS64_T ZEXPORT unzGetOffset64 (unzFile file);\nextern uLong ZEXPORT unzGetOffset (unzFile file);\n\n/* Set the current file offset */\nextern int ZEXPORT unzSetOffset64 (unzFile file, ZPOS64_T pos);\nextern int ZEXPORT unzSetOffset (unzFile file, uLong pos);\n\n\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* _unz64_H */\n"
  },
  {
    "path": "Loader/libs/minizip/zip.c",
    "content": "/* zip.c -- IO on .zip files using zlib\n   Version 1.1, February 14h, 2010\n   part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )\n\n         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )\n\n         Modifications for Zip64 support\n         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )\n\n         For more info read MiniZip_info.txt\n\n         Changes\n   Oct-2009 - Mathias Svensson - Remove old C style function prototypes\n   Oct-2009 - Mathias Svensson - Added Zip64 Support when creating new file archives\n   Oct-2009 - Mathias Svensson - Did some code cleanup and refactoring to get better overview of some functions.\n   Oct-2009 - Mathias Svensson - Added zipRemoveExtraInfoBlock to strip extra field data from its ZIP64 data\n                                 It is used when recreting zip archive with RAW when deleting items from a zip.\n                                 ZIP64 data is automaticly added to items that needs it, and existing ZIP64 data need to be removed.\n   Oct-2009 - Mathias Svensson - Added support for BZIP2 as compression mode (bzip2 lib is required)\n   Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer\n\n*/\n\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n#include \"zlib.h\"\n#include \"zip.h\"\n\n#ifdef STDC\n#  include <stddef.h>\n#  include <string.h>\n#  include <stdlib.h>\n#endif\n#ifdef NO_ERRNO_H\n    extern int errno;\n#else\n#   include <errno.h>\n#endif\n\n\n#ifndef local\n#  define local static\n#endif\n/* compile with -Dlocal if your debugger can't find static symbols */\n\n#ifndef VERSIONMADEBY\n# define VERSIONMADEBY   (0x0) /* platform depedent */\n#endif\n\n#ifndef Z_BUFSIZE\n#define Z_BUFSIZE (64*1024) //(16384)\n#endif\n\n#ifndef Z_MAXFILENAMEINZIP\n#define Z_MAXFILENAMEINZIP (256)\n#endif\n\n#ifndef ALLOC\n# define ALLOC(size) (malloc(size))\n#endif\n#ifndef TRYFREE\n# define TRYFREE(p) {if (p) free(p);}\n#endif\n\n/*\n#define SIZECENTRALDIRITEM (0x2e)\n#define SIZEZIPLOCALHEADER (0x1e)\n*/\n\n/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */\n\n\n// NOT sure that this work on ALL platform\n#define MAKEULONG64(a, b) ((ZPOS64_T)(((unsigned long)(a)) | ((ZPOS64_T)((unsigned long)(b))) << 32))\n\n#ifndef SEEK_CUR\n#define SEEK_CUR    1\n#endif\n\n#ifndef SEEK_END\n#define SEEK_END    2\n#endif\n\n#ifndef SEEK_SET\n#define SEEK_SET    0\n#endif\n\n#ifndef DEF_MEM_LEVEL\n#if MAX_MEM_LEVEL >= 8\n#  define DEF_MEM_LEVEL 8\n#else\n#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL\n#endif\n#endif\nconst char zip_copyright[] =\" zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll\";\n\n\n#define SIZEDATA_INDATABLOCK (4096-(4*4))\n\n#define LOCALHEADERMAGIC    (0x04034b50)\n#define CENTRALHEADERMAGIC  (0x02014b50)\n#define ENDHEADERMAGIC      (0x06054b50)\n#define ZIP64ENDHEADERMAGIC      (0x6064b50)\n#define ZIP64ENDLOCHEADERMAGIC   (0x7064b50)\n\n#define FLAG_LOCALHEADER_OFFSET (0x06)\n#define CRC_LOCALHEADER_OFFSET  (0x0e)\n\n#define SIZECENTRALHEADER (0x2e) /* 46 */\n\ntypedef struct linkedlist_datablock_internal_s\n{\n  struct linkedlist_datablock_internal_s* next_datablock;\n  uLong  avail_in_this_block;\n  uLong  filled_in_this_block;\n  uLong  unused; /* for future use and alignement */\n  unsigned char data[SIZEDATA_INDATABLOCK];\n} linkedlist_datablock_internal;\n\ntypedef struct linkedlist_data_s\n{\n    linkedlist_datablock_internal* first_block;\n    linkedlist_datablock_internal* last_block;\n} linkedlist_data;\n\n\ntypedef struct\n{\n    z_stream stream;            /* zLib stream structure for inflate */\n#ifdef HAVE_BZIP2\n    bz_stream bstream;          /* bzLib stream structure for bziped */\n#endif\n\n    int  stream_initialised;    /* 1 is stream is initialised */\n    uInt pos_in_buffered_data;  /* last written byte in buffered_data */\n\n    ZPOS64_T pos_local_header;     /* offset of the local header of the file\n                                     currenty writing */\n    char* central_header;       /* central header data for the current file */\n    uLong size_centralExtra;\n    uLong size_centralheader;   /* size of the central header for cur file */\n    uLong size_centralExtraFree; /* Extra bytes allocated to the centralheader but that are not used */\n    uLong flag;                 /* flag of the file currently writing */\n\n    int  method;                /* compression method of file currenty wr.*/\n    int  raw;                   /* 1 for directly writing raw data */\n    Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/\n    uLong dosDate;\n    uLong crc32;\n    int  encrypt;\n    int  zip64;               /* Add ZIP64 extened information in the extra field */\n    ZPOS64_T pos_zip64extrainfo;\n    ZPOS64_T totalCompressedData;\n    ZPOS64_T totalUncompressedData;\n#ifndef NOCRYPT\n    unsigned long keys[3];     /* keys defining the pseudo-random sequence */\n    const unsigned long* pcrc_32_tab;\n    int crypt_header_size;\n#endif\n} curfile64_info;\n\ntypedef struct\n{\n    zlib_filefunc64_32_def z_filefunc;\n    voidpf filestream;        /* io structore of the zipfile */\n    linkedlist_data central_dir;/* datablock with central dir in construction*/\n    int  in_opened_file_inzip;  /* 1 if a file in the zip is currently writ.*/\n    curfile64_info ci;            /* info on the file curretly writing */\n\n    ZPOS64_T begin_pos;            /* position of the beginning of the zipfile */\n    ZPOS64_T add_position_when_writting_offset;\n    ZPOS64_T number_entry;\n\n#ifndef NO_ADDFILEINEXISTINGZIP\n    char *globalcomment;\n#endif\n\n} zip64_internal;\n\n\n#ifndef NOCRYPT\n#define INCLUDECRYPTINGCODE_IFCRYPTALLOWED\n#include \"crypt.h\"\n#endif\n\nlocal linkedlist_datablock_internal* allocate_new_datablock()\n{\n    linkedlist_datablock_internal* ldi;\n    ldi = (linkedlist_datablock_internal*)\n                 ALLOC(sizeof(linkedlist_datablock_internal));\n    if (ldi!=NULL)\n    {\n        ldi->next_datablock = NULL ;\n        ldi->filled_in_this_block = 0 ;\n        ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ;\n    }\n    return ldi;\n}\n\nlocal void free_datablock(linkedlist_datablock_internal* ldi)\n{\n    while (ldi!=NULL)\n    {\n        linkedlist_datablock_internal* ldinext = ldi->next_datablock;\n        TRYFREE(ldi);\n        ldi = ldinext;\n    }\n}\n\nlocal void init_linkedlist(linkedlist_data* ll)\n{\n    ll->first_block = ll->last_block = NULL;\n}\n\nlocal void free_linkedlist(linkedlist_data* ll)\n{\n    free_datablock(ll->first_block);\n    ll->first_block = ll->last_block = NULL;\n}\n\n\nlocal int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len)\n{\n    linkedlist_datablock_internal* ldi;\n    const unsigned char* from_copy;\n\n    if (ll==NULL)\n        return ZIP_INTERNALERROR;\n\n    if (ll->last_block == NULL)\n    {\n        ll->first_block = ll->last_block = allocate_new_datablock();\n        if (ll->first_block == NULL)\n            return ZIP_INTERNALERROR;\n    }\n\n    ldi = ll->last_block;\n    from_copy = (unsigned char*)buf;\n\n    while (len>0)\n    {\n        uInt copy_this;\n        uInt i;\n        unsigned char* to_copy;\n\n        if (ldi->avail_in_this_block==0)\n        {\n            ldi->next_datablock = allocate_new_datablock();\n            if (ldi->next_datablock == NULL)\n                return ZIP_INTERNALERROR;\n            ldi = ldi->next_datablock ;\n            ll->last_block = ldi;\n        }\n\n        if (ldi->avail_in_this_block < len)\n            copy_this = (uInt)ldi->avail_in_this_block;\n        else\n            copy_this = (uInt)len;\n\n        to_copy = &(ldi->data[ldi->filled_in_this_block]);\n\n        for (i=0;i<copy_this;i++)\n            *(to_copy+i)=*(from_copy+i);\n\n        ldi->filled_in_this_block += copy_this;\n        ldi->avail_in_this_block -= copy_this;\n        from_copy += copy_this ;\n        len -= copy_this;\n    }\n    return ZIP_OK;\n}\n\n\n\n/****************************************************************************/\n\n#ifndef NO_ADDFILEINEXISTINGZIP\n/* ===========================================================================\n   Inputs a long in LSB order to the given file\n   nbByte == 1, 2 ,4 or 8 (byte, short or long, ZPOS64_T)\n*/\n\nlocal int zip64local_putValue OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte));\nlocal int zip64local_putValue (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte)\n{\n    unsigned char buf[8];\n    int n;\n    for (n = 0; n < nbByte; n++)\n    {\n        buf[n] = (unsigned char)(x & 0xff);\n        x >>= 8;\n    }\n    if (x != 0)\n      {     /* data overflow - hack for ZIP64 (X Roche) */\n      for (n = 0; n < nbByte; n++)\n        {\n          buf[n] = 0xff;\n        }\n      }\n\n    if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte)\n        return ZIP_ERRNO;\n    else\n        return ZIP_OK;\n}\n\nlocal void zip64local_putValue_inmemory OF((void* dest, ZPOS64_T x, int nbByte));\nlocal void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte)\n{\n    unsigned char* buf=(unsigned char*)dest;\n    int n;\n    for (n = 0; n < nbByte; n++) {\n        buf[n] = (unsigned char)(x & 0xff);\n        x >>= 8;\n    }\n\n    if (x != 0)\n    {     /* data overflow - hack for ZIP64 */\n       for (n = 0; n < nbByte; n++)\n       {\n          buf[n] = 0xff;\n       }\n    }\n}\n\n/****************************************************************************/\n\n\nlocal uLong zip64local_TmzDateToDosDate(const tm_zip* ptm)\n{\n    uLong year = (uLong)ptm->tm_year;\n    if (year>=1980)\n        year-=1980;\n    else if (year>=80)\n        year-=80;\n    return\n      (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) |\n        ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour));\n}\n\n\n/****************************************************************************/\n\nlocal int zip64local_getByte OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int *pi));\n\nlocal int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def,voidpf filestream,int* pi)\n{\n    unsigned char c;\n    int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1);\n    if (err==1)\n    {\n        *pi = (int)c;\n        return ZIP_OK;\n    }\n    else\n    {\n        if (ZERROR64(*pzlib_filefunc_def,filestream))\n            return ZIP_ERRNO;\n        else\n            return ZIP_EOF;\n    }\n}\n\n\n/* ===========================================================================\n   Reads a long in LSB order from the given gz_stream. Sets\n*/\nlocal int zip64local_getShort OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX));\n\nlocal int zip64local_getShort (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX)\n{\n    uLong x ;\n    int i = 0;\n    int err;\n\n    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);\n    x = (uLong)i;\n\n    if (err==ZIP_OK)\n        err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);\n    x += ((uLong)i)<<8;\n\n    if (err==ZIP_OK)\n        *pX = x;\n    else\n        *pX = 0;\n    return err;\n}\n\nlocal int zip64local_getLong OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong *pX));\n\nlocal int zip64local_getLong (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX)\n{\n    uLong x ;\n    int i = 0;\n    int err;\n\n    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);\n    x = (uLong)i;\n\n    if (err==ZIP_OK)\n        err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);\n    x += ((uLong)i)<<8;\n\n    if (err==ZIP_OK)\n        err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);\n    x += ((uLong)i)<<16;\n\n    if (err==ZIP_OK)\n        err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);\n    x += ((uLong)i)<<24;\n\n    if (err==ZIP_OK)\n        *pX = x;\n    else\n        *pX = 0;\n    return err;\n}\n\nlocal int zip64local_getLong64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX));\n\n\nlocal int zip64local_getLong64 (const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX)\n{\n  ZPOS64_T x;\n  int i = 0;\n  int err;\n\n  err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);\n  x = (ZPOS64_T)i;\n\n  if (err==ZIP_OK)\n    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);\n  x += ((ZPOS64_T)i)<<8;\n\n  if (err==ZIP_OK)\n    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);\n  x += ((ZPOS64_T)i)<<16;\n\n  if (err==ZIP_OK)\n    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);\n  x += ((ZPOS64_T)i)<<24;\n\n  if (err==ZIP_OK)\n    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);\n  x += ((ZPOS64_T)i)<<32;\n\n  if (err==ZIP_OK)\n    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);\n  x += ((ZPOS64_T)i)<<40;\n\n  if (err==ZIP_OK)\n    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);\n  x += ((ZPOS64_T)i)<<48;\n\n  if (err==ZIP_OK)\n    err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);\n  x += ((ZPOS64_T)i)<<56;\n\n  if (err==ZIP_OK)\n    *pX = x;\n  else\n    *pX = 0;\n\n  return err;\n}\n\n#ifndef BUFREADCOMMENT\n#define BUFREADCOMMENT (0x400)\n#endif\n/*\n  Locate the Central directory of a zipfile (at the end, just before\n    the global comment)\n*/\nlocal ZPOS64_T zip64local_SearchCentralDir OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream));\n\nlocal ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)\n{\n  unsigned char* buf;\n  ZPOS64_T uSizeFile;\n  ZPOS64_T uBackRead;\n  ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */\n  ZPOS64_T uPosFound=0;\n\n  if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)\n    return 0;\n\n\n  uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);\n\n  if (uMaxBack>uSizeFile)\n    uMaxBack = uSizeFile;\n\n  buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);\n  if (buf==NULL)\n    return 0;\n\n  uBackRead = 4;\n  while (uBackRead<uMaxBack)\n  {\n    uLong uReadSize;\n    ZPOS64_T uReadPos ;\n    int i;\n    if (uBackRead+BUFREADCOMMENT>uMaxBack)\n      uBackRead = uMaxBack;\n    else\n      uBackRead+=BUFREADCOMMENT;\n    uReadPos = uSizeFile-uBackRead ;\n\n    uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?\n      (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);\n    if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)\n      break;\n\n    if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)\n      break;\n\n    for (i=(int)uReadSize-3; (i--)>0;)\n      if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&\n        ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))\n      {\n        uPosFound = uReadPos+i;\n        break;\n      }\n\n      if (uPosFound!=0)\n        break;\n  }\n  TRYFREE(buf);\n  return uPosFound;\n}\n\n/*\nLocate the End of Zip64 Central directory locator and from there find the CD of a zipfile (at the end, just before\nthe global comment)\n*/\nlocal ZPOS64_T zip64local_SearchCentralDir64 OF((const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream));\n\nlocal ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream)\n{\n  unsigned char* buf;\n  ZPOS64_T uSizeFile;\n  ZPOS64_T uBackRead;\n  ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */\n  ZPOS64_T uPosFound=0;\n  uLong uL;\n  ZPOS64_T relativeOffset;\n\n  if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)\n    return 0;\n\n  uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);\n\n  if (uMaxBack>uSizeFile)\n    uMaxBack = uSizeFile;\n\n  buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);\n  if (buf==NULL)\n    return 0;\n\n  uBackRead = 4;\n  while (uBackRead<uMaxBack)\n  {\n    uLong uReadSize;\n    ZPOS64_T uReadPos;\n    int i;\n    if (uBackRead+BUFREADCOMMENT>uMaxBack)\n      uBackRead = uMaxBack;\n    else\n      uBackRead+=BUFREADCOMMENT;\n    uReadPos = uSizeFile-uBackRead ;\n\n    uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?\n      (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);\n    if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)\n      break;\n\n    if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)\n      break;\n\n    for (i=(int)uReadSize-3; (i--)>0;)\n    {\n      // Signature \"0x07064b50\" Zip64 end of central directory locater\n      if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07))\n      {\n        uPosFound = uReadPos+i;\n        break;\n      }\n    }\n\n      if (uPosFound!=0)\n        break;\n  }\n\n  TRYFREE(buf);\n  if (uPosFound == 0)\n    return 0;\n\n  /* Zip64 end of central directory locator */\n  if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0)\n    return 0;\n\n  /* the signature, already checked */\n  if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)\n    return 0;\n\n  /* number of the disk with the start of the zip64 end of  central directory */\n  if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)\n    return 0;\n  if (uL != 0)\n    return 0;\n\n  /* relative offset of the zip64 end of central directory record */\n  if (zip64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=ZIP_OK)\n    return 0;\n\n  /* total number of disks */\n  if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)\n    return 0;\n  if (uL != 1)\n    return 0;\n\n  /* Goto Zip64 end of central directory record */\n  if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0)\n    return 0;\n\n  /* the signature */\n  if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)\n    return 0;\n\n  if (uL != 0x06064b50) // signature of 'Zip64 end of central directory'\n    return 0;\n\n  return relativeOffset;\n}\n\nint LoadCentralDirectoryRecord(zip64_internal* pziinit)\n{\n  int err=ZIP_OK;\n  ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/\n\n  ZPOS64_T size_central_dir;     /* size of the central directory  */\n  ZPOS64_T offset_central_dir;   /* offset of start of central directory */\n  ZPOS64_T central_pos;\n  uLong uL;\n\n  uLong number_disk;          /* number of the current dist, used for\n                              spaning ZIP, unsupported, always 0*/\n  uLong number_disk_with_CD;  /* number the the disk with central dir, used\n                              for spaning ZIP, unsupported, always 0*/\n  ZPOS64_T number_entry;\n  ZPOS64_T number_entry_CD;      /* total number of entries in\n                                the central dir\n                                (same than number_entry on nospan) */\n  uLong VersionMadeBy;\n  uLong VersionNeeded;\n  uLong size_comment;\n\n  int hasZIP64Record = 0;\n\n  // check first if we find a ZIP64 record\n  central_pos = zip64local_SearchCentralDir64(&pziinit->z_filefunc,pziinit->filestream);\n  if(central_pos > 0)\n  {\n    hasZIP64Record = 1;\n  }\n  else if(central_pos == 0)\n  {\n    central_pos = zip64local_SearchCentralDir(&pziinit->z_filefunc,pziinit->filestream);\n  }\n\n/* disable to allow appending to empty ZIP archive\n        if (central_pos==0)\n            err=ZIP_ERRNO;\n*/\n\n  if(hasZIP64Record)\n  {\n    ZPOS64_T sizeEndOfCentralDirectory;\n    if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)\n      err=ZIP_ERRNO;\n\n    /* the signature, already checked */\n    if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK)\n      err=ZIP_ERRNO;\n\n    /* size of zip64 end of central directory record */\n    if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &sizeEndOfCentralDirectory)!=ZIP_OK)\n      err=ZIP_ERRNO;\n\n    /* version made by */\n    if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionMadeBy)!=ZIP_OK)\n      err=ZIP_ERRNO;\n\n    /* version needed to extract */\n    if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionNeeded)!=ZIP_OK)\n      err=ZIP_ERRNO;\n\n    /* number of this disk */\n    if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK)\n      err=ZIP_ERRNO;\n\n    /* number of the disk with the start of the central directory */\n    if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK)\n      err=ZIP_ERRNO;\n\n    /* total number of entries in the central directory on this disk */\n    if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &number_entry)!=ZIP_OK)\n      err=ZIP_ERRNO;\n\n    /* total number of entries in the central directory */\n    if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&number_entry_CD)!=ZIP_OK)\n      err=ZIP_ERRNO;\n\n    if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0))\n      err=ZIP_BADZIPFILE;\n\n    /* size of the central directory */\n    if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&size_central_dir)!=ZIP_OK)\n      err=ZIP_ERRNO;\n\n    /* offset of start of central directory with respect to the\n    starting disk number */\n    if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&offset_central_dir)!=ZIP_OK)\n      err=ZIP_ERRNO;\n\n    // TODO..\n    // read the comment from the standard central header.\n    size_comment = 0;\n  }\n  else\n  {\n    // Read End of central Directory info\n    if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)\n      err=ZIP_ERRNO;\n\n    /* the signature, already checked */\n    if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK)\n      err=ZIP_ERRNO;\n\n    /* number of this disk */\n    if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK)\n      err=ZIP_ERRNO;\n\n    /* number of the disk with the start of the central directory */\n    if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK)\n      err=ZIP_ERRNO;\n\n    /* total number of entries in the central dir on this disk */\n    number_entry = 0;\n    if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK)\n      err=ZIP_ERRNO;\n    else\n      number_entry = uL;\n\n    /* total number of entries in the central dir */\n    number_entry_CD = 0;\n    if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK)\n      err=ZIP_ERRNO;\n    else\n      number_entry_CD = uL;\n\n    if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0))\n      err=ZIP_BADZIPFILE;\n\n    /* size of the central directory */\n    size_central_dir = 0;\n    if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK)\n      err=ZIP_ERRNO;\n    else\n      size_central_dir = uL;\n\n    /* offset of start of central directory with respect to the starting disk number */\n    offset_central_dir = 0;\n    if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK)\n      err=ZIP_ERRNO;\n    else\n      offset_central_dir = uL;\n\n\n    /* zipfile global comment length */\n    if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &size_comment)!=ZIP_OK)\n      err=ZIP_ERRNO;\n  }\n\n  if ((central_pos<offset_central_dir+size_central_dir) &&\n    (err==ZIP_OK))\n    err=ZIP_BADZIPFILE;\n\n  if (err!=ZIP_OK)\n  {\n    ZCLOSE64(pziinit->z_filefunc, pziinit->filestream);\n    return ZIP_ERRNO;\n  }\n\n  if (size_comment>0)\n  {\n    pziinit->globalcomment = (char*)ALLOC(size_comment+1);\n    if (pziinit->globalcomment)\n    {\n      size_comment = ZREAD64(pziinit->z_filefunc, pziinit->filestream, pziinit->globalcomment,size_comment);\n      pziinit->globalcomment[size_comment]=0;\n    }\n  }\n\n  byte_before_the_zipfile = central_pos - (offset_central_dir+size_central_dir);\n  pziinit->add_position_when_writting_offset = byte_before_the_zipfile;\n\n  {\n    ZPOS64_T size_central_dir_to_read = size_central_dir;\n    size_t buf_size = SIZEDATA_INDATABLOCK;\n    void* buf_read = (void*)ALLOC(buf_size);\n    if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0)\n      err=ZIP_ERRNO;\n\n    while ((size_central_dir_to_read>0) && (err==ZIP_OK))\n    {\n      ZPOS64_T read_this = SIZEDATA_INDATABLOCK;\n      if (read_this > size_central_dir_to_read)\n        read_this = size_central_dir_to_read;\n\n      if (ZREAD64(pziinit->z_filefunc, pziinit->filestream,buf_read,(uLong)read_this) != read_this)\n        err=ZIP_ERRNO;\n\n      if (err==ZIP_OK)\n        err = add_data_in_datablock(&pziinit->central_dir,buf_read, (uLong)read_this);\n\n      size_central_dir_to_read-=read_this;\n    }\n    TRYFREE(buf_read);\n  }\n  pziinit->begin_pos = byte_before_the_zipfile;\n  pziinit->number_entry = number_entry_CD;\n\n  if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET) != 0)\n    err=ZIP_ERRNO;\n\n  return err;\n}\n\n\n#endif /* !NO_ADDFILEINEXISTINGZIP*/\n\n\n/************************************************************/\nextern zipFile ZEXPORT zipOpen3 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def)\n{\n    zip64_internal ziinit;\n    zip64_internal* zi;\n    int err=ZIP_OK;\n\n    ziinit.z_filefunc.zseek32_file = NULL;\n    ziinit.z_filefunc.ztell32_file = NULL;\n    if (pzlib_filefunc64_32_def==NULL)\n        fill_fopen64_filefunc(&ziinit.z_filefunc.zfile_func64);\n    else\n        ziinit.z_filefunc = *pzlib_filefunc64_32_def;\n\n    ziinit.filestream = ZOPEN64(ziinit.z_filefunc,\n                  pathname,\n                  (append == APPEND_STATUS_CREATE) ?\n                  (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) :\n                    (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING));\n\n    if (ziinit.filestream == NULL)\n        return NULL;\n\n    if (append == APPEND_STATUS_CREATEAFTER)\n        ZSEEK64(ziinit.z_filefunc,ziinit.filestream,0,SEEK_END);\n\n    ziinit.begin_pos = ZTELL64(ziinit.z_filefunc,ziinit.filestream);\n    ziinit.in_opened_file_inzip = 0;\n    ziinit.ci.stream_initialised = 0;\n    ziinit.number_entry = 0;\n    ziinit.add_position_when_writting_offset = 0;\n    init_linkedlist(&(ziinit.central_dir));\n\n\n\n    zi = (zip64_internal*)ALLOC(sizeof(zip64_internal));\n    if (zi==NULL)\n    {\n        ZCLOSE64(ziinit.z_filefunc,ziinit.filestream);\n        return NULL;\n    }\n\n    /* now we add file in a zipfile */\n#    ifndef NO_ADDFILEINEXISTINGZIP\n    ziinit.globalcomment = NULL;\n    if (append == APPEND_STATUS_ADDINZIP)\n    {\n      // Read and Cache Central Directory Records\n      err = LoadCentralDirectoryRecord(&ziinit);\n    }\n\n    if (globalcomment)\n    {\n      *globalcomment = ziinit.globalcomment;\n    }\n#    endif /* !NO_ADDFILEINEXISTINGZIP*/\n\n    if (err != ZIP_OK)\n    {\n#    ifndef NO_ADDFILEINEXISTINGZIP\n        TRYFREE(ziinit.globalcomment);\n#    endif /* !NO_ADDFILEINEXISTINGZIP*/\n        TRYFREE(zi);\n        return NULL;\n    }\n    else\n    {\n        *zi = ziinit;\n        return (zipFile)zi;\n    }\n}\n\nextern zipFile ZEXPORT zipOpen2 (const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def)\n{\n    if (pzlib_filefunc32_def != NULL)\n    {\n        zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;\n        fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def);\n        return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill);\n    }\n    else\n        return zipOpen3(pathname, append, globalcomment, NULL);\n}\n\nextern zipFile ZEXPORT zipOpen2_64 (const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def)\n{\n    if (pzlib_filefunc_def != NULL)\n    {\n        zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;\n        zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def;\n        zlib_filefunc64_32_def_fill.ztell32_file = NULL;\n        zlib_filefunc64_32_def_fill.zseek32_file = NULL;\n        return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill);\n    }\n    else\n        return zipOpen3(pathname, append, globalcomment, NULL);\n}\n\n\n\nextern zipFile ZEXPORT zipOpen (const char* pathname, int append)\n{\n    return zipOpen3((const void*)pathname,append,NULL,NULL);\n}\n\nextern zipFile ZEXPORT zipOpen64 (const void* pathname, int append)\n{\n    return zipOpen3(pathname,append,NULL,NULL);\n}\n\nint Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local)\n{\n  /* write the local header */\n  int err;\n  uInt size_filename = (uInt)strlen(filename);\n  uInt size_extrafield = size_extrafield_local;\n\n  err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC, 4);\n\n  if (err==ZIP_OK)\n  {\n    if(zi->ci.zip64)\n      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);/* version needed to extract */\n    else\n      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */\n  }\n\n  if (err==ZIP_OK)\n    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2);\n\n  if (err==ZIP_OK)\n    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2);\n\n  if (err==ZIP_OK)\n    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4);\n\n  // CRC / Compressed size / Uncompressed size will be filled in later and rewritten later\n  if (err==ZIP_OK)\n    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */\n  if (err==ZIP_OK)\n  {\n    if(zi->ci.zip64)\n      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* compressed size, unknown */\n    else\n      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */\n  }\n  if (err==ZIP_OK)\n  {\n    if(zi->ci.zip64)\n      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* uncompressed size, unknown */\n    else\n      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */\n  }\n\n  if (err==ZIP_OK)\n    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2);\n\n  if(zi->ci.zip64)\n  {\n    size_extrafield += 20;\n  }\n\n  if (err==ZIP_OK)\n    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield,2);\n\n  if ((err==ZIP_OK) && (size_filename > 0))\n  {\n    if (ZWRITE64(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename)\n      err = ZIP_ERRNO;\n  }\n\n  if ((err==ZIP_OK) && (size_extrafield_local > 0))\n  {\n    if (ZWRITE64(zi->z_filefunc, zi->filestream, extrafield_local, size_extrafield_local) != size_extrafield_local)\n      err = ZIP_ERRNO;\n  }\n\n\n  if ((err==ZIP_OK) && (zi->ci.zip64))\n  {\n      // write the Zip64 extended info\n      short HeaderID = 1;\n      short DataSize = 16;\n      ZPOS64_T CompressedSize = 0;\n      ZPOS64_T UncompressedSize = 0;\n\n      // Remember position of Zip64 extended info for the local file header. (needed when we update size after done with file)\n      zi->ci.pos_zip64extrainfo = ZTELL64(zi->z_filefunc,zi->filestream);\n\n      err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)HeaderID,2);\n      err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)DataSize,2);\n\n      err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)UncompressedSize,8);\n      err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)CompressedSize,8);\n  }\n\n  return err;\n}\n\n/*\n NOTE.\n When writing RAW the ZIP64 extended information in extrafield_local and extrafield_global needs to be stripped\n before calling this function it can be done with zipRemoveExtraInfoBlock\n\n It is not done here because then we need to realloc a new buffer since parameters are 'const' and I want to minimize\n unnecessary allocations.\n */\nextern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename, const zip_fileinfo* zipfi,\n                                         const void* extrafield_local, uInt size_extrafield_local,\n                                         const void* extrafield_global, uInt size_extrafield_global,\n                                         const char* comment, int method, int level, int raw,\n                                         int windowBits,int memLevel, int strategy,\n                                         const char* password, uLong crcForCrypting,\n                                         uLong versionMadeBy, uLong flagBase, int zip64)\n{\n    zip64_internal* zi;\n    uInt size_filename;\n    uInt size_comment;\n    uInt i;\n    int err = ZIP_OK;\n\n#    ifdef NOCRYPT\n    if (password != NULL)\n        return ZIP_PARAMERROR;\n#    endif\n\n    if (file == NULL)\n        return ZIP_PARAMERROR;\n\n#ifdef HAVE_BZIP2\n    if ((method!=0) && (method!=Z_DEFLATED) && (method!=Z_BZIP2ED))\n      return ZIP_PARAMERROR;\n#else\n    if ((method!=0) && (method!=Z_DEFLATED))\n      return ZIP_PARAMERROR;\n#endif\n\n    zi = (zip64_internal*)file;\n\n    if (zi->in_opened_file_inzip == 1)\n    {\n        err = zipCloseFileInZip (file);\n        if (err != ZIP_OK)\n            return err;\n    }\n\n    if (filename==NULL)\n        filename=\"-\";\n\n    if (comment==NULL)\n        size_comment = 0;\n    else\n        size_comment = (uInt)strlen(comment);\n\n    size_filename = (uInt)strlen(filename);\n\n    if (zipfi == NULL)\n        zi->ci.dosDate = 0;\n    else\n    {\n        if (zipfi->dosDate != 0)\n            zi->ci.dosDate = zipfi->dosDate;\n        else\n          zi->ci.dosDate = zip64local_TmzDateToDosDate(&zipfi->tmz_date);\n    }\n\n    zi->ci.flag = flagBase;\n    if ((level==8) || (level==9))\n      zi->ci.flag |= 2;\n    if (level==2)\n      zi->ci.flag |= 4;\n    if (level==1)\n      zi->ci.flag |= 6;\n    if (password != NULL)\n      zi->ci.flag |= 1;\n\n    zi->ci.crc32 = 0;\n    zi->ci.method = method;\n    zi->ci.encrypt = 0;\n    zi->ci.stream_initialised = 0;\n    zi->ci.pos_in_buffered_data = 0;\n    zi->ci.raw = raw;\n    zi->ci.pos_local_header = ZTELL64(zi->z_filefunc,zi->filestream);\n\n    zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + size_extrafield_global + size_comment;\n    zi->ci.size_centralExtraFree = 32; // Extra space we have reserved in case we need to add ZIP64 extra info data\n\n    zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader + zi->ci.size_centralExtraFree);\n\n    zi->ci.size_centralExtra = size_extrafield_global;\n    zip64local_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4);\n    /* version info */\n    zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)versionMadeBy,2);\n    zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2);\n    zip64local_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2);\n    zip64local_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2);\n    zip64local_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4);\n    zip64local_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/\n    zip64local_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/\n    zip64local_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/\n    zip64local_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2);\n    zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2);\n    zip64local_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2);\n    zip64local_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/\n\n    if (zipfi==NULL)\n        zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2);\n    else\n        zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2);\n\n    if (zipfi==NULL)\n        zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4);\n    else\n        zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4);\n\n    if(zi->ci.pos_local_header >= 0xffffffff)\n      zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)0xffffffff,4);\n    else\n      zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header - zi->add_position_when_writting_offset,4);\n\n    for (i=0;i<size_filename;i++)\n        *(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i);\n\n    for (i=0;i<size_extrafield_global;i++)\n        *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+i) =\n              *(((const char*)extrafield_global)+i);\n\n    for (i=0;i<size_comment;i++)\n        *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+\n              size_extrafield_global+i) = *(comment+i);\n    if (zi->ci.central_header == NULL)\n        return ZIP_INTERNALERROR;\n\n    zi->ci.zip64 = zip64;\n    zi->ci.totalCompressedData = 0;\n    zi->ci.totalUncompressedData = 0;\n    zi->ci.pos_zip64extrainfo = 0;\n\n    err = Write_LocalFileHeader(zi, filename, size_extrafield_local, extrafield_local);\n\n#ifdef HAVE_BZIP2\n    zi->ci.bstream.avail_in = (uInt)0;\n    zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE;\n    zi->ci.bstream.next_out = (char*)zi->ci.buffered_data;\n    zi->ci.bstream.total_in_hi32 = 0;\n    zi->ci.bstream.total_in_lo32 = 0;\n    zi->ci.bstream.total_out_hi32 = 0;\n    zi->ci.bstream.total_out_lo32 = 0;\n#endif\n\n    zi->ci.stream.avail_in = (uInt)0;\n    zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;\n    zi->ci.stream.next_out = zi->ci.buffered_data;\n    zi->ci.stream.total_in = 0;\n    zi->ci.stream.total_out = 0;\n    zi->ci.stream.data_type = Z_BINARY;\n\n#ifdef HAVE_BZIP2\n    if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED || zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw))\n#else\n    if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))\n#endif\n    {\n        if(zi->ci.method == Z_DEFLATED)\n        {\n          zi->ci.stream.zalloc = (alloc_func)0;\n          zi->ci.stream.zfree = (free_func)0;\n          zi->ci.stream.opaque = (voidpf)0;\n\n          if (windowBits>0)\n              windowBits = -windowBits;\n\n          err = deflateInit2(&zi->ci.stream, level, Z_DEFLATED, windowBits, memLevel, strategy);\n\n          if (err==Z_OK)\n              zi->ci.stream_initialised = Z_DEFLATED;\n        }\n        else if(zi->ci.method == Z_BZIP2ED)\n        {\n#ifdef HAVE_BZIP2\n            // Init BZip stuff here\n          zi->ci.bstream.bzalloc = 0;\n          zi->ci.bstream.bzfree = 0;\n          zi->ci.bstream.opaque = (voidpf)0;\n\n          err = BZ2_bzCompressInit(&zi->ci.bstream, level, 0,35);\n          if(err == BZ_OK)\n            zi->ci.stream_initialised = Z_BZIP2ED;\n#endif\n        }\n\n    }\n\n#    ifndef NOCRYPT\n    zi->ci.crypt_header_size = 0;\n    if ((err==Z_OK) && (password != NULL))\n    {\n        unsigned char bufHead[RAND_HEAD_LEN];\n        unsigned int sizeHead;\n        zi->ci.encrypt = 1;\n        zi->ci.pcrc_32_tab = get_crc_table();\n        /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/\n\n        sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting);\n        zi->ci.crypt_header_size = sizeHead;\n\n        if (ZWRITE64(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead)\n                err = ZIP_ERRNO;\n    }\n#    endif\n\n    if (err==Z_OK)\n        zi->in_opened_file_inzip = 1;\n    return err;\n}\n\nextern int ZEXPORT zipOpenNewFileInZip4 (zipFile file, const char* filename, const zip_fileinfo* zipfi,\n                                         const void* extrafield_local, uInt size_extrafield_local,\n                                         const void* extrafield_global, uInt size_extrafield_global,\n                                         const char* comment, int method, int level, int raw,\n                                         int windowBits,int memLevel, int strategy,\n                                         const char* password, uLong crcForCrypting,\n                                         uLong versionMadeBy, uLong flagBase)\n{\n    return zipOpenNewFileInZip4_64 (file, filename, zipfi,\n                                 extrafield_local, size_extrafield_local,\n                                 extrafield_global, size_extrafield_global,\n                                 comment, method, level, raw,\n                                 windowBits, memLevel, strategy,\n                                 password, crcForCrypting, versionMadeBy, flagBase, 0);\n}\n\nextern int ZEXPORT zipOpenNewFileInZip3 (zipFile file, const char* filename, const zip_fileinfo* zipfi,\n                                         const void* extrafield_local, uInt size_extrafield_local,\n                                         const void* extrafield_global, uInt size_extrafield_global,\n                                         const char* comment, int method, int level, int raw,\n                                         int windowBits,int memLevel, int strategy,\n                                         const char* password, uLong crcForCrypting)\n{\n    return zipOpenNewFileInZip4_64 (file, filename, zipfi,\n                                 extrafield_local, size_extrafield_local,\n                                 extrafield_global, size_extrafield_global,\n                                 comment, method, level, raw,\n                                 windowBits, memLevel, strategy,\n                                 password, crcForCrypting, VERSIONMADEBY, 0, 0);\n}\n\nextern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, const char* filename, const zip_fileinfo* zipfi,\n                                         const void* extrafield_local, uInt size_extrafield_local,\n                                         const void* extrafield_global, uInt size_extrafield_global,\n                                         const char* comment, int method, int level, int raw,\n                                         int windowBits,int memLevel, int strategy,\n                                         const char* password, uLong crcForCrypting, int zip64)\n{\n    return zipOpenNewFileInZip4_64 (file, filename, zipfi,\n                                 extrafield_local, size_extrafield_local,\n                                 extrafield_global, size_extrafield_global,\n                                 comment, method, level, raw,\n                                 windowBits, memLevel, strategy,\n                                 password, crcForCrypting, VERSIONMADEBY, 0, zip64);\n}\n\nextern int ZEXPORT zipOpenNewFileInZip2(zipFile file, const char* filename, const zip_fileinfo* zipfi,\n                                        const void* extrafield_local, uInt size_extrafield_local,\n                                        const void* extrafield_global, uInt size_extrafield_global,\n                                        const char* comment, int method, int level, int raw)\n{\n    return zipOpenNewFileInZip4_64 (file, filename, zipfi,\n                                 extrafield_local, size_extrafield_local,\n                                 extrafield_global, size_extrafield_global,\n                                 comment, method, level, raw,\n                                 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,\n                                 NULL, 0, VERSIONMADEBY, 0, 0);\n}\n\nextern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file, const char* filename, const zip_fileinfo* zipfi,\n                                        const void* extrafield_local, uInt size_extrafield_local,\n                                        const void* extrafield_global, uInt size_extrafield_global,\n                                        const char* comment, int method, int level, int raw, int zip64)\n{\n    return zipOpenNewFileInZip4_64 (file, filename, zipfi,\n                                 extrafield_local, size_extrafield_local,\n                                 extrafield_global, size_extrafield_global,\n                                 comment, method, level, raw,\n                                 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,\n                                 NULL, 0, VERSIONMADEBY, 0, zip64);\n}\n\nextern int ZEXPORT zipOpenNewFileInZip64 (zipFile file, const char* filename, const zip_fileinfo* zipfi,\n                                        const void* extrafield_local, uInt size_extrafield_local,\n                                        const void*extrafield_global, uInt size_extrafield_global,\n                                        const char* comment, int method, int level, int zip64)\n{\n    return zipOpenNewFileInZip4_64 (file, filename, zipfi,\n                                 extrafield_local, size_extrafield_local,\n                                 extrafield_global, size_extrafield_global,\n                                 comment, method, level, 0,\n                                 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,\n                                 NULL, 0, VERSIONMADEBY, 0, zip64);\n}\n\nextern int ZEXPORT zipOpenNewFileInZip (zipFile file, const char* filename, const zip_fileinfo* zipfi,\n                                        const void* extrafield_local, uInt size_extrafield_local,\n                                        const void*extrafield_global, uInt size_extrafield_global,\n                                        const char* comment, int method, int level)\n{\n    return zipOpenNewFileInZip4_64 (file, filename, zipfi,\n                                 extrafield_local, size_extrafield_local,\n                                 extrafield_global, size_extrafield_global,\n                                 comment, method, level, 0,\n                                 -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,\n                                 NULL, 0, VERSIONMADEBY, 0, 0);\n}\n\nlocal int zip64FlushWriteBuffer(zip64_internal* zi)\n{\n    int err=ZIP_OK;\n\n    if (zi->ci.encrypt != 0)\n    {\n#ifndef NOCRYPT\n        uInt i;\n        int t;\n        for (i=0;i<zi->ci.pos_in_buffered_data;i++)\n            zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab, zi->ci.buffered_data[i],t);\n#endif\n    }\n\n    if (ZWRITE64(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data) != zi->ci.pos_in_buffered_data)\n      err = ZIP_ERRNO;\n\n    zi->ci.totalCompressedData += zi->ci.pos_in_buffered_data;\n\n#ifdef HAVE_BZIP2\n    if(zi->ci.method == Z_BZIP2ED)\n    {\n      zi->ci.totalUncompressedData += zi->ci.bstream.total_in_lo32;\n      zi->ci.bstream.total_in_lo32 = 0;\n      zi->ci.bstream.total_in_hi32 = 0;\n    }\n    else\n#endif\n    {\n      zi->ci.totalUncompressedData += zi->ci.stream.total_in;\n      zi->ci.stream.total_in = 0;\n    }\n\n\n    zi->ci.pos_in_buffered_data = 0;\n\n    return err;\n}\n\nextern int ZEXPORT zipWriteInFileInZip (zipFile file,const void* buf,unsigned int len)\n{\n    zip64_internal* zi;\n    int err=ZIP_OK;\n\n    if (file == NULL)\n        return ZIP_PARAMERROR;\n    zi = (zip64_internal*)file;\n\n    if (zi->in_opened_file_inzip == 0)\n        return ZIP_PARAMERROR;\n\n    zi->ci.crc32 = crc32(zi->ci.crc32,buf,(uInt)len);\n\n#ifdef HAVE_BZIP2\n    if(zi->ci.method == Z_BZIP2ED && (!zi->ci.raw))\n    {\n      zi->ci.bstream.next_in = (void*)buf;\n      zi->ci.bstream.avail_in = len;\n      err = BZ_RUN_OK;\n\n      while ((err==BZ_RUN_OK) && (zi->ci.bstream.avail_in>0))\n      {\n        if (zi->ci.bstream.avail_out == 0)\n        {\n          if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)\n            err = ZIP_ERRNO;\n          zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE;\n          zi->ci.bstream.next_out = (char*)zi->ci.buffered_data;\n        }\n\n\n        if(err != BZ_RUN_OK)\n          break;\n\n        if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw))\n        {\n          uLong uTotalOutBefore_lo = zi->ci.bstream.total_out_lo32;\n//          uLong uTotalOutBefore_hi = zi->ci.bstream.total_out_hi32;\n          err=BZ2_bzCompress(&zi->ci.bstream,  BZ_RUN);\n\n          zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore_lo) ;\n        }\n      }\n\n      if(err == BZ_RUN_OK)\n        err = ZIP_OK;\n    }\n    else\n#endif\n    {\n      zi->ci.stream.next_in = (Bytef*)buf;\n      zi->ci.stream.avail_in = len;\n\n      while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0))\n      {\n          if (zi->ci.stream.avail_out == 0)\n          {\n              if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)\n                  err = ZIP_ERRNO;\n              zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;\n              zi->ci.stream.next_out = zi->ci.buffered_data;\n          }\n\n\n          if(err != ZIP_OK)\n              break;\n\n          if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))\n          {\n              uLong uTotalOutBefore = zi->ci.stream.total_out;\n              err=deflate(&zi->ci.stream,  Z_NO_FLUSH);\n              if(uTotalOutBefore > zi->ci.stream.total_out)\n              {\n                int bBreak = 0;\n                bBreak++;\n              }\n\n              zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;\n          }\n          else\n          {\n              uInt copy_this,i;\n              if (zi->ci.stream.avail_in < zi->ci.stream.avail_out)\n                  copy_this = zi->ci.stream.avail_in;\n              else\n                  copy_this = zi->ci.stream.avail_out;\n\n              for (i = 0; i < copy_this; i++)\n                  *(((char*)zi->ci.stream.next_out)+i) =\n                      *(((const char*)zi->ci.stream.next_in)+i);\n              {\n                  zi->ci.stream.avail_in -= copy_this;\n                  zi->ci.stream.avail_out-= copy_this;\n                  zi->ci.stream.next_in+= copy_this;\n                  zi->ci.stream.next_out+= copy_this;\n                  zi->ci.stream.total_in+= copy_this;\n                  zi->ci.stream.total_out+= copy_this;\n                  zi->ci.pos_in_buffered_data += copy_this;\n              }\n          }\n      }// while(...)\n    }\n\n    return err;\n}\n\nextern int ZEXPORT zipCloseFileInZipRaw (zipFile file, uLong uncompressed_size, uLong crc32)\n{\n    return zipCloseFileInZipRaw64 (file, uncompressed_size, crc32);\n}\n\nextern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_size, uLong crc32)\n{\n    zip64_internal* zi;\n    ZPOS64_T compressed_size;\n    uLong invalidValue = 0xffffffff;\n    short datasize = 0;\n    int err=ZIP_OK;\n\n    if (file == NULL)\n        return ZIP_PARAMERROR;\n    zi = (zip64_internal*)file;\n\n    if (zi->in_opened_file_inzip == 0)\n        return ZIP_PARAMERROR;\n    zi->ci.stream.avail_in = 0;\n\n    if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))\n                {\n                        while (err==ZIP_OK)\n                        {\n                                uLong uTotalOutBefore;\n                                if (zi->ci.stream.avail_out == 0)\n                                {\n                                        if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)\n                                                err = ZIP_ERRNO;\n                                        zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;\n                                        zi->ci.stream.next_out = zi->ci.buffered_data;\n                                }\n                                uTotalOutBefore = zi->ci.stream.total_out;\n                                err=deflate(&zi->ci.stream,  Z_FINISH);\n                                zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;\n                        }\n                }\n    else if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw))\n    {\n#ifdef HAVE_BZIP2\n      err = BZ_FINISH_OK;\n      while (err==BZ_FINISH_OK)\n      {\n        uLong uTotalOutBefore;\n        if (zi->ci.bstream.avail_out == 0)\n        {\n          if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)\n            err = ZIP_ERRNO;\n          zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE;\n          zi->ci.bstream.next_out = (char*)zi->ci.buffered_data;\n        }\n        uTotalOutBefore = zi->ci.bstream.total_out_lo32;\n        err=BZ2_bzCompress(&zi->ci.bstream,  BZ_FINISH);\n        if(err == BZ_STREAM_END)\n          err = Z_STREAM_END;\n\n        zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore);\n      }\n\n      if(err == BZ_FINISH_OK)\n        err = ZIP_OK;\n#endif\n    }\n\n    if (err==Z_STREAM_END)\n        err=ZIP_OK; /* this is normal */\n\n    if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK))\n                {\n        if (zip64FlushWriteBuffer(zi)==ZIP_ERRNO)\n            err = ZIP_ERRNO;\n                }\n\n    if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))\n    {\n        int tmp_err = deflateEnd(&zi->ci.stream);\n        if (err == ZIP_OK)\n            err = tmp_err;\n        zi->ci.stream_initialised = 0;\n    }\n#ifdef HAVE_BZIP2\n    else if((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw))\n    {\n      int tmperr = BZ2_bzCompressEnd(&zi->ci.bstream);\n                        if (err==ZIP_OK)\n                                err = tmperr;\n                        zi->ci.stream_initialised = 0;\n    }\n#endif\n\n    if (!zi->ci.raw)\n    {\n        crc32 = (uLong)zi->ci.crc32;\n        uncompressed_size = zi->ci.totalUncompressedData;\n    }\n    compressed_size = zi->ci.totalCompressedData;\n\n#    ifndef NOCRYPT\n    compressed_size += zi->ci.crypt_header_size;\n#    endif\n\n    // update Current Item crc and sizes,\n    if(compressed_size >= 0xffffffff || uncompressed_size >= 0xffffffff || zi->ci.pos_local_header >= 0xffffffff)\n    {\n      /*version Made by*/\n      zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)45,2);\n      /*version needed*/\n      zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)45,2);\n\n    }\n\n    zip64local_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/\n\n\n    if(compressed_size >= 0xffffffff)\n      zip64local_putValue_inmemory(zi->ci.central_header+20, invalidValue,4); /*compr size*/\n    else\n      zip64local_putValue_inmemory(zi->ci.central_header+20, compressed_size,4); /*compr size*/\n\n    /// set internal file attributes field\n    if (zi->ci.stream.data_type == Z_ASCII)\n        zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2);\n\n    if(uncompressed_size >= 0xffffffff)\n      zip64local_putValue_inmemory(zi->ci.central_header+24, invalidValue,4); /*uncompr size*/\n    else\n      zip64local_putValue_inmemory(zi->ci.central_header+24, uncompressed_size,4); /*uncompr size*/\n\n    // Add ZIP64 extra info field for uncompressed size\n    if(uncompressed_size >= 0xffffffff)\n      datasize += 8;\n\n    // Add ZIP64 extra info field for compressed size\n    if(compressed_size >= 0xffffffff)\n      datasize += 8;\n\n    // Add ZIP64 extra info field for relative offset to local file header of current file\n    if(zi->ci.pos_local_header >= 0xffffffff)\n      datasize += 8;\n\n    if(datasize > 0)\n    {\n      char* p = NULL;\n\n      if((uLong)(datasize + 4) > zi->ci.size_centralExtraFree)\n      {\n        // we can not write more data to the buffer that we have room for.\n        return ZIP_BADZIPFILE;\n      }\n\n      p = zi->ci.central_header + zi->ci.size_centralheader;\n\n      // Add Extra Information Header for 'ZIP64 information'\n      zip64local_putValue_inmemory(p, 0x0001, 2); // HeaderID\n      p += 2;\n      zip64local_putValue_inmemory(p, datasize, 2); // DataSize\n      p += 2;\n\n      if(uncompressed_size >= 0xffffffff)\n      {\n        zip64local_putValue_inmemory(p, uncompressed_size, 8);\n        p += 8;\n      }\n\n      if(compressed_size >= 0xffffffff)\n      {\n        zip64local_putValue_inmemory(p, compressed_size, 8);\n        p += 8;\n      }\n\n      if(zi->ci.pos_local_header >= 0xffffffff)\n      {\n        zip64local_putValue_inmemory(p, zi->ci.pos_local_header, 8);\n        p += 8;\n      }\n\n      // Update how much extra free space we got in the memory buffer\n      // and increase the centralheader size so the new ZIP64 fields are included\n      // ( 4 below is the size of HeaderID and DataSize field )\n      zi->ci.size_centralExtraFree -= datasize + 4;\n      zi->ci.size_centralheader += datasize + 4;\n\n      // Update the extra info size field\n      zi->ci.size_centralExtra += datasize + 4;\n      zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)zi->ci.size_centralExtra,2);\n    }\n\n    if (err==ZIP_OK)\n        err = add_data_in_datablock(&zi->central_dir, zi->ci.central_header, (uLong)zi->ci.size_centralheader);\n\n    free(zi->ci.central_header);\n\n    if (err==ZIP_OK)\n    {\n        // Update the LocalFileHeader with the new values.\n\n        ZPOS64_T cur_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream);\n\n        if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0)\n            err = ZIP_ERRNO;\n\n        if (err==ZIP_OK)\n            err = zip64local_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */\n\n        if(uncompressed_size >= 0xffffffff)\n        {\n          if(zi->ci.pos_zip64extrainfo > 0)\n          {\n            // Update the size in the ZIP64 extended field.\n            if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_zip64extrainfo + 4,ZLIB_FILEFUNC_SEEK_SET)!=0)\n              err = ZIP_ERRNO;\n\n            if (err==ZIP_OK) /* compressed size, unknown */\n              err = zip64local_putValue(&zi->z_filefunc, zi->filestream, uncompressed_size, 8);\n\n            if (err==ZIP_OK) /* uncompressed size, unknown */\n              err = zip64local_putValue(&zi->z_filefunc, zi->filestream, compressed_size, 8);\n          }\n        }\n        else\n        {\n          if (err==ZIP_OK) /* compressed size, unknown */\n              err = zip64local_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4);\n\n          if (err==ZIP_OK) /* uncompressed size, unknown */\n              err = zip64local_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4);\n        }\n\n        if (ZSEEK64(zi->z_filefunc,zi->filestream, cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0)\n            err = ZIP_ERRNO;\n    }\n\n    zi->number_entry ++;\n    zi->in_opened_file_inzip = 0;\n\n    return err;\n}\n\nextern int ZEXPORT zipCloseFileInZip (zipFile file)\n{\n    return zipCloseFileInZipRaw (file,0,0);\n}\n\nint Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip)\n{\n  int err = ZIP_OK;\n  ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writting_offset;\n\n  err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDLOCHEADERMAGIC,4);\n\n  /*num disks*/\n    if (err==ZIP_OK) /* number of the disk with the start of the central directory */\n      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4);\n\n  /*relative offset*/\n    if (err==ZIP_OK) /* Relative offset to the Zip64EndOfCentralDirectory */\n      err = zip64local_putValue(&zi->z_filefunc,zi->filestream, pos,8);\n\n  /*total disks*/ /* Do not support spawning of disk so always say 1 here*/\n    if (err==ZIP_OK) /* number of the disk with the start of the central directory */\n      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)1,4);\n\n    return err;\n}\n\nint Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip)\n{\n  int err = ZIP_OK;\n\n  uLong Zip64DataSize = 44;\n\n  err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDHEADERMAGIC,4);\n\n  if (err==ZIP_OK) /* size of this 'zip64 end of central directory' */\n    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)Zip64DataSize,8); // why ZPOS64_T of this ?\n\n  if (err==ZIP_OK) /* version made by */\n    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);\n\n  if (err==ZIP_OK) /* version needed */\n    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);\n\n  if (err==ZIP_OK) /* number of this disk */\n    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4);\n\n  if (err==ZIP_OK) /* number of the disk with the start of the central directory */\n    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4);\n\n  if (err==ZIP_OK) /* total number of entries in the central dir on this disk */\n    err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8);\n\n  if (err==ZIP_OK) /* total number of entries in the central dir */\n    err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8);\n\n  if (err==ZIP_OK) /* size of the central directory */\n    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)size_centraldir,8);\n\n  if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */\n  {\n    ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writting_offset;\n    err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (ZPOS64_T)pos,8);\n  }\n  return err;\n}\nint Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip)\n{\n  int err = ZIP_OK;\n\n  /*signature*/\n  err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4);\n\n  if (err==ZIP_OK) /* number of this disk */\n    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);\n\n  if (err==ZIP_OK) /* number of the disk with the start of the central directory */\n    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);\n\n  if (err==ZIP_OK) /* total number of entries in the central dir on this disk */\n  {\n    {\n      if(zi->number_entry >= 0xFFFF)\n        err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record\n      else\n        err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);\n    }\n  }\n\n  if (err==ZIP_OK) /* total number of entries in the central dir */\n  {\n    if(zi->number_entry >= 0xFFFF)\n      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record\n    else\n      err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);\n  }\n\n  if (err==ZIP_OK) /* size of the central directory */\n    err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4);\n\n  if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */\n  {\n    ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writting_offset;\n    if(pos >= 0xffffffff)\n    {\n      err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)0xffffffff,4);\n    }\n    else\n                  err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4);\n  }\n\n   return err;\n}\n\nint Write_GlobalComment(zip64_internal* zi, const char* global_comment)\n{\n  int err = ZIP_OK;\n  uInt size_global_comment = 0;\n\n  if(global_comment != NULL)\n    size_global_comment = (uInt)strlen(global_comment);\n\n  err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2);\n\n  if (err == ZIP_OK && size_global_comment > 0)\n  {\n    if (ZWRITE64(zi->z_filefunc,zi->filestream, global_comment, size_global_comment) != size_global_comment)\n      err = ZIP_ERRNO;\n  }\n  return err;\n}\n\nextern int ZEXPORT zipClose (zipFile file, const char* global_comment)\n{\n    zip64_internal* zi;\n    int err = 0;\n    uLong size_centraldir = 0;\n    ZPOS64_T centraldir_pos_inzip;\n    ZPOS64_T pos;\n\n    if (file == NULL)\n        return ZIP_PARAMERROR;\n\n    zi = (zip64_internal*)file;\n\n    if (zi->in_opened_file_inzip == 1)\n    {\n        err = zipCloseFileInZip (file);\n    }\n\n#ifndef NO_ADDFILEINEXISTINGZIP\n    if (global_comment==NULL)\n        global_comment = zi->globalcomment;\n#endif\n\n    centraldir_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream);\n\n    if (err==ZIP_OK)\n    {\n        linkedlist_datablock_internal* ldi = zi->central_dir.first_block;\n        while (ldi!=NULL)\n        {\n            if ((err==ZIP_OK) && (ldi->filled_in_this_block>0))\n            {\n                if (ZWRITE64(zi->z_filefunc,zi->filestream, ldi->data, ldi->filled_in_this_block) != ldi->filled_in_this_block)\n                    err = ZIP_ERRNO;\n            }\n\n            size_centraldir += ldi->filled_in_this_block;\n            ldi = ldi->next_datablock;\n        }\n    }\n    free_linkedlist(&(zi->central_dir));\n\n    pos = centraldir_pos_inzip - zi->add_position_when_writting_offset;\n    if(pos >= 0xffffffff)\n    {\n      ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream);\n      Write_Zip64EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip);\n\n      Write_Zip64EndOfCentralDirectoryLocator(zi, Zip64EOCDpos);\n    }\n\n    if (err==ZIP_OK)\n      err = Write_EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip);\n\n    if(err == ZIP_OK)\n      err = Write_GlobalComment(zi, global_comment);\n\n    if (ZCLOSE64(zi->z_filefunc,zi->filestream) != 0)\n        if (err == ZIP_OK)\n            err = ZIP_ERRNO;\n\n#ifndef NO_ADDFILEINEXISTINGZIP\n    TRYFREE(zi->globalcomment);\n#endif\n    TRYFREE(zi);\n\n    return err;\n}\n\nextern int ZEXPORT zipRemoveExtraInfoBlock (char* pData, int* dataLen, short sHeader)\n{\n  char* p = pData;\n  int size = 0;\n  char* pNewHeader;\n  char* pTmp;\n  short header;\n  short dataSize;\n\n  int retVal = ZIP_OK;\n\n  if(pData == NULL || *dataLen < 4)\n    return ZIP_PARAMERROR;\n\n  pNewHeader = (char*)ALLOC(*dataLen);\n  pTmp = pNewHeader;\n\n  while(p < (pData + *dataLen))\n  {\n    header = *(short*)p;\n    dataSize = *(((short*)p)+1);\n\n    if( header == sHeader ) // Header found.\n    {\n      p += dataSize + 4; // skip it. do not copy to temp buffer\n    }\n    else\n    {\n      // Extra Info block should not be removed, So copy it to the temp buffer.\n      memcpy(pTmp, p, dataSize + 4);\n      p += dataSize + 4;\n      size += dataSize + 4;\n    }\n\n  }\n\n  if(size < *dataLen)\n  {\n    // clean old extra info block.\n    memset(pData,0, *dataLen);\n\n    // copy the new extra info block over the old\n    if(size > 0)\n      memcpy(pData, pNewHeader, size);\n\n    // set the new extra info size\n    *dataLen = size;\n\n    retVal = ZIP_OK;\n  }\n  else\n    retVal = ZIP_ERRNO;\n\n  TRYFREE(pNewHeader);\n\n  return retVal;\n}\n"
  },
  {
    "path": "Loader/libs/minizip/zip.h",
    "content": "/* zip.h -- IO on .zip files using zlib\n   Version 1.1, February 14h, 2010\n   part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )\n\n         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )\n\n         Modifications for Zip64 support\n         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )\n\n         For more info read MiniZip_info.txt\n\n         ---------------------------------------------------------------------------\n\n   Condition of use and distribution are the same than zlib :\n\n  This software is provided 'as-is', without any express or implied\n  warranty.  In no event will the authors be held liable for any damages\n  arising from the use of this software.\n\n  Permission is granted to anyone to use this software for any purpose,\n  including commercial applications, and to alter it and redistribute it\n  freely, subject to the following restrictions:\n\n  1. The origin of this software must not be misrepresented; you must not\n     claim that you wrote the original software. If you use this software\n     in a product, an acknowledgment in the product documentation would be\n     appreciated but is not required.\n  2. Altered source versions must be plainly marked as such, and must not be\n     misrepresented as being the original software.\n  3. This notice may not be removed or altered from any source distribution.\n\n        ---------------------------------------------------------------------------\n\n        Changes\n\n        See header of zip.h\n\n*/\n\n#ifndef _zip12_H\n#define _zip12_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n//#define HAVE_BZIP2\n\n#ifndef _ZLIB_H\n#include \"zlib.h\"\n#endif\n\n#ifndef _ZLIBIOAPI_H\n#include \"ioapi.h\"\n#endif\n\n#ifdef HAVE_BZIP2\n#include \"bzlib.h\"\n#endif\n\n#define Z_BZIP2ED 12\n\n#if defined(STRICTZIP) || defined(STRICTZIPUNZIP)\n/* like the STRICT of WIN32, we define a pointer that cannot be converted\n    from (void*) without cast */\ntypedef struct TagzipFile__ { int unused; } zipFile__;\ntypedef zipFile__ *zipFile;\n#else\ntypedef voidp zipFile;\n#endif\n\n#define ZIP_OK                          (0)\n#define ZIP_EOF                         (0)\n#define ZIP_ERRNO                       (Z_ERRNO)\n#define ZIP_PARAMERROR                  (-102)\n#define ZIP_BADZIPFILE                  (-103)\n#define ZIP_INTERNALERROR               (-104)\n\n#ifndef DEF_MEM_LEVEL\n#  if MAX_MEM_LEVEL >= 8\n#    define DEF_MEM_LEVEL 8\n#  else\n#    define DEF_MEM_LEVEL  MAX_MEM_LEVEL\n#  endif\n#endif\n/* default memLevel */\n\n/* tm_zip contain date/time info */\ntypedef struct tm_zip_s\n{\n    uInt tm_sec;            /* seconds after the minute - [0,59] */\n    uInt tm_min;            /* minutes after the hour - [0,59] */\n    uInt tm_hour;           /* hours since midnight - [0,23] */\n    uInt tm_mday;           /* day of the month - [1,31] */\n    uInt tm_mon;            /* months since January - [0,11] */\n    uInt tm_year;           /* years - [1980..2044] */\n} tm_zip;\n\ntypedef struct\n{\n    tm_zip      tmz_date;       /* date in understandable format           */\n    uLong       dosDate;       /* if dos_date == 0, tmu_date is used      */\n/*    uLong       flag;        */   /* general purpose bit flag        2 bytes */\n\n    uLong       internal_fa;    /* internal file attributes        2 bytes */\n    uLong       external_fa;    /* external file attributes        4 bytes */\n} zip_fileinfo;\n\ntypedef const char* zipcharpc;\n\n\n#define APPEND_STATUS_CREATE        (0)\n#define APPEND_STATUS_CREATEAFTER   (1)\n#define APPEND_STATUS_ADDINZIP      (2)\n\nextern zipFile ZEXPORT zipOpen OF((const char *pathname, int append));\nextern zipFile ZEXPORT zipOpen64 OF((const void *pathname, int append));\n/*\n  Create a zipfile.\n     pathname contain on Windows XP a filename like \"c:\\\\zlib\\\\zlib113.zip\" or on\n       an Unix computer \"zlib/zlib113.zip\".\n     if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip\n       will be created at the end of the file.\n         (useful if the file contain a self extractor code)\n     if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will\n       add files in existing zip (be sure you don't add file that doesn't exist)\n     If the zipfile cannot be opened, the return value is NULL.\n     Else, the return value is a zipFile Handle, usable with other function\n       of this zip package.\n*/\n\n/* Note : there is no delete function into a zipfile.\n   If you want delete file into a zipfile, you must open a zipfile, and create another\n   Of couse, you can use RAW reading and writing to copy the file you did not want delte\n*/\n\nextern zipFile ZEXPORT zipOpen2 OF((const char *pathname,\n                                   int append,\n                                   zipcharpc* globalcomment,\n                                   zlib_filefunc_def* pzlib_filefunc_def));\n\nextern zipFile ZEXPORT zipOpen2_64 OF((const void *pathname,\n                                   int append,\n                                   zipcharpc* globalcomment,\n                                   zlib_filefunc64_def* pzlib_filefunc_def));\n\nextern int ZEXPORT zipOpenNewFileInZip OF((zipFile file,\n                       const char* filename,\n                       const zip_fileinfo* zipfi,\n                       const void* extrafield_local,\n                       uInt size_extrafield_local,\n                       const void* extrafield_global,\n                       uInt size_extrafield_global,\n                       const char* comment,\n                       int method,\n                       int level));\n\nextern int ZEXPORT zipOpenNewFileInZip64 OF((zipFile file,\n                       const char* filename,\n                       const zip_fileinfo* zipfi,\n                       const void* extrafield_local,\n                       uInt size_extrafield_local,\n                       const void* extrafield_global,\n                       uInt size_extrafield_global,\n                       const char* comment,\n                       int method,\n                       int level,\n                       int zip64));\n\n/*\n  Open a file in the ZIP for writing.\n  filename : the filename in zip (if NULL, '-' without quote will be used\n  *zipfi contain supplemental information\n  if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local\n    contains the extrafield data the the local header\n  if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global\n    contains the extrafield data the the local header\n  if comment != NULL, comment contain the comment string\n  method contain the compression method (0 for store, Z_DEFLATED for deflate)\n  level contain the level of compression (can be Z_DEFAULT_COMPRESSION)\n  zip64 is set to 1 if a zip64 extended information block should be added to the local file header.\n                    this MUST be '1' if the uncompressed size is >= 0xffffffff.\n\n*/\n\n\nextern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file,\n                                            const char* filename,\n                                            const zip_fileinfo* zipfi,\n                                            const void* extrafield_local,\n                                            uInt size_extrafield_local,\n                                            const void* extrafield_global,\n                                            uInt size_extrafield_global,\n                                            const char* comment,\n                                            int method,\n                                            int level,\n                                            int raw));\n\n\nextern int ZEXPORT zipOpenNewFileInZip2_64 OF((zipFile file,\n                                            const char* filename,\n                                            const zip_fileinfo* zipfi,\n                                            const void* extrafield_local,\n                                            uInt size_extrafield_local,\n                                            const void* extrafield_global,\n                                            uInt size_extrafield_global,\n                                            const char* comment,\n                                            int method,\n                                            int level,\n                                            int raw,\n                                            int zip64));\n/*\n  Same than zipOpenNewFileInZip, except if raw=1, we write raw file\n */\n\nextern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file,\n                                            const char* filename,\n                                            const zip_fileinfo* zipfi,\n                                            const void* extrafield_local,\n                                            uInt size_extrafield_local,\n                                            const void* extrafield_global,\n                                            uInt size_extrafield_global,\n                                            const char* comment,\n                                            int method,\n                                            int level,\n                                            int raw,\n                                            int windowBits,\n                                            int memLevel,\n                                            int strategy,\n                                            const char* password,\n                                            uLong crcForCrypting));\n\nextern int ZEXPORT zipOpenNewFileInZip3_64 OF((zipFile file,\n                                            const char* filename,\n                                            const zip_fileinfo* zipfi,\n                                            const void* extrafield_local,\n                                            uInt size_extrafield_local,\n                                            const void* extrafield_global,\n                                            uInt size_extrafield_global,\n                                            const char* comment,\n                                            int method,\n                                            int level,\n                                            int raw,\n                                            int windowBits,\n                                            int memLevel,\n                                            int strategy,\n                                            const char* password,\n                                            uLong crcForCrypting,\n                                            int zip64\n                                            ));\n\n/*\n  Same than zipOpenNewFileInZip2, except\n    windowBits,memLevel,,strategy : see parameter strategy in deflateInit2\n    password : crypting password (NULL for no crypting)\n    crcForCrypting : crc of file to compress (needed for crypting)\n */\n\nextern int ZEXPORT zipOpenNewFileInZip4 OF((zipFile file,\n                                            const char* filename,\n                                            const zip_fileinfo* zipfi,\n                                            const void* extrafield_local,\n                                            uInt size_extrafield_local,\n                                            const void* extrafield_global,\n                                            uInt size_extrafield_global,\n                                            const char* comment,\n                                            int method,\n                                            int level,\n                                            int raw,\n                                            int windowBits,\n                                            int memLevel,\n                                            int strategy,\n                                            const char* password,\n                                            uLong crcForCrypting,\n                                            uLong versionMadeBy,\n                                            uLong flagBase\n                                            ));\n\n\nextern int ZEXPORT zipOpenNewFileInZip4_64 OF((zipFile file,\n                                            const char* filename,\n                                            const zip_fileinfo* zipfi,\n                                            const void* extrafield_local,\n                                            uInt size_extrafield_local,\n                                            const void* extrafield_global,\n                                            uInt size_extrafield_global,\n                                            const char* comment,\n                                            int method,\n                                            int level,\n                                            int raw,\n                                            int windowBits,\n                                            int memLevel,\n                                            int strategy,\n                                            const char* password,\n                                            uLong crcForCrypting,\n                                            uLong versionMadeBy,\n                                            uLong flagBase,\n                                            int zip64\n                                            ));\n/*\n  Same than zipOpenNewFileInZip4, except\n    versionMadeBy : value for Version made by field\n    flag : value for flag field (compression level info will be added)\n */\n\n\nextern int ZEXPORT zipWriteInFileInZip OF((zipFile file,\n                       const void* buf,\n                       unsigned len));\n/*\n  Write data in the zipfile\n*/\n\nextern int ZEXPORT zipCloseFileInZip OF((zipFile file));\n/*\n  Close the current file in the zipfile\n*/\n\nextern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file,\n                                            uLong uncompressed_size,\n                                            uLong crc32));\n\nextern int ZEXPORT zipCloseFileInZipRaw64 OF((zipFile file,\n                                            ZPOS64_T uncompressed_size,\n                                            uLong crc32));\n\n/*\n  Close the current file in the zipfile, for file opened with\n    parameter raw=1 in zipOpenNewFileInZip2\n  uncompressed_size and crc32 are value for the uncompressed size\n*/\n\nextern int ZEXPORT zipClose OF((zipFile file,\n                const char* global_comment));\n/*\n  Close the zipfile\n*/\n\n\nextern int ZEXPORT zipRemoveExtraInfoBlock OF((char* pData, int* dataLen, short sHeader));\n/*\n  zipRemoveExtraInfoBlock -  Added by Mathias Svensson\n\n  Remove extra information block from a extra information data for the local file header or central directory header\n\n  It is needed to remove ZIP64 extra information blocks when before data is written if using RAW mode.\n\n  0x0001 is the signature header for the ZIP64 extra information blocks\n\n  usage.\n                        Remove ZIP64 Extra information from a central director extra field data\n              zipRemoveExtraInfoBlock(pCenDirExtraFieldData, &nCenDirExtraFieldDataLen, 0x0001);\n\n                        Remove ZIP64 Extra information from a Local File Header extra field data\n        zipRemoveExtraInfoBlock(pLocalHeaderExtraFieldData, &nLocalHeaderExtraFieldDataLen, 0x0001);\n*/\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif /* _zip64_H */\n"
  },
  {
    "path": "Loader/tools/packer.php",
    "content": "<?php \n\nconst PRIVATE_KEY = <<<EOD\n-----BEGIN RSA PRIVATE KEY-----\nMIICXwIBAAKBgQC+1xcYsEE+ab/Ame1/HHAgfBRhD67I9mBYCiOJqC3lJX5RKFvt\nOTcF5Sf5Bz3NL/2QWPLu40+yt4EvjZ3HOUAHrVgo2Fjo4vpaRoEaEtaccOziPH/A\nSScOfL+uppNGOa0glTCZLKVZI3Go8zoutr8VDw2dNT7rDM/4TvPjwMYd3QIDAQAB\nAoGBAL7C9n1hQfaHcnut4i8bWCHApgZXzNlpHekjSV7C1A2oKtopQ6qfdJbZ99kA\nGhDPFeGCaGPOqM32jJXiM4L/gTXxdaZMlthVgxQRqrnGkh4NqPQLAYo0qgb21TsY\nRE2BXdSET1E8WbGWjZ4508Jx6TNtTaSJJlgsSnqVibJHAEyBAkEA3i/+jif6KKVm\nQ0aS0TJIPCOjp2fmBfke27j/BdC2wJ5Arp1VO+sgKM8qJqaoOUCv+z08WGyIostF\noOfRiGF9DQJBANvh3WQkbIjAgVrWoasHI54S7lz8kkeqKJ30LdIUK/1I9+rf3iy5\nYvSmrnH4VnTx4XfxemKfF+HQNnlqcf1sEBECQQCbidGTRl0S0yaRdfgVRjPXFcPc\nzxjxmYGGoyyzr3YfxSjWlAE03tY2ez+wqv4chjIrmKSD6gaEn/PwPhgqdsSJAkEA\nnRoW3ZsstNSeV7Hsls8mAqZSCrwnI+8O0DSLnILvHyxIfldvXZMjgdup3iJqW2oL\nB3DQWbCEFsJ2eW+1fDT+kQJBANUUbnJNJtrUMK013eEIWwgXLk7cnJ71CkhtnVUP\n6sK44uktZ2a6YSkpmcRPgniy6McUR8g58ZgMeXn5OUv91lU=\n-----END RSA PRIVATE KEY-----\nEOD;\n\n$files = \"\";\n$zipFile = \"script.zip\";\n$finalFile = \"v1\";\nfor ($i = 1; $i < count($argv); $i ++) {\n    if ($argv[$i] == '-o') {\n        $finalFile = $argv[$i + 1];\n        break;\n    }\n    $files .= $argv[$i] . \" \";\n}\n\nif (!empty($files)) {\n\n    //compress files\n    echo system(\"zip $zipFile $files\"); \n\n    //get and encrypt zip file's md5\n    $zipFileMD5 = md5_file($zipFile);\n    $private_key = openssl_pkey_get_private(PRIVATE_KEY);\n    $ret = openssl_private_encrypt($zipFileMD5, $encrypted, $private_key);\n\n    if (!$ret || empty($encrypted)) {\n        unlink($zipFile);\n        echo \"fail to encrypt file md5\";\n    }\n\n    $md5File = \"key\";\n    file_put_contents($md5File, $encrypted);\n\n    //pack script zip file and md5 file to final zip file\n    echo system(\"zip $finalFile $zipFile $md5File\"); \n\n    unlink($md5File);\n    unlink($zipFile);\n}\n"
  },
  {
    "path": "README-CN.md",
    "content": "# JSPatch\n\nJSPatch 可以让你用 JavaScript 书写原生 iOS APP。只需在项目引入极小的引擎，就可以使用 JavaScript 调用任何 Objective-C 的原生接口，获得脚本语言的优势：为项目动态添加模块，或替换项目原生代码动态修复 bug。\n\n项目仍在开发中，欢迎一起完善这个项目。\n\n**注意**：完善的文档请移步 [Wiki](https://github.com/bang590/JSPatch/wiki/)。\n\n## 示例\n\n```objc\n@implementation AppDelegate\n\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions \n{\n    [JPEngine startEngine];\n    NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@\"demo\" ofType:@\"js\"];\n    NSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil];\n    [JPEngine evaluateScript:script];\n    \n    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];\n    [self.window addSubview:[self genView]];\n    [self.window makeKeyAndVisible];\n    \n    return YES;\n}\n\n- (UIView *)genView\n{\n    return [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 320)];\n}\n\n@end\n```\n\n```js\n// demo.js\nrequire('UIView, UIColor, UILabel')\ndefineClass('AppDelegate', {\n  // replace the -genView method\n  genView: function() {\n    var view = self.ORIGgenView();\n    view.setBackgroundColor(UIColor.greenColor())\n    var label = UILabel.alloc().initWithFrame(view.frame());\n    label.setText(\"JSPatch\");\n    label.setTextAlignment(1);\n    view.addSubview(label);\n    return view;\n  }\n});\n```\n\n可以使用 [JSPatch Convertor](https://github.com/bang590/JSPatchConvertor) 自动把 Objective-C 代码转为 JavaScript 代码。\n\n## 安装\n\n拷贝 `JSPatch/` 目录下的三个文件 `JSEngine.m` / `JSEngine.h` / `JSPatch.js` 到项目里即可。\n\n## 使用\n\n### Objective-C:\n1. `#import \"JPEngine.h\"`\n2. 调用`[JPEngine startEngine]`\n3. 通过`[JPEngine evaluateScript:@\"\"]`接口执行 JavaScript。\n\n```objc\n[JPEngine startEngine];\n\n// 直接执行js\n[JPEngine evaluateScript:@\"\\\n var alertView = require('UIAlertView').alloc().init();\\\n alertView.setTitle('Alert');\\\n alertView.setMessage('AlertView from js'); \\\n alertView.addButtonWithTitle('OK');\\\n alertView.show(); \\\n\"];\n\n// 从网络拉回js脚本执行\n[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@\"http://cnbang.net/test.js\"]] queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {\n    NSString *script = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];\n    [JPEngine evaluateScript:script];\n}];\n\n// 执行本地js文件\nNSString *sourcePath = [[NSBundle mainBundle] pathForResource:@\"sample\" ofType:@\"js\"];\nNSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil];\n[JPEngine evaluateScript:script];\n```\n\n### JavaScript:\n\n#### 基础使用方式\n\n```js\n// 调用require引入要使用的OC类\nrequire('UIView, UIColor, UISlider, NSIndexPath')\n\n// 调用类方法\nvar redColor = UIColor.redColor();\n\n// 调用实例方法\nvar view = UIView.alloc().init();\nview.setNeedsLayout();\n\n// set proerty\nview.setBackgroundColor(redColor);\n\n// get property \nvar bgColor = view.backgroundColor();\n\n// 多参数方法名用'_'隔开：\n// OC：NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:1];\nvar indexPath = NSIndexPath.indexPathForRow_inSection(0, 1);\n\n// 方法名包含下划线'_'，js用双下划线表示\n// OC: [JPObject _privateMethod];\nJPObject.__privateMethod()\n\n// 如果要把 `NSArray` / `NSString` / `NSDictionary` 转为对应的 JS 类型，使用 `.toJS()` 接口.\nvar arr = require('NSMutableArray').alloc().init()\narr.addObject(\"JS\")\njsArr = arr.toJS()\nconsole.log(jsArr.push(\"Patch\").join(''))  //output: JSPatch\n\n// 在JS用字典的方式表示 CGRect / CGSize / CGPoint / NSRange\nvar view = UIView.alloc().initWithFrame({x:20, y:20, width:100, height:100});\nvar x = view.bounds().x;\n\n// block 从 JavaScript 传入 Objective-C 时，需要写上每个参数的类型。\n// OC Method: + (void)request:(void(^)(NSString *content, BOOL success))callback\nrequire('JPObject').request(block(\"NSString *, BOOL\", function(ctn, succ) {\n  if (succ) log(ctn)\n}));\n\n// GCD\ndispatch_after(function(1.0, function(){\n  // do something\n}))\ndispatch_async_main(function(){\n  // do something\n})\n```\n\n详细文档请参考wiki页面：[Base Usage](https://github.com/bang590/JSPatch/wiki/Base-usage)\n\n\n#### 定义类/替换方法\n\n用 `defineClass()` 定义 Objective-C 的类，对类和实例方法进行动态替换。\n\n```objc\n// OC\n@implementation JPTableViewController\n...\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath\n{\n  NSString *content = self.dataSource[[indexPath row]];  //may cause out of bound\n  JPViewController *ctrl = [[JPViewController alloc] initWithContent:content];\n  [self.navigationController pushViewController:ctrl];\n}\n- (NSArray *)dataSource\n{\n  return @[@\"JSPatch\", @\"is\"];\n}\n- (void)customMethod\n{\n  NSLog(@\"callCustom method\")\n}\n@end\n```\n\n```objc\n// JS\ndefineClass(\"JPTableViewController\", {\n  // instance method definitions\n  tableView_didSelectRowAtIndexPath: function(tableView, indexPath) {\n    var row = indexPath.row()\n    if (self.dataSource().count() > row) {  //fix the out of bound bug here\n      var content = self.dataSource().objectAtIndex(row);\n      var ctrl = JPViewController.alloc().initWithContent(content);\n      self.navigationController().pushViewController(ctrl);\n    }\n  },\n\n  dataSource: function() {\n    // get the original method by adding prefix 'ORIG'\n    var data = self.ORIGdataSource().toJS();\n    return data.push('Good!');\n  }\n}, {})\n```\n\n详细文档请参考wiki页面：[Usage of defineClass](https://github.com/bang590/JSPatch/wiki/Usage-of-defineClass)\n\n\n#### 扩展\n\n一些自定义的struct类型、C函数调用以及其他功能可以通过扩展实现，调用 `+addExtensions:` 可以加载扩展接口：\n\n```objc\n@implementation AppDelegate\n\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions \n{\n    [JPEngine startEngine];\n\n    //添加扩展\n    [JPEngine addExtensions:@[@\"JPInclude\", @\"JPCGTransform\"]];\n\n    NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@\"demo\" ofType:@\"js\"];\n    NSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil];\n    [JPEngine evaluateScript:script];\n}\n```\n\n```js\ninclude('test.js')   //`include()`方法在扩展 JPInclude.m 里提供\nvar view = require('UIView').alloc().init()\n\n//struct CGAffineTransform 类型在 JPCGTransform.m 里提供支持\nview.setTransform({a:1, b:0, c:0, d:1, tx:0, ty:100})\n```\n\n扩展可以在JS动态加载，更推荐这种加载方式，在需要用到时才加载：\n\n```js\nrequire('JPEngine').addExtensions(['JPInclude', 'JPCGTransform'])\n\n// `include()` and `CGAffineTransform` is avaliable now.\n```\n\n可以通过新增扩展为自己项目里的 struct 类型以及C函数添加支持，详情请见wiki页面：[Adding new extensions](https://github.com/bang590/JSPatch/wiki/Adding-new-extensions)\n\n\n## 运行环境\n- iOS 7+\n- JavaScriptCore.framework\n- 支持 armv7/armv7s/arm64\n"
  },
  {
    "path": "README.md",
    "content": "# JSPatch\n[![Travis](https://img.shields.io/travis/bang590/JSPatch.svg)](https://travis-ci.org/bang590/JSPatch)\n![CocoaPods Version](https://img.shields.io/cocoapods/v/JSPatch.svg?style=flat)\n[![License](https://img.shields.io/github/license/bang590/JSPatch.svg?style=flat)](https://github.com/bang590/JSPatch/blob/master/LICENSE)\n\n[中文介绍](https://github.com/bang590/JSPatch/blob/master/README-CN.md) | [文档](https://github.com/bang590/JSPatch/wiki) | [JSPatch平台](http://jspatch.com)\n\n**请大家不要自行接入 JSPatch，统一接入 JSPatch 平台，让热修复在一个安全和可控的环境下使用。原因详见 [这里](http://jspatch.com/Docs/appleFAQ)**\n\nJSPatch bridges Objective-C and JavaScript using the Objective-C runtime. You can call any Objective-C class and method in JavaScript by just including a small engine. That makes the APP obtaining the power of script language: add modules or replacing Objective-C code to fix bugs dynamically.\n\nJSPatch is still in development, welcome to improve the project together.\n\n**Notice**: Please go to [Wiki](https://github.com/bang590/JSPatch/wiki/) to get full document.\n\n## Example\n\n```objc\n@implementation AppDelegate\n\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions \n{\n    [JPEngine startEngine];\n    NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@\"demo\" ofType:@\"js\"];\n    NSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil];\n    [JPEngine evaluateScript:script];\n    \n    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];\n    [self.window addSubview:[self genView]];\n    [self.window makeKeyAndVisible];\n    \n    return YES;\n}\n\n- (UIView *)genView\n{\n    return [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 320)];\n}\n\n@end\n```\n\n```js\n// demo.js\nrequire('UIView, UIColor, UILabel')\ndefineClass('AppDelegate', {\n  // replace the -genView method\n  genView: function() {\n    var view = self.ORIGgenView();\n    view.setBackgroundColor(UIColor.greenColor())\n    var label = UILabel.alloc().initWithFrame(view.frame());\n    label.setText(\"JSPatch\");\n    label.setTextAlignment(1);\n    view.addSubview(label);\n    return view;\n  }\n});\n```\n\nYou can also try to use [JSPatch Convertor](https://github.com/bang590/JSPatchConvertor) to convertor code from Objective-C to JavaScript automatically.\n\n## Installation\n\n### CocoaPods\n\n[CocoaPods](http://cocoapods.org) is a dependency manager for Objective-C, which automates and simplifies the process of using 3rd-party libraries like JSPatch in your projects. See the [\"Getting Started\"](https://guides.cocoapods.org/using/getting-started.html) guide for more information.\n\n```ruby\n# Your Podfile\nplatform :ios, '6.0'\npod 'JSPatch'\n```\n\n### Manually\n\nCopy `JSEngine.m` `JSEngine.h` `JSPatch.js` in `JSPatch/` to your project.\n\n\n## Usage\n\n### Objective-C\n1. `#import \"JPEngine.h\"`\n2. call `[JPEngine startEngine]`\n3. exec JavasScript by `[JPEngine evaluateScript:@\"\"]`\n\n```objc\n[JPEngine startEngine];\n\n// exec js directly\n[JPEngine evaluateScript:@\"\\\n var alertView = require('UIAlertView').alloc().init();\\\n alertView.setTitle('Alert');\\\n alertView.setMessage('AlertView from js'); \\\n alertView.addButtonWithTitle('OK');\\\n alertView.show(); \\\n\"];\n\n// exec js file from network\n[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@\"http://cnbang.net/test.js\"]] queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {\n    NSString *script = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];\n    [JPEngine evaluateScript:script];\n}];\n\n// exec local js file\nNSString *sourcePath = [[NSBundle mainBundle] pathForResource:@\"sample\" ofType:@\"js\"];\nNSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil];\n[JPEngine evaluateScript:script];\n```\n\n### JavaScript\n\n#### Base Usage\n\n```js\n//require\nrequire('UIView, UIColor, UISlider, NSIndexPath')\n\n// Invoke class method\nvar redColor = UIColor.redColor();\n\n// Invoke instance method\nvar view = UIView.alloc().init();\nview.setNeedsLayout();\n\n// set proerty\nview.setBackgroundColor(redColor);\n\n// get property \nvar bgColor = view.backgroundColor();\n\n// multi-params method (use underline to separate)\n// OC：NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:1];\nvar indexPath = NSIndexPath.indexPathForRow_inSection(0, 1);\n\n// method name contains underline (use double undeline to represent)\n// OC: [JPObject _privateMethod];\nJPObject.__privateMethod()\n\n// use .toJS() to convert NSArray / NSString / NSDictionary to JS type.\nvar arr = require('NSMutableArray').alloc().init()\narr.addObject(\"JS\")\njsArr = arr.toJS()\nconsole.log(jsArr.push(\"Patch\").join(''))  //output: JSPatch\n\n// use hashes to represent struct like CGRect / CGSize / CGPoint / NSRange\nvar view = UIView.alloc().initWithFrame({x:20, y:20, width:100, height:100});\nvar x = view.bounds().x;\n\n// wrap function with `block()` when passing block from JS to OC\n// OC Method: + (void)request:(void(^)(NSString *content, BOOL success))callback\nrequire('JPObject').request(block(\"NSString *, BOOL\", function(ctn, succ) {\n  if (succ) log(ctn)\n}));\n\n// GCD\ndispatch_after(1.0, function(){\n  // do something\n})\ndispatch_async_main(function(){\n  // do something\n})\n```\n\nGo to wiki page for more details: [Base Usage](https://github.com/bang590/JSPatch/wiki/Base-usage)\n\n\n\n#### defineClass\nYou can redefine an existing class and override methods.\n\n```objc\n// OC\n@implementation JPTableViewController\n...\n- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath\n{\n  NSString *content = self.dataSource[[indexPath row]];  //may cause out of bound\n  JPViewController *ctrl = [[JPViewController alloc] initWithContent:content];\n  [self.navigationController pushViewController:ctrl];\n}\n- (NSArray *)dataSource\n{\n  return @[@\"JSPatch\", @\"is\"];\n}\n- (void)customMethod\n{\n  NSLog(@\"callCustom method\")\n}\n@end\n```\n\n```objc\n// JS\ndefineClass(\"JPTableViewController\", {\n  // instance method definitions\n  tableView_didSelectRowAtIndexPath: function(tableView, indexPath) {\n    var row = indexPath.row()\n    if (self.dataSource().count() > row) {  //fix the out of bound bug here\n      var content = self.dataSource().objectAtIndex(row);\n      var ctrl = JPViewController.alloc().initWithContent(content);\n      self.navigationController().pushViewController(ctrl);\n    }\n  },\n\n  dataSource: function() {\n    // get the original method by adding prefix 'ORIG'\n    var data = self.ORIGdataSource().toJS();\n    return data.push('Good!');\n  }\n}, {})\n```\n\nGo to wiki page for more details: [Usage of defineClass](https://github.com/bang590/JSPatch/wiki/Usage-of-defineClass)\n\n#### Extensions\n\nThere are some extensions provide support for custom struct type, C methods and other functional, call `+addExtensions:` after starting engine to add extensions:\n\n```objc\n@implementation AppDelegate\n\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions \n{\n    [JPEngine startEngine];\n\n    //add extensions after startEngine\n    [JPEngine addExtensions:@[@\"JPInclude\", @\"JPCGTransform\"]];\n\n    NSString *sourcePath = [[NSBundle mainBundle] pathForResource:@\"demo\" ofType:@\"js\"];\n    NSString *script = [NSString stringWithContentsOfFile:sourcePath encoding:NSUTF8StringEncoding error:nil];\n    [JPEngine evaluateScript:script];\n}\n\n@end\n```\n\n```js\ninclude('test.js')   //include function provide by JPInclude.m\nvar view = require('UIView').alloc().init()\n\n//CGAffineTransform is supported in JPCGTransform.m\nview.setTransform({a:1, b:0, c:0, d:1, tx:0, ty:100})\n```\n\nExtensions can be added dynamiclly in JS, which is recommended:\n\n```js\nrequire('JPEngine').addExtensions(['JPInclude', 'JPCGTransform'])\n\n// `include()` and `CGAffineTransform` is avaliable now.\n```\n\nYou can create your own extension to support custom struct type and C methods in project, see the wiki page for more details: [Adding new extensions](https://github.com/bang590/JSPatch/wiki/Adding-new-extensions)\n\n\n## Enviroment\n- iOS 7+, forward compatibility with iOS 6\n- JavaScriptCore.framework\n- Support armv7/armv7s/arm64\n"
  }
]