text:
<?xml version="1.0" encoding="UTF-8"?>
<Tokens version="1.0">
	<File path="Classes/TDReplicator.html">

		<Token>
			<TokenIdentifier>//apple_ref/occ/cl/TDReplicator</TokenIdentifier>
			<Abstract type="html">Abstract base class for push or pull replications.</Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<NodeRef refid="43"/>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/clm/TDReplicator/progressChangedNotification</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>+ (NSString *)progressChangedNotification</Declaration>

			<Anchor>//api/name/progressChangedNotification</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/clm/TDReplicator/stoppedNotification</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>+ (NSString *)stoppedNotification</Declaration>

			<Anchor>//api/name/stoppedNotification</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/initWithDB:remote:push:continuous:</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>- (id)initWithDB:(TDDatabase *)db remote:(NSURL *)remote push:(BOOL)push continuous:(BOOL)continuous</Declaration>

			<Anchor>//api/name/initWithDB:remote:push:continuous:</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/setDb:</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (readonly) TDDatabase *db</Declaration>

			<Anchor>//api/name/db</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instp/TDReplicator/db</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (readonly) TDDatabase *db</Declaration>

			<Anchor>//api/name/db</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/setRemote:</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (readonly) NSURL *remote</Declaration>

			<Anchor>//api/name/remote</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instp/TDReplicator/remote</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (readonly) NSURL *remote</Declaration>

			<Anchor>//api/name/remote</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/setIsPush:</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (readonly) BOOL isPush</Declaration>

			<Anchor>//api/name/isPush</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instp/TDReplicator/isPush</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (readonly) BOOL isPush</Declaration>

			<Anchor>//api/name/isPush</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/setContinuous:</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (readonly) BOOL continuous</Declaration>

			<Anchor>//api/name/continuous</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instp/TDReplicator/continuous</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (readonly) BOOL continuous</Declaration>

			<Anchor>//api/name/continuous</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/setFilterName:</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (copy) NSString *filterName</Declaration>

			<Anchor>//api/name/filterName</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instp/TDReplicator/filterName</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (copy) NSString *filterName</Declaration>

			<Anchor>//api/name/filterName</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/setFilterParameters:</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (copy) NSDictionary *filterParameters</Declaration>

			<Anchor>//api/name/filterParameters</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instp/TDReplicator/filterParameters</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (copy) NSDictionary *filterParameters</Declaration>

			<Anchor>//api/name/filterParameters</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/setOptions:</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (copy) NSDictionary *options</Declaration>

			<Anchor>//api/name/options</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instp/TDReplicator/options</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (copy) NSDictionary *options</Declaration>

			<Anchor>//api/name/options</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/setRequestHeaders:</TokenIdentifier>
			<Abstract type="html">Optional dictionary of headers to be added to all requests to remote servers.</Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (copy) NSDictionary *requestHeaders</Declaration>

			<Anchor>//api/name/requestHeaders</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instp/TDReplicator/requestHeaders</TokenIdentifier>
			<Abstract type="html">Optional dictionary of headers to be added to all requests to remote servers.</Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (copy) NSDictionary *requestHeaders</Declaration>

			<Anchor>//api/name/requestHeaders</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/setAuthorizer:</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (retain) id<TDAuthorizer> authorizer</Declaration>

			<Anchor>//api/name/authorizer</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instp/TDReplicator/authorizer</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (retain) id<TDAuthorizer> authorizer</Declaration>

			<Anchor>//api/name/authorizer</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/start</TokenIdentifier>
			<Abstract type="html">Starts the replicator.
    Replicators run asynchronously so nothing will happen until later.
    A replicator can only be started once; don't reuse it after it stops. </Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>- (void)start</Declaration>

			<Anchor>//api/name/start</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/stop</TokenIdentifier>
			<Abstract type="html">Request to stop the replicator.
    Any pending asynchronous operations will be canceled.
    TDReplicatorStoppedNotification will be posted when it finally stops. </Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>- (void)stop</Declaration>

			<Anchor>//api/name/stop</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/setRunning:</TokenIdentifier>
			<Abstract type="html">Is the replicator running? (Observable)</Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (readonly, nonatomic) BOOL running</Declaration>

			<Anchor>//api/name/running</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instp/TDReplicator/running</TokenIdentifier>
			<Abstract type="html">Is the replicator running? (Observable)</Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (readonly, nonatomic) BOOL running</Declaration>

			<Anchor>//api/name/running</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/setOnline:</TokenIdentifier>
			<Abstract type="html">Is the replicator able to connect to the remote host?</Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (readonly, nonatomic) BOOL online</Declaration>

			<Anchor>//api/name/online</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instp/TDReplicator/online</TokenIdentifier>
			<Abstract type="html">Is the replicator able to connect to the remote host?</Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (readonly, nonatomic) BOOL online</Declaration>

			<Anchor>//api/name/online</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/setActive:</TokenIdentifier>
			<Abstract type="html">Is the replicator actively sending/receiving revisions? (Observable)</Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (readonly, nonatomic) BOOL active</Declaration>

			<Anchor>//api/name/active</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instp/TDReplicator/active</TokenIdentifier>
			<Abstract type="html">Is the replicator actively sending/receiving revisions? (Observable)</Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (readonly, nonatomic) BOOL active</Declaration>

			<Anchor>//api/name/active</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/setError:</TokenIdentifier>
			<Abstract type="html">Latest error encountered while replicating.
    This is set to nil when starting. It may also be set to nil by the client if desired.
    Not all errors are fatal; if .running is still true, the replicator will retry. </Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (retain, nonatomic) NSError *error</Declaration>

			<Anchor>//api/name/error</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instp/TDReplicator/error</TokenIdentifier>
			<Abstract type="html">Latest error encountered while replicating.
    This is set to nil when starting. It may also be set to nil by the client if desired.
    Not all errors are fatal; if .running is still true, the replicator will retry. </Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (retain, nonatomic) NSError *error</Declaration>

			<Anchor>//api/name/error</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/setSessionID:</TokenIdentifier>
			<Abstract type="html">A unique-per-process string identifying this replicator instance.</Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (copy, nonatomic) NSString *sessionID</Declaration>

			<Anchor>//api/name/sessionID</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instp/TDReplicator/sessionID</TokenIdentifier>
			<Abstract type="html">A unique-per-process string identifying this replicator instance.</Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (copy, nonatomic) NSString *sessionID</Declaration>

			<Anchor>//api/name/sessionID</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/setChangesProcessed:</TokenIdentifier>
			<Abstract type="html">Number of changes (docs or other metadata) transferred so far.</Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (readonly, nonatomic) NSUInteger changesProcessed</Declaration>

			<Anchor>//api/name/changesProcessed</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instp/TDReplicator/changesProcessed</TokenIdentifier>
			<Abstract type="html">Number of changes (docs or other metadata) transferred so far.</Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (readonly, nonatomic) NSUInteger changesProcessed</Declaration>

			<Anchor>//api/name/changesProcessed</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/setChangesTotal:</TokenIdentifier>
			<Abstract type="html">Approximate total number of changes to transfer.
    This is only an estimate and its value will change during replication. It starts at zero and returns to zero when replication stops. </Abstract>
			<DeclaredIn>TDInternal.h</DeclaredIn>

			<Declaration>@property (readonly, nonatomic) NSUInteger changesTotal</Declaration>

			<Anchor>//api/name/changesTotal</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instp/TDReplicator/changesTotal</TokenIdentifier>
			<Abstract type="html">Approximate total number of changes to transfer.
    This is only an estimate and its value will change during replication. It starts at zero and returns to zero when replication stops. </Abstract>
			<DeclaredIn>TDInternal.h</DeclaredIn>

			<Declaration>@property (readonly, nonatomic) NSUInteger changesTotal</Declaration>

			<Anchor>//api/name/changesTotal</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/setActiveRequestsStatus:</TokenIdentifier>
			<Abstract type="html">JSON-compatible array of status info about active remote HTTP requests.</Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (readonly) NSArray *activeRequestsStatus</Declaration>

			<Anchor>//api/name/activeRequestsStatus</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instp/TDReplicator/activeRequestsStatus</TokenIdentifier>
			<Abstract type="html">JSON-compatible array of status info about active remote HTTP requests.</Abstract>
			<DeclaredIn>TDReplicator.h</DeclaredIn>

			<Declaration>@property (readonly) NSArray *activeRequestsStatus</Declaration>

			<Anchor>//api/name/activeRequestsStatus</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/setLastSequence:</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDInternal.h</DeclaredIn>

			<Declaration>@property (copy) NSString *lastSequence</Declaration>

			<Anchor>//api/name/lastSequence</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instp/TDReplicator/lastSequence</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDInternal.h</DeclaredIn>

			<Declaration>@property (copy) NSString *lastSequence</Declaration>

			<Anchor>//api/name/lastSequence</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/maybeCreateRemoteDB</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDInternal.h</DeclaredIn>

			<Declaration>- (void)maybeCreateRemoteDB</Declaration>

			<Anchor>//api/name/maybeCreateRemoteDB</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/beginReplicating</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDInternal.h</DeclaredIn>

			<Declaration>- (void)beginReplicating</Declaration>

			<Anchor>//api/name/beginReplicating</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/addToInbox:</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDInternal.h</DeclaredIn>

			<Declaration>- (void)addToInbox:(TDRevision *)rev</Declaration>

			<Anchor>//api/name/addToInbox:</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/addRevsToInbox:</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDInternal.h</DeclaredIn>

			<Declaration>- (void)addRevsToInbox:(TDRevisionList *)revs</Declaration>

			<Anchor>//api/name/addRevsToInbox:</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/processInbox:</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDInternal.h</DeclaredIn>

			<Declaration>- (void)processInbox:(TDRevisionList *)inbox</Declaration>

			<Anchor>//api/name/processInbox:</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/sendAsyncRequest:path:body:onCompletion:</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDInternal.h</DeclaredIn>

			<Declaration>- (TDRemoteJSONRequest *)sendAsyncRequest:(NSString *)method path:(NSString *)relativePath body:(id)body onCompletion:(TDRemoteRequestCompletionBlock)onCompletion</Declaration>

			<Anchor>//api/name/sendAsyncRequest:path:body:onCompletion:</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/addRemoteRequest:</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDInternal.h</DeclaredIn>

			<Declaration>- (void)addRemoteRequest:(TDRemoteRequest *)request</Declaration>

			<Anchor>//api/name/addRemoteRequest:</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/removeRemoteRequest:</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDInternal.h</DeclaredIn>

			<Declaration>- (void)removeRemoteRequest:(TDRemoteRequest *)request</Declaration>

			<Anchor>//api/name/removeRemoteRequest:</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/asyncTaskStarted</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDInternal.h</DeclaredIn>

			<Declaration>- (void)asyncTaskStarted</Declaration>

			<Anchor>//api/name/asyncTaskStarted</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/asyncTasksFinished:</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDInternal.h</DeclaredIn>

			<Declaration>- (void)asyncTasksFinished:(NSUInteger)numTasks</Declaration>

			<Anchor>//api/name/asyncTasksFinished:</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/stopped</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDInternal.h</DeclaredIn>

			<Declaration>- (void)stopped</Declaration>

			<Anchor>//api/name/stopped</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/databaseClosing</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDInternal.h</DeclaredIn>

			<Declaration>- (void)databaseClosing</Declaration>

			<Anchor>//api/name/databaseClosing</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/revisionFailed</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDInternal.h</DeclaredIn>

			<Declaration>- (void)revisionFailed</Declaration>

			<Anchor>//api/name/revisionFailed</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/retry</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDInternal.h</DeclaredIn>

			<Declaration>- (void)retry</Declaration>

			<Anchor>//api/name/retry</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/reachabilityChanged:</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDInternal.h</DeclaredIn>

			<Declaration>- (void)reachabilityChanged:(TDReachability *)host</Declaration>

			<Anchor>//api/name/reachabilityChanged:</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/goOffline</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDInternal.h</DeclaredIn>

			<Declaration>- (BOOL)goOffline</Declaration>

			<Anchor>//api/name/goOffline</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/goOnline</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDInternal.h</DeclaredIn>

			<Declaration>- (BOOL)goOnline</Declaration>

			<Anchor>//api/name/goOnline</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instm/TDReplicator/setSavingCheckpoint:</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDInternal.h</DeclaredIn>

			<Declaration>@property (readonly) BOOL savingCheckpoint</Declaration>

			<Anchor>//api/name/savingCheckpoint</Anchor>
		</Token>

		<Token>
			<TokenIdentifier>//apple_ref/occ/instp/TDReplicator/savingCheckpoint</TokenIdentifier>
			<Abstract type="html"></Abstract>
			<DeclaredIn>TDInternal.h</DeclaredIn>

			<Declaration>@property (readonly) BOOL savingCheckpoint</Declaration>

			<Anchor>//api/name/savingCheckpoint</Anchor>
		</Token>

	</File>
</Tokens>


text:
package com.github.stigmata.printer;

import java.io.PrintWriter;
import java.io.StringWriter;

import com.github.stigmata.ExtractionResultSet;

/**
 *
 *
 *
 * @author Haruaki TAMADA
 */
public abstract class AbstractExtractionResultSetPrinter implements ExtractionResultSetPrinter{
    @Override
    public abstract void printResult(PrintWriter out, ExtractionResultSet ers);

    public void printHeader(PrintWriter out){
    }

    public void printFooter(PrintWriter out){
        out.flush();
    }

    @Override
    public String getResult(ExtractionResultSet ers){
        StringWriter writer = new StringWriter();
        PrintWriter out = new PrintWriter(writer);

        printResult(out, ers);

        out.close();
        return writer.toString();
    }
}

redpajama_set_name: RedPajamaGithub


text:
package app.ddf.danskdatahistoriskforening.dal;

import android.content.Context;
import android.net.Uri;

public interface IDAO {
    int saveItemToDB(Context context, Item item);
    String getOverviewFromBackend();
    Item getDetailsFromBackEnd(String detailsURI);
    int updateItem(Context context, Item item);
    void postFile(Context context, Uri path, int itemID, String extension);

    void cancelDownload();
}


text:
namespace content {
class DownloadItem;
class WebContents;

// Interface to request GET downloads and send notifications for POST
// downloads.
class CONTENT_EXPORT DownloadControllerAndroid {
 public:
  // Returns the singleton instance of the DownloadControllerAndroid.
  static DownloadControllerAndroid* Get();

  // Called to set the DownloadControllerAndroid instance.
  static void SetDownloadControllerAndroid(
      DownloadControllerAndroid* download_controller);

  // Starts a new download request with Android. Should be called on the
  // UI thread.
  virtual void CreateGETDownload(int render_process_id, int render_view_id,
                                 int request_id) = 0;

  // Should be called when a download is started. It can be either a GET
  // request with authentication or a POST request. Notifies the embedding
  // app about the download. Should be called on the UI thread.
  virtual void OnDownloadStarted(DownloadItem* download_item) = 0;

  // Called when a download is initiated by context menu.
  virtual void StartContextMenuDownload(
      const ContextMenuParams& params, WebContents* web_contents,
      bool is_link, const std::string& extra_headers) = 0;

  // Called when a dangerous download item is verified or rejected.
  virtual void DangerousDownloadValidated(
      WebContents* web_contents, int download_id, bool accept) = 0;

  // Callback when user permission prompt finishes. Args: whether file access
  // permission is acquired.
  typedef base::Callback<void(bool)> AcquireFileAccessPermissionCallback;

  // Called to prompt the user for file access permission. When finished,
  // |callback| will be executed.
  virtual void AcquireFileAccessPermission(
      WebContents* web_contents,
      const AcquireFileAccessPermissionCallback& callback) = 0;

  // Called by unit test to approve or disapprove file access request.
  virtual void SetApproveFileAccessRequestForTesting(bool approve) {};

 protected:
  virtual ~DownloadControllerAndroid() {};
  static DownloadControllerAndroid* download_controller_;
};

}  // namespace content

#endif  // CONTENT_PUBLIC_BROWSER_ANDROID_DOWNLOAD_CONTROLLER_ANDROID_H_


text:
using Newtonsoft.Json;
using System.Collections.Generic;

namespace Wargaming.WebAPI.WoT.Model
{
	public class GroupedContacts
	{
		/// <summary>
		/// Blocked
		/// </summary>
		[JsonProperty("blocked")]
		public List<int> Blocked { get; set; }

		/// <summary>
		/// Ignored
		/// </summary>
		[JsonProperty("ignored")]
		public List<int> Ignored { get; set; }

		/// <summary>
		/// Muted
		/// </summary>
		[JsonProperty("muted")]
		public List<int> Muted { get; set; }

		/// <summary>
		/// Not grouped
		/// </summary>
		[JsonProperty("ungrouped")]
		public List<int> Ungrouped { get; set; }

		/// <summary>
		/// Groups
		/// </summary>
		[JsonProperty("groups")]
		public Dictionary<string, List<int>> Groups { get; set; }
	}
}


text:
package com.ds.master.bean;

/**
 * Created by Administrator on 2016/0/25.
 */

public class PhoneInfo {

    public String idx;
    public String name;
    public String namec;
    public String number;

    public PhoneInfo(String idx, String name,String namec,String number){

        this.idx = idx;
        this.name = name;
        this.namec = namec;
        this.number = number;
    }

}


text:
<?xml version="1.0"?>
<!--

-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>
  <groupId>org.lilyproject</groupId>
  <artifactId>lily-general-module</artifactId>
  <packaging>jar</packaging>

  <parent>
    <groupId>org.lilyproject</groupId>
    <artifactId>lily-server</artifactId>
    <version>2.8-SNAPSHOT</version>
    <relativePath>../</relativePath>
  </parent>

  <name>Lily: Runtime: general module</name>

  <dependencies>
    <dependency>
      <groupId>org.lilyproject</groupId>
      <artifactId>lily-zk-util</artifactId>
    </dependency>
    <dependency>
      <groupId>org.lilyproject</groupId>
      <artifactId>lily-linkindex</artifactId>
    </dependency>
    <dependency>
      <groupId>com.ngdata</groupId>
      <artifactId>hbase-sep-impl</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
    </dependency>
    <dependency>
      <groupId>org.lilyproject</groupId>
      <artifactId>lily-runtime-conf</artifactId>
    </dependency>
    <dependency>
      <groupId>org.lilyproject</groupId>
      <artifactId>lily-hbase-client</artifactId>
    </dependency>
    <dependency>
      <groupId>org.lilyproject</groupId>
      <artifactId>lily-sep</artifactId>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.lilyproject</groupId>
        <artifactId>lily-runtime-genclassloader-plugin</artifactId>
      </plugin>

      <plugin>
        <artifactId>maven-resources-plugin</artifactId>
        <executions>
          <execution>
            <id>copy-resources</id>
            <phase>compile</phase>
            <goals>
              <goal>copy-resources</goal>
            </goals>
            <configuration>
              <outputDirectory>${basedir}/target/classes/LILY-INF/conf</outputDirectory>
              <resources>
                <resource>
                  <directory>${basedir}/../conf/general</directory>
                  <filtering>false</filtering>
                </resource>
              </resources>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

</project>


text:
V systému má existovat třída, která může mít nejvýše jednu globálně sdílenou instanci a zároveň sama centralizuje k této své instanci přístup.

### Řešení

Správná implementace singletonu silně závisí na jazyku, který použijeme, protože každý z nich nabízí jiné prostředky a konstrukce. Na implementaci máme následující požadavky:

* nesmí být možné vytvářet instance singletonu jinde, než v singletonu samém
* vytváření singletonu musí proběhnout nejvýše jednou, a proto je nutné zajistit vláknovou bezpečnost, aby dvě různá vlákna v jeden okamžik nevytvářela dvě různé instance singletonu
* při získávání již existující instance singletonu se nesmí provádět žádné zbytečné operace
* nemělo by být možné použít reflexi a zničit či zaměnit instanci singletonu během vykonávání programu
* instance singletonu by měla být serializovatelná

```uml:class
class EagerSingleton {
  -{static} instance: EagerSingleton = new EagerSingleton()
  +{static} getInstance(): EagerSingleton
}
class LazySingleton {
  -{static} instance: LazySingleton = null
  +{static} getInstance(): LazySingleton
}
note bottom of LazySingleton
  if (instance == null) then
    instance = new LazySingleton();
  return instance;
end note
```

### Implementace (Java)

V jazyce Java existuje několik způsobů, jak uvedené požadavky zajistit.

#### Singleton (jednoduchý)

Tento postup je velmi jednoduchý, ale zároveň neimplementuje všechny požadavky. Je však vláknově bezpečný a efektivní.

```java
public final class Singleton {
    public static final Singleton INSTANCE = new Singleton();

    private Singleton() {
        // ...
    }
}
```

#### Singleton (realizace s použitím dvojité kontroly)

Tento postup umožňuje línou inicializaci za cenu mírně nepřehledné metody pro získání instance. Je vláknově bezpečný.

```java
public final class Singleton {
    private static Singleton INSTANCE = null;

    private Singleton() {
        // ...
    }

    public static Singleton getInstance() {
        if (INSTANCE == null) {
            synchronized (Singleton.class) {
                if (INSTANCE == null) {
                    INSTANCE = new Singleton();
                }
            }
        }

        return INSTANCE;
    }
}
```

#### Singleton (realizace vnitřní pomocnou třídou)

V této implementaci je instance singletonu vytvořena classloaderem během načítání třídy. Původním autorem techniky je zřejmě [Bill Pugh](http://www.cs.umd.edu/~pugh/).

```java
public final class Singleton {
    private Singleton() {
        // ...
    }

    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }

    private static class SingletonHolder {
        private static Singleton INSTANCE = new Singleton();
    }
}
```

#### Singleton (realizace výčtovým typem)

Tuto techniku doporučuje [Joshua Bloch](https://en.wikipedia.org/wiki/Joshua_Bloch) ve [své přednášce](http://www.youtube.com/watch?v=pi_I7oD_uGI#t=28m50s).
Podle něj se jedná o nejlepší a nejrobustnější implementaci, která implementuje všechny rozumné požadavky, které na singleton můžeme mít.

> This approach is functionally equivalent to the public field approach, except that it is more concise, provides the serialization machinery for free, and provides an ironclad guarantee against multiple instantiation, even in the face of sophisticated serialization or reflection attacks. While this approach has yet to be widely adopted, a single-element enum type is the best way to implement a singleton. *Joshua Bloch*

```java
public enum Singleton {
    INSTANCE;

    // ...
}
```

#### Použití

```java
Singleton.getInstance().doSomething();
```

### Reference

- předmět X36ASS na FEL ČVUT
- předmět X36OBP na FEL ČVUT
- http://stackoverflow.com/questions/70689/what-is-an-efficient-way-to-implement-a-singleton-pattern-in-java
- http://www.oodesign.com/singleton-pattern.html
- http://objekty.vse.cz/Objekty/Vzory-Singleton
- http://sourcemaking.com/design_patterns/singleton


text:
require 'socket'
require 'logger'

require 'eventmachine'

# Framework for intercepting packets, redirecting them to a handler, and doing
# something with the "stolen" connection.
#
# == Description
#
# PacketThief is a little Ruby framework for programatically intercepting network
# traffic. It provides an abstraction around configuring various OS firewalls and
# for gathering information about the original connection, and it offers several
# sample handler classes (for use with EventMachine) for intercepting and
# forwarding traffic. If you want a full fledged security tool for intercepting
# and analyzing network traffic, check out
# {Mallory}[http://intrepidusgroup.com/insight/mallory/] instead.
#
# PacketThief is currently intended to be run on a computer that should be
# configured as the gateway for whatever network traffic you wish to intercept.
# You then use PacketThief to configure your OS firewall and network routing to
# send specified network traffic to a socket. The socket handling code can then
# read the data, modify it, send it on to the original destination (although the
# new connection will originate from the gateway), etc.
#
# Currently, PacketThief supports basic redirection using Ipfw (Mac OS X, BSD)
# and Netfilter (Linux). It also more than likely requires your PacketThief-based
# script to be run as root in order to modify your system's firewall.
#
# == Usage
#
# First, you must configure the system that will run PacketThief to be able to
# intercept network traffic. If that host system has two network interfaces (such
# as a laptop with ethernet and wifi), then you can turn the system into a router
# by configure one interface to be an external interface that can communicate
# with your main network and the Internet, and the other interface can be
# configured as the gateway for one or more devices/client systems that you would
# like to test.
#
# NATing multiple network interfaces can be easily done in Mac OS X by enabling
# Internet Sharing in the Sharing System Preference pane, which will also let you
# configure your wifi to be a wireless access point. For Linux, take a look at
# the +examples/setup_iptables.sh+ script, or {search the Internet for tutorials
# on various ways to set up Mallory}[https://bitbucket.org/IntrepidusGroup/mallory/wiki/Home].
#
# Basic use:
#
#     require 'packetthief'
#     # redirect tcp traffic destined for port 443 to localhost port 65432:
#     PacketThief.redirect(:to_ports => 65432).where(:protocol => :tcp, :dest_port => 443).run
#     at_exit { PacketThief.revert } # Remove our firewall rules when we exit
#
# This will set up Firewall/routing rules to redirect packets matching the .where
# clause to the localhost port specified by the redirect() clause. The
# Kernel#at_exit handler calls the .revert method which will remove the firewall
# rules added by PacketThief.
#
# You can then capture network traffic in your script by opening a listening
# socket your +:to_ports+ destination. When you create the socket, set the
# hostname to a blank string to have it listen on all interfaces -- this winds up
# being more compatible with different firewalls.
#
# Using a TCPServer:
#
#     TCPServer.new('', 65432)
#
# or (untested):
#
#     TCPServer.new(65432)
#
# Using EventMachine:
#
#     EM.run {
#         start_server '', 65432, MyHandler
#     }
#
#
# In your listener code you can recover the original destination by passing in an
# accepted socket or an EventMachine::Connection-based handler.
#
#     PacketThief.original_dest(socket_or_em_connection)
#
# PacketThief also provides several EventMachine handlers to help build
# interceptors. For example, PacketThief::Handlers::TransparentProxy provides a
# class that allows you to view or mangle arbitrary TCP traffic before passing it
# on to the original destination. The package also includes several handlers for
# dealing with SSL-based traffic. Unlike EventMachine's built-in SSL support
# (#start_tls), PacketThief::Handlers::SSLClient and
# PacketThief::Handlers::SSLServer give you direct access to the
# OpenSSL::SSL::SSLContext to configure certificates and callbacks, and
# PacketThief::Handlers::SSLSmartProxy will connect to the original destination
# in order to acquire its host certificate, which it then modifies for use with a
# configured CA. See the documentation and the example directory for more
# information.
#
# == Mac OS X Setup example
#
# * Share your wifi over your ethernet. Mac OS X will run natd with your wifi as the lan.
# * Connect a mobile or wifi device to this wifi.
# * Run your PacketThief code, and specify `:in_interface => 'en1'` (assuming
#   your Airport/wifi is on en1) in the .where clause. The specified :to_ports
#   port should start receiving incoming TCP connections.
#
# Note that connections initiated both on the Mac and on any device from the
# network will hit your socket. In the future, you will be able to narrow down
# what traffic is caught.
#
module PacketThief
  autoload :RedirectRule, 'packetthief/redirect_rule'
  autoload :Impl,         'packetthief/impl'

  autoload :Handlers, 'packetthief/handlers'
  autoload :Logging,  'packetthief/logging'
  autoload :Util, 'packetthief/util'

  class << self
    include Logging
  end

  def self.logger=(log)
    PacketThief::Logging.logger = log
  end

  def self.logger
    PacketThief::Logging.logger
  end

  def self.implementation; @implementation ; end

  def self.implementation=(newimpl)
    logdebug "Set implementation to: #{newimpl}"
    if newimpl == nil
      @implementation = nil
    elsif newimpl.kind_of? Module
      @implementation = newimpl
    else
      PacketThief::Impl.constants.each do |c|
        if c.downcase.to_sym == newimpl.downcase.to_sym
          @implementation = PacketThief::Impl.const_get c
          return @implementation
        end
      end
      raise AttributeError, "Unknown implementation"
    end
  end

  def self.guess_implementation
    case RUBY_PLATFORM
    when /linux/
      Impl::Netfilter
    when /darwin(10|[0-9]($|[^0]))/ # Mac OS X 10.6 and earlier.
      Impl::Ipfw
    when /darwin(11)/ # Mac OS X 10.7
      Impl::PFRdr
    else
      raise "Platform #{RUBY_PLATFORM} not yet supported! If you know your network implementation, call it directly."
    end
  end

  # Pass the call on to @implementation, or an OS-specific default, if one is known.
  def self.method_missing(m, *args, &block)
    logdebug "method_missing: #{m}", :args => args, :block => block
    if self.implementation == nil
      self.implementation = guess_implementation
    end
    self.implementation.send(m, *args, &block)
  end

  # Quietly ignore .revert calls if implementation is nil.
  def self.revert
    implementation.revert if implementation
  end

end


text:
package org.jreversepro.jls.emitter.java14;

import org.jreversepro.ast.block.Block;
import org.jreversepro.ast.block.MethodBlock;
import org.jreversepro.jls.emitter.EmitterTarget;
import org.jreversepro.jls.emitter.SourceEmitter;

public class DefaultSourceEmitter implements SourceEmitter {

  public String emitCode(Block block) {
    if (!(block instanceof MethodBlock)) {
      throw new IllegalArgumentException(
          "I take only MethodBlocks. Can't take " + block.getClass().getName());
    }
    EmitterTarget target = new EmitterTarget();
    block.getEmitter().emitJLSCode(target, block);
    return target.getEmittedCode();
  }

}


text:
module.exports = function (app,Controller) {

	var routes = {

		"get":[
			{
				"url":"/",
				"description":"Get the List of Blogs"
			},
			{
				url:"/:id",
				"description":"get one blog"
			}
		],
		"post":[
			{
				"url":"/",
				"description":"create a blog",
				"body":["title,content"]
			},
			{
				url:"/:id",
				"description":"Copy a blog over"
			}

		],
		"put":[
			{
				"url":"/:id",
				"description":"Update a blog",
				"body":["title,content"]
			}
		],
		"delete":[
			{
				"url":"/:id",
				"description":"Delete a blog"
			}
		]
	}

	app.param('id',Controller.load);
	app.get('/',Controller.index);
	app.post('/', Controller.create);

	//this will fork the blog
	app.post('/:id', Controller.fork);
	app.get('/:id', Controller.show);
	app.put('/:id', Controller.update);
	//we have to check the request, if it's delete it makes the owner only allowed to delete
	app.delete('/:id', Controller.destroy);

	return routes;

};


text:
package cn.tomoya.config.security;

import cn.tomoya.module.security.core.MyFilterSecurityInterceptor;
import cn.tomoya.module.security.core.MyUserDetailService;
import cn.tomoya.module.security.core.ValidateCodeAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

/**
 * xgb
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	@Autowired
	private MyUserDetailService myUserDetailService;
	@Autowired
	private MyFilterSecurityInterceptor myFilterSecurityInterceptor;
	@Autowired
	private ValidateCodeAuthenticationFilter validateCodeAuthenticationFilter;

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		// 经过权限校验的地址
		http.headers().frameOptions().disable();
		http.authorizeRequests().antMatchers("/static/**").permitAll()
				.antMatchers("/upload", "/UEditor", "/attendance", "/admin/**", "/topic/create", "/topic/*/delete", "/topic/*/edit",
						"/reply/save", "/reply/*/delete", "/reply/*/edit", "/reply/*/up", "/reply/*/cancelUp",
						"/reply/*/down", "/reply/*/cancelDown", "/collect/**", "/notification/**", "/user/profile",
						"/user/changePassword", "/user/accessToken", "/user/refreshToken", "/user/space",
						"/space/deleteFile")
				.authenticated();

		// 管理后台登录
		http.formLogin().successHandler(savedRequestAwareAuthenticationSuccessHandler()).loginPage("/admin/login").loginProcessingUrl("/admin/login").usernameParameter("username").passwordParameter("password")
				.failureUrl("/admin/login?error").defaultSuccessUrl("/admin/index").permitAll();

		// token expired after 30 days
		http.rememberMe().key("remember-me").alwaysRemember(true).tokenValiditySeconds(2592000);

//		http.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/").deleteCookies("JSESSIONID");

		// 管理后台退出
		http.logout().logoutRequestMatcher(new AntPathRequestMatcher("/admin/logout")).logoutSuccessUrl("/admin/login").deleteCookies("JSESSIONID");

		http.addFilterBefore(myFilterSecurityInterceptor, FilterSecurityInterceptor.class);
		http.addFilterBefore(validateCodeAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

		// 不经过权限校验的
		http.csrf().ignoringAntMatchers("/api/**", "/upload", "/UEditor", "/user/space/deleteFile");
	}

	@Override
	public void configure(WebSecurity web) throws Exception {
		web.ignoring().antMatchers("/js/**", "/css/**", "/images/**", "/**/favicon.ico");
	}

	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.userDetailsService(myUserDetailService).passwordEncoder(new BCryptPasswordEncoder());
	}

	@Override
	@Bean
	public AuthenticationManager authenticationManagerBean() throws Exception {
		return super.authenticationManagerBean();
	}

	@Bean
	public SavedRequestAwareAuthenticationSuccessHandler savedRequestAwareAuthenticationSuccessHandler() {
		SavedRequestAwareAuthenticationSuccessHandler auth = new SavedRequestAwareAuthenticationSuccessHandler();
		auth.setTargetUrlParameter("targetUrl");
		return auth;
	}
}


text:
/*
 * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the University of California, Berkeley nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdio.h>
#include <inttypes.h>
#include <ctype.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#include <rte_string_fns.h>

#include "cmdline_parse.h"
#include "cmdline_parse_string.h"

struct cmdline_token_ops cmdline_token_string_ops = {
	.parse = cmdline_parse_string,
	.complete_get_nb = cmdline_complete_get_nb_string,
	.complete_get_elt = cmdline_complete_get_elt_string,
	.get_help = cmdline_get_help_string,
};

#define MULTISTRING_HELP "Mul-choice STRING"
#define ANYSTRING_HELP   "Any STRING"
#define FIXEDSTRING_HELP "Fixed STRING"

static unsigned int
get_token_len(const char *s)
{
	char c;
	unsigned int i=0;

	c = s[i];
	while (c!='#' && c!='\0') {
		i++;
		c = s[i];
	}
	return i;
}

static const char *
get_next_token(const char *s)
{
	unsigned int i;
	i = get_token_len(s);
	if (s[i] == '#')
		return s+i+1;
	return NULL;
}

int
cmdline_parse_string(cmdline_parse_token_hdr_t *tk, const char *buf, void *res)
{
	struct cmdline_token_string *tk2;
	struct cmdline_token_string_data *sd;
	unsigned int token_len;
	const char *str;

	if (!tk || !buf || ! *buf)
		return -1;

	tk2 = (struct cmdline_token_string *)tk;

	sd = &tk2->string_data;

	/* fixed string */
	if (sd->str) {
		str = sd->str;
		do {
			token_len = get_token_len(str);

			/* if token is too big... */
			if (token_len >= STR_TOKEN_SIZE - 1) {
				continue;
			}

			if ( strncmp(buf, str, token_len) ) {
				continue;
			}

			if ( !cmdline_isendoftoken(*(buf+token_len)) ) {
				continue;
			}

			break;
		} while ( (str = get_next_token(str)) != NULL );

		if (!str)
			return -1;
	}
	/* unspecified string */
	else {
		token_len = 0;
		while(!cmdline_isendoftoken(buf[token_len]) &&
		      token_len < (STR_TOKEN_SIZE-1))
			token_len++;

		/* return if token too long */
		if (token_len >= STR_TOKEN_SIZE - 1) {
			return -1;
		}
	}

	if (res) {
		/* we are sure that token_len is < STR_TOKEN_SIZE-1 */
		snprintf(res, STR_TOKEN_SIZE, "%s", buf);
		*((char *)res + token_len) = 0;
	}

	return token_len;
}

int cmdline_complete_get_nb_string(cmdline_parse_token_hdr_t *tk)
{
	struct cmdline_token_string *tk2;
	struct cmdline_token_string_data *sd;
	const char *str;
	int ret = 1;

	if (!tk)
		return -1;

	tk2 = (struct cmdline_token_string *)tk;
	sd = &tk2->string_data;

	if (!sd->str)
		return 0;

	str = sd->str;
	while( (str = get_next_token(str)) != NULL ) {
		ret++;
	}
	return ret;
}

int cmdline_complete_get_elt_string(cmdline_parse_token_hdr_t *tk, int idx,
				    char *dstbuf, unsigned int size)
{
	struct cmdline_token_string *tk2;
	struct cmdline_token_string_data *sd;
	const char *s;
	unsigned int len;

	if (!tk || !dstbuf || idx < 0)
		return -1;

	tk2 = (struct cmdline_token_string *)tk;
	sd = &tk2->string_data;

	s = sd->str;

	while (idx-- && s)
		s = get_next_token(s);

	if (!s)
		return -1;

	len = get_token_len(s);
	if (len > size - 1)
		return -1;

	memcpy(dstbuf, s, len);
	dstbuf[len] = '\0';
	return 0;
}

int cmdline_get_help_string(cmdline_parse_token_hdr_t *tk, char *dstbuf,
			    unsigned int size)
{
	struct cmdline_token_string *tk2;
	struct cmdline_token_string_data *sd;
	const char *s;

	if (!tk || !dstbuf)
		return -1;

	tk2 = (struct cmdline_token_string *)tk;
	sd = &tk2->string_data;

	s = sd->str;

	if (s) {
		if (get_next_token(s))
			snprintf(dstbuf, size, MULTISTRING_HELP);
		else
			snprintf(dstbuf, size, FIXEDSTRING_HELP);
	} else
		snprintf(dstbuf, size, ANYSTRING_HELP);

	return 0;
}


text:
int main(int argc, const char * argv[])
{

    @autoreleasepool {
        NSDate *now = [NSDate date];
        NSCalendar *calendar = [[NSCalendar alloc]
                                initWithCalendarIdentifier:NSGregorianCalendar];
        NSDateComponents *components = [[NSDateComponents alloc] init];
        [components setMonth:1];
        NSDate *oneMonthFromNow = [calendar dateByAddingComponents:components
                                                            toDate:now
                                                           options:0];
        NSLog(@"%@", oneMonthFromNow);
    }
    return 0;
}


text:
USING_NS_CC;
extern "C"

const char* nativeLogin(int platfrom)
{
	JniMethodInfo jmi;
		if(JniHelper::getStaticMethodInfo(jmi , "com/dmzj/manhua/openapi/OpenApiHelper" , "onLogin" , "(I)V"))
		{
			jmi.env->CallStaticVoidMethod(jmi.classID , jmi.methodID , platfrom);
		}
}

void ThreePartyHelper::onThreePartyLogin(int paltform)
{
	nativeLogin(paltform);
}

void ThreePartyHelper::onPartyLoginReturn(int paltform,std::string token)
{

}


text:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

    <title>Porting Python 2 Code to Python 3 — Python 2.7.12 documentation</title>

    <link rel="stylesheet" href="../_static/classic.css" type="text/css" />
    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />

    <link rel="search" type="application/opensearchdescription+xml"
          title="Search within Python 2.7.12 documentation"
          href="../_static/opensearch.xml"/>
    <link rel="author" title="About these documents" href="../about.html" />
    <link rel="copyright" title="Copyright" href="../copyright.html" />
    <link rel="top" title="Python 2.7.12 documentation" href="../contents.html" />
    <link rel="up" title="Python HOWTOs" href="index.html" />
    <link rel="next" title="Porting Extension Modules to Python 3" href="cporting.html" />
    <link rel="prev" title="Python HOWTOs" href="index.html" />
    <link rel="shortcut icon" type="image/png" href="../_static/py.png" />

Navigation

          index

          modules |

          next |

          previous |

Python »

          2.7.12
          Documentation »

Python HOWTOs »

Porting Python 2 Code to Python 3¶

<col class="field-name" />
<col class="field-body" />

author:	Brett Cannon

Abstract

With Python 3 being the future of Python while Python 2 is still in active
use, it is good to have your project available for both major releases of
Python. This guide is meant to help you figure out how best to support both
Python 2 & 3 simultaneously.

If you are looking to port an extension module instead of pure Python code,
please see Porting Extension Modules to Python 3.

If you would like to read one core Python developer’s take on why Python 3
came into existence, you can read Nick Coghlan’s Python 3 Q & A.

For help with porting, you can email the python-porting mailing list with
questions.

The Short Explanation¶

To make your project be single-source Python 2/3 compatible, the basic steps
are:

Update your code to drop support for Python 2.5 or older (supporting only
Python 2.7 is ideal)

Make sure you have good test coverage (coverage.py can help;
pip install coverage)

Learn the differences between Python 2 & 3

Use Modernize or Futurize to update your code (pip install modernize or
pip install future, respectively)

Use Pylint to help make sure you don’t regress on your Python 3 support
(if only supporting Python 2.7/3.4 or newer; pip install pylint)

Use caniusepython3 to find out which of your dependencies are blocking your
use of Python 3 (pip install caniusepython3)

Once your dependencies are no longer blocking you, use continuous integration
to make sure you stay compatible with Python 2 & 3 (tox can help test
against multiple versions of Python; pip install tox)

If you are dropping support for Python 2 entirely, then after you learn the
differences between Python 2 & 3 you can run 2to3 over your code and skip the
rest of the steps outlined above.

Details¶

A key point about supporting Python 2 & 3 simultaneously is that you can start
today! Even if your dependencies are not supporting Python 3 yet that does
not mean you can’t modernize your code now to support Python 3. Most changes
required to support Python 3 lead to cleaner code using newer practices even in
Python 2.

Another key point is that modernizing your Python 2 code to also support
Python 3 is largely automated for you. While you might have to make some API
decisions thanks to Python 3 clarifying text data versus binary data, the
lower-level work is now mostly done for you and thus can at least benefit from
the automated changes immediately.

Keep those key points in mind while you read on about the details of porting
your code to support Python 2 & 3 simultaneously.

Drop support for Python 2.5 and older (at least)¶

While you can make Python 2.5 work with Python 3, it is much easier if you
only have to work with Python 2.6 or newer (and easier still if you only have
to work with Python 2.7). If dropping Python 2.5 is not an option then the six
project can help you support Python 2.5 & 3 simultaneously
(pip install six). Do realize, though, that nearly all the projects listed
in this HOWTO will not be available to you.

If you are able to only support Python 2.6 or newer, then the required changes
to your code should continue to look and feel like idiomatic Python code. At
worst you will have to use a function instead of a method in some instances or
have to import a function instead of using a built-in one, but otherwise the
overall transformation should not feel foreign to you.

But please aim for Python 2.7. Bugfixes for that version of Python will continue
until 2020 while Python 2.6 is no longer supported. There are also some tools
mentioned in this HOWTO which do not support Python 2.6 (e.g., Pylint), and
this will become more commonplace as time goes on.

Make sure you specify the proper version support in your setup.py file¶

In your setup.py file you should have the proper trove classifier
specifying what versions of Python you support. As your project does not support
Python 3 yet you should at least have
Programming Language :: Python :: 2 :: Only specified. Ideally you should
also specify each major/minor version of Python that you do support, e.g.
Programming Language :: Python :: 2.7.

Have good test coverage¶

Once you have your code supporting the oldest version of Python 2 you want it
to, you will want to make sure your test suite has good coverage. A good rule of
thumb is that if you want to be confident enough in your test suite that any
failures that appear after having tools rewrite your code are actual bugs in the
tools and not in your code. If you want a number to aim for, try to get over 80%
coverage (and don’t feel bad if you can’t easily get past 90%). If you
don’t already have a tool to measure test coverage then coverage.py is
recommended.

Learn the differences between Python 2 & 3¶

Once you have your code well-tested you are ready to begin porting your code to
Python 3! But to fully understand how your code is going to change and what
you want to look out for while you code, you will want to learn what changes
Python 3 makes in terms of Python 2. Typically the two best ways of doing that
is reading the “What’s New” doc for each release of Python 3 and the
Porting to Python 3 book (which is free online). There is also a handy
cheat sheet from the Python-Future project.

Update your code¶

Once you feel like you know what is different in Python 3 compared to Python 2,
it’s time to update your code! You have a choice between two tools in porting
your code automatically: Modernize and Futurize. Which tool you choose will
depend on how much like Python 3 you want your code to be. Futurize does its
best to make Python 3 idioms and practices exist in Python 2, e.g. backporting
the bytes type from Python 3 so that you have semantic parity between the
major versions of Python. Modernize,
on the other hand, is more conservative and targets a Python 2/3 subset of
Python, relying on six to help provide compatibility.

Regardless of which tool you choose, they will update your code to run under
Python 3 while staying compatible with the version of Python 2 you started with.
Depending on how conservative you want to be, you may want to run the tool over
your test suite first and visually inspect the diff to make sure the
transformation is accurate. After you have transformed your test suite and
verified that all the tests still pass as expected, then you can transform your
application code knowing that any tests which fail is a translation failure.

Unfortunately the tools can’t automate everything to make your code work under
Python 3 and so there are a handful of things you will need to update manually
to get full Python 3 support (which of these steps are necessary vary between
the tools). Read the documentation for the tool you choose to use to see what it
fixes by default and what it can do optionally to know what will (not) be fixed
for you and what you may have to fix on your own (e.g. using io.open() over
the built-in open() function is off by default in Modernize). Luckily,
though, there are only a couple of things to watch out for which can be
considered large issues that may be hard to debug if not watched for.

Division¶

In Python 3, 5 / 2 == 2.5 and not 2; all division between int values
result in a float. This change has actually been planned since Python 2.2
which was released in 2002. Since then users have been encouraged to add
from __future__ import division to any and all files which use the / and
// operators or to be running the interpreter with the -Q flag. If you
have not been doing this then you will need to go through your code and do two
things:

Add from __future__ import division to your files

Update any division operator as necessary to either use // to use floor
division or continue using / and expect a float

The reason that / isn’t simply translated to // automatically is that if
an object defines its own __div__ method but not __floordiv__ then your
code would begin to fail.

Text versus binary data¶

In Python 2 you could use the str type for both text and binary data.
Unfortunately this confluence of two different concepts could lead to brittle
code which sometimes worked for either kind of data, sometimes not. It also
could lead to confusing APIs if people didn’t explicitly state that something
that accepted str accepted either text or binary data instead of one
specific type. This complicated the situation especially for anyone supporting
multiple languages as APIs wouldn’t bother explicitly supporting unicode
when they claimed text data support.

To make the distinction between text and binary data clearer and more
pronounced, Python 3 did what most languages created in the age of the internet
have done and made text and binary data distinct types that cannot blindly be
mixed together (Python predates widespread access to the internet). For any code
that only deals with text or only binary data, this separation doesn’t pose an
issue. But for code that has to deal with both, it does mean you might have to
now care about when you are using text compared to binary data, which is why
this cannot be entirely automated.

To start, you will need to decide which APIs take text and which take binary
(it is highly recommended you don’t design APIs that can take both due to
the difficulty of keeping the code working; as stated earlier it is difficult to
do well). In Python 2 this means making sure the APIs that take text can work
with unicode in Python 2 and those that work with binary data work with the
bytes type from Python 3 and thus a subset of str in Python 2 (which the
bytes type in Python 2 is an alias for). Usually the biggest issue is
realizing which methods exist for which types in Python 2 & 3 simultaneously
(for text that’s unicode in Python 2 and str in Python 3, for binary
that’s str/bytes in Python 2 and bytes in Python 3). The following
table lists the unique methods of each data type across Python 2 & 3
(e.g., the decode() method is usable on the equivalent binary data type in
either Python 2 or 3, but it can’t be used by the text data type consistently
between Python 2 and 3 because str in Python 3 doesn’t have the method).

<colgroup>
<col width="53%" />
<col width="47%" />
</colgroup>

Text data
Binary data

__mod__ (% operator)

decode

encode

format

isdecimal

isnumeric

Making the distinction easier to handle can be accomplished by encoding and
decoding between binary data and text at the edge of your code. This means that
when you receive text in binary data, you should immediately decode it. And if
your code needs to send text as binary data then encode it as late as possible.
This allows your code to work with only text internally and thus eliminates
having to keep track of what type of data you are working with.

The next issue is making sure you know whether the string literals in your code
represent text or binary data. At minimum you should add a b prefix to any
literal that presents binary data. For text you should either use the
from __future__ import unicode_literals statement or add a u prefix to
the text literal.

As part of this dichotomy you also need to be careful about opening files.
Unless you have been working on Windows, there is a chance you have not always
bothered to add the b mode when opening a binary file (e.g., rb for
binary reading).  Under Python 3, binary files and text files are clearly
distinct and mutually incompatible; see the io module for details.
Therefore, you must make a decision of whether a file will be used for
binary access (allowing binary data to be read and/or written) or text access
(allowing text data to be read and/or written). You should also use io.open()
for opening files instead of the built-in open() function as the io
module is consistent from Python 2 to 3 while the built-in open() function
is not (in Python 3 it’s actually io.open()).

The constructors of both str and bytes have different semantics for the
same arguments between Python 2 & 3. Passing an integer to bytes in Python 2
will give you the string representation of the integer: bytes(3) == '3'.
But in Python 3, an integer argument to bytes will give you a bytes object
as long as the integer specified, filled with null bytes:
bytes(3) == b'\x00\x00\x00'. A similar worry is necessary when passing a
bytes object to str. In Python 2 you just get the bytes object back:
str(b'3') == b'3'. But in Python 3 you get the string representation of the
bytes object: str(b'3') == "b'3'".

Finally, the indexing of binary data requires careful handling (slicing does
not require any special handling). In Python 2,
b'123'[1] == b'2' while in Python 3 b'123'[1] == 50. Because binary data
is simply a collection of binary numbers, Python 3 returns the integer value for
the byte you index on. But in Python 2 because bytes == str, indexing
returns a one-item slice of bytes. The six project has a function
named six.indexbytes() which will return an integer like in Python 3:
six.indexbytes(b'123', 1).

To summarize:

Decide which of your APIs take text and which take binary data

Make sure that your code that works with text also works with unicode and
code for binary data works with bytes in Python 2 (see the table above
for what methods you cannot use for each type)

Mark all binary literals with a b prefix, use a u prefix or
__future__ import statement for text literals

Decode binary data to text as soon as possible, encode text as binary data as
late as possible

Open files using io.open() and make sure to specify the b mode when
appropriate

Be careful when indexing binary data

Prevent compatibility regressions¶

Once you have fully translated your code to be compatible with Python 3, you
will want to make sure your code doesn’t regress and stop working under
Python 3. This is especially true if you have a dependency which is blocking you
from actually running under Python 3 at the moment.

To help with staying compatible, any new modules you create should have
at least the following block of code at the top of it:

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

You can also run Python 2 with the -3 flag to be warned about various
compatibility issues your code triggers during execution. If you turn warnings
into errors with -Werror then you can make sure that you don’t accidentally
miss a warning.

You can also use the Pylint project and its --py3k flag to lint your code
to receive warnings when your code begins to deviate from Python 3
compatibility. This also prevents you from having to run Modernize or Futurize
over your code regularly to catch compatibility regressions. This does require
you only support Python 2.7 and Python 3.4 or newer as that is Pylint’s
minimum Python version support.

Check which dependencies block your transition¶

After you have made your code compatible with Python 3 you should begin to
care about whether your dependencies have also been ported. The caniusepython3
project was created to help you determine which projects
– directly or indirectly – are blocking you from supporting Python 3. There
is both a command-line tool as well as a web interface at
https://caniusepython3.com .

The project also provides code which you can integrate into your test suite so
that you will have a failing test when you no longer have dependencies blocking
you from using Python 3. This allows you to avoid having to manually check your
dependencies and to be notified quickly when you can start running on Python 3.

Update your setup.py file to denote Python 3 compatibility¶

Once your code works under Python 3, you should update the classifiers in
your setup.py to contain Programming Language :: Python :: 3 and to not
specify sole Python 2 support. This will tell
anyone using your code that you support Python 2 and 3. Ideally you will
also want to add classifiers for each major/minor version of Python you now
support.

Use continuous integration to stay compatible¶

Once you are able to fully run under Python 3 you will want to make sure your
code always works under both Python 2 & 3. Probably the best tool for running
your tests under multiple Python interpreters is tox. You can then integrate
tox with your continuous integration system so that you never accidentally break
Python 2 or 3 support.

You may also want to use the -bb flag with the Python 3 interpreter to
trigger an exception when you are comparing bytes to strings. Usually it’s
simply False, but if you made a mistake in your separation of text/binary
data handling you may be accidentally comparing text and binary data. This flag
will raise an exception when that occurs to help track down such cases.

And that’s mostly it! At this point your code base is compatible with both
Python 2 and 3 simultaneously. Your testing will also be set up so that you
don’t accidentally break Python 2 or 3 compatibility regardless of which version
you typically run your tests under while developing.

Dropping Python 2 support completely¶

If you are able to fully drop support for Python 2, then the steps required
to transition to Python 3 simplify greatly.

Update your code to only support Python 2.7

Make sure you have good test coverage (coverage.py can help)

Learn the differences between Python 2 & 3

Use 2to3 to rewrite your code to run only under Python 3

After this your code will be fully Python 3 compliant but in a way that is not
supported by Python 2. You should also update the classifiers in your
setup.py to contain Programming Language :: Python :: 3 :: Only.

Table Of Contents

Porting Python 2 Code to Python 3

The Short Explanation

Details

Drop support for Python 2.5 and older (at least)

Make sure you specify the proper version support in your setup.py file

Have good test coverage

Learn the differences between Python 2 & 3

Update your code

Division

Text versus binary data

Prevent compatibility regressions

Check which dependencies block your transition

Update your setup.py file to denote Python 3 compatibility

Use continuous integration to stay compatible

Dropping Python 2 support completely

Previous topic

Python HOWTOs

Next topic

Porting Extension Modules to Python 3

This Page

Report a Bug

Show Source

Quick search

    <form class="search" action="../search.html" method="get">
      <input type="text" name="q" />
      <input type="submit" value="Go" />
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>

    Enter search terms or a module, class or function name.

Navigation

          index

          modules |

          next |

          previous |

Python »

          2.7.12
          Documentation »

Python HOWTOs »

    © Copyright 1990-2016, Python Software Foundation.

    The Python Software Foundation is a non-profit corporation.
    Please donate.

    Last updated on Jun 25, 2016.
    Found a bug?

    Created using Sphinx 1.3.3.


text:
proximity_mapping = {
    'q': ['a', 's', 'w', '2', '1', '`'],
    'w': ['q', 'a', 's', 'd', 'e', '3', '2', '1'],
    'e': ['w', 's', 'd', 'f', 'r', '4', '3', '2'],
    'r': ['e', 'd', 'f', 'g', 't', '5', '4', '3'],
    't': ['r', 'f', 'g', 'h', 'y', '6', '5', '4'],
    'y': ['t', 'g', 'h', 'j', 'u', '7', '6', '5'],
    'u': ['y', 'h', 'j', 'k', 'i', '8', '7', '6'],
    'i': ['u', 'j', 'k', 'l', 'o', '9', '8', '7'],
    'o': ['i', 'k', 'l', ';', 'p', '0', '9', '8'],
    'p': ['o', 'l', ';', '\'', '[', '-', '0', '9'],
    '[': ['p', ';', '\'', ']', '=', '-', '0'],
    ']': ['[', '\'', '\\', '='],

    'a': ['z', 'x', 's',           'w', 'q'],
    's': ['a', 'z', 'x', 'c', 'd', 'e', 'w', 'q'],
    'd': ['s', 'x', 'c', 'v', 'f', 'r', 'e', 'w'],
    'f': ['d', 'c', 'v', 'b', 'g', 't', 'r', 'e'],
    'g': ['f', 'v', 'b', 'n', 'h', 'y', 't', 'r'],
    'h': ['g', 'b', 'n', 'm', 'j', 'u', 'y', 't'],
    'j': ['h', 'n', 'm', ',', 'k', 'i', 'u', 'y'],
    'k': ['j', 'm', ',', '.', 'l', 'o', 'i', 'u'],
    'l': ['k', ',', '.', '/', ';', 'p', 'o', 'i'],
    ';': ['l', '.', '/', '\'', '[', 'p'],
    '\'': [';', '/', ']', '[', 'p'],

    'z': [     'x', 's', 'a'],
    'x': ['z', 'c', 'd', 's', 'a'],
    'c': ['x', 'v', 'f', 'd', 's'],
    'v': ['c', 'b', 'g', 'f', 'd'],
    'b': ['v', 'n', 'h', 'g', 'f'],
    'n': ['b', 'm', 'j', 'h', 'g'],
    'm': ['n', ',', 'k', 'j', 'h'],

    '1': ['q', 'w', '2', '`'],
    '2': ['1', 'q', 'w', 'e', '3'],
    '3': ['2', 'w', 'e', 'r', '4'],
    '4': ['3', 'e', 'r', 't', '5'],
    '5': ['4', 'r', 't', 'y', '6'],
    '6': ['5', 't', 'y', 'u', '7'],
    '7': ['6', 'y', 'u', 'i', '8'],
    '8': ['7', 'u', 'i', 'o', '9'],
    '9': ['8', 'i', 'o', 'p', '0'],
    '0': ['9', 'o', 'p', '[', '-'],
    '-': ['0', 'p', '[', ']', '='],
    '+': ['-', '[', ']', '\\']
}

# version 1 variables
max_extra = 1  # input has extra characters
max_missing = -1  # input has less characters

class MatchStats(object):
    def __init__(self, item, disparity):
        self.match = 0
        self.proximity = 0
        self.disparity = disparity
        self.item = item
        self.too_disparate = False
        self.missing = 0

    def increment_match(self):
        self.match += 1

    def increment_proximity(self):
        self.proximity += 1

    def increment_proximity(self):
        self.proximity += 1

    def increment_missing(self):
        self.missing += 1

    def compare(self, other_instance):
        if other_instance is None:
            return self

        if self.proximity > other_instance.proximity:
            return other_instance
        elif self.proximity < other_instance.proximity:
            return self
        else:
            if self.match > other_instance.match:
                return self
            elif self.match < other_instance.match:
                return other_instance
            else:
                if self.disparity > other_instance.disparity:
                    return other_instance
                else:
                    return self

class BetterMatchStats(object):
    # version 2 & 3 variables
    max_sequential_disparity = 2

    def __init__(self, matchterm):
        self.match = 0
        self.proximity = 0
        self.disparity = 0
        self.sequential_disparity = 0
        self.matchterm = matchterm
        self.too_disparate = False
        self.runner_up_score = 0
        self.runner_up_matchterm = ''

    def increment_match(self):
        self.match += 1
        self._reset_sequential_disparity()

    def increment_proximity(self):
        self.proximity += 1
        self._reset_sequential_disparity()

    def increment_disparity(self):
        self.disparity += 1
        self._increment_sequential_disparity()
        if self.disparity > len(self.matchterm):
            self.too_disparate = True

    def _increment_sequential_disparity(self):
        self.sequential_disparity += 1
        if self.sequential_disparity > BetterMatchStats.max_sequential_disparity:
            self.too_disparate = True

    def _reset_sequential_disparity(self):
        self.sequential_disparity = 0

    def get_score(self):
        if self.disparity == 0 and self.proximity == 0:
            return 100
        else:
            return 100 - ((self.disparity * 2) + self.proximity)

    def compare(self, other_instance):
        if other_instance is None or other_instance.too_disparate:
            return self

        if self.too_disparate:
            other_instance.runner_up_score = self.get_score()
            other_instance.runner_up_matchterm = self.matchterm
            return other_instance

        if self.disparity > other_instance.disparity:
            other_instance.runner_up_score = self.get_score()
            other_instance.runner_up_matchterm = self.matchterm
            return other_instance
        elif self.disparity < other_instance.disparity:
            return self

        if self.match > other_instance.match:
            return self
        elif self.match < other_instance.match:
            other_instance.runner_up_score = self.get_score()
            other_instance.runner_up_matchterm = self.matchterm
            return other_instance

        if self.proximity > other_instance.proximity:
            other_instance.runner_up_score = self.get_score()
            other_instance.runner_up_matchterm = self.matchterm
            return other_instance
        else:
            return self

    def copy_attributes(self, other_instance):
        self.match = other_instance.match
        self.proximity = other_instance.proximity
        self.disparity = other_instance.disparity
        self.sequential_disparity = other_instance.sequential_disparity
        self.too_disparate = other_instance.too_disparate

    @classmethod
    def copy(cls, obj):
        instance = BetterMatchStats(obj.matchterm)
        instance.match = obj.match
        instance.proximity = obj.proximity
        instance.disparity = obj.disparity
        instance.sequential_disparity = obj.sequential_disparity
        instance.too_disparate = obj.too_disparate
        return instance

def is_in_proximity(char1, char2):
    if char2 in proximity_mapping[char1]:
        return True
    else:
        return False

# version 1
def getbestmatch_v1(input_, list_):
    input_ = input_.lower()
    matchstats_best = None
    for item in list_:
        item = item.lower()
        disparity = len(input_) - len(item)
        # ensure disparity isn't too great
        if disparity < max_missing or disparity > max_extra:
            continue

        inner = input_
        outer = item
        if disparity < 0:
            inner = input_
            outer = item
        elif disparity > 0:
            inner = item
            outer = input_

        # now we put the smaller as the inner to move around
        # so we use the absolute val of disparity to
        # put the smaller through the scenarios

        for i in range(0, abs(disparity) + 1):
            outer_subset = outer[i:]
            matchstats = MatchStats(item, abs(disparity))

            # loop through characters and compare them
            for j, inner_char in enumerate(inner):
                if inner_char == outer_subset[j]:
                    matchstats.increment_match()
                    continue
                elif is_in_proximity(inner_char, outer_subset[j]):
                    matchstats.increment_proximity()
                    continue
                else:
                    matchstats.too_disparate = True
                    break

            if not matchstats.too_disparate:
                matchstats_best = matchstats.compare(matchstats_best)

    if matchstats_best is None:
        return None
    else:
        return matchstats_best.item

# version 2
def getbestmatch_v2(input_, list_):
    # case insenitive matching
    input_ = input_.lower()

    # stores best match so far
    current_matchstats_best = None

    # iterate through all the possible matchterms
    # to find the best match
    for matchterm in list_:

        # case insenitive matching
        matchterm = matchterm.lower()

        # ensure disparity isn't too great from the get go
        # by comparing overall length, if it is too disparate
        # then move on to the next matchterm
        # if abs(len(input_) - len(matchterm)) > max_sequential_disparity:
        #     continue

        # create object to hold the match stats
        matchstats = BetterMatchStats(matchterm)

        # run the input_ and matchterm through
        # scenarios find a potential match
        matchup_v2(input_, matchterm, matchstats)

        # done with while because we hit the end of an index
        # now let's calculate the leftover disparity
        max_char_len = 0
        if len(input_) > len(matchterm):
            max_char_len = len(input_)
        else:
            max_char_len = len(matchterm)
        for i in (range(0, abs(max_char_len - (matchstats.match + matchstats.proximity + matchstats.disparity)))):
            matchstats.increment_disparity()

        # compare the matchstats after matchup with the current best matchstats
        # and set the better of the two to the best match so far
        # -- may the best match win...
        current_matchstats_best = matchstats.compare(current_matchstats_best)

    return current_matchstats_best.matchterm

def matchup_v2(input_, matchterm, matchstats, depth=0):
    input_index = 0
    matchterm_index = 0
    while matchterm_index <  len(matchterm) and input_index < len(input_):
        if input_[input_index] == matchterm[matchterm_index]:
            matchstats.increment_match()
            input_index = input_index + 1
            matchterm_index = matchterm_index + 1
            continue
        elif is_in_proximity(input_[input_index], matchterm[matchterm_index]):
            matchstats.increment_proximity()
            input_index = input_index + 1
            matchterm_index = matchterm_index + 1
        else:
            # increment disparity and check if we are too disparate
            matchstats.increment_disparity()
            if matchstats.too_disparate:
                return

            # here we need to branch and try both the possibility that input_ has
            # missing or extra chars, then compare the two branches to pick the
            # best matchup

            # input_ may have bad chars, similar to the proximity solution,
            # but treats it as a disparity
            bad_char_scenario = None
            if input_index + 1 <= len(input_) and matchterm_index + 1 <= len(matchterm):
                bad_char_scenario = BetterMatchStats.copy(matchstats)
                matchup_v2(input_[input_index + 1:], matchterm[matchterm_index + 1:], bad_char_scenario, depth=depth+1)

            # input_ may have missing chars
            missing_char_scenario = None
            if matchterm_index + 1 <= len(matchterm):
                missing_char_scenario = BetterMatchStats.copy(matchstats)
                matchup_v2(input_[input_index:], matchterm[matchterm_index + 1:], missing_char_scenario, depth=depth+1)

            # input_ may have extra chars
            extra_char_scenario = None
            if input_index + 1 <= len(input_):
                extra_char_scenario = BetterMatchStats.copy(matchstats)
                matchup_v2(input_[input_index + 1:], matchterm[matchterm_index:], extra_char_scenario, depth=depth+1)

            # if both the input_ and matchterm have reached the end of their input_
            # then return
            if input_index + 1 >= len(input_) and matchterm_index + 1 >= len(matchterm):
                return

            # grab either one that is not None and compare to the other
            # one, which may be None, but one of these scenarios is
            # guaranteed to not be None by this point
            best_scenario = None
            if missing_char_scenario is not None:
                best_scenario = missing_char_scenario.compare(extra_char_scenario)
            else:
                best_scenario = extra_char_scenario.compare(missing_char_scenario)

            # compare the winner of missing vs extra with the bad chars scenario
            best_scenario = best_scenario.compare(bad_char_scenario)

            # copy the attributes from the best scenario
            # because simply setting the object makes the
            # root caller lose the changes
            matchstats.copy_attributes(best_scenario)
            return

            # investigate this
            # >> veweerython
            # Did you mean "deleteprop"?

# version 3
def getbestmatch_v3(input_, list_, set_max_sequential_disparity=None):
    # case insenitive matching
    input_ = input_.lower()

    # stores best match so far
    current_matchstats_best = None

    if set_max_sequential_disparity is not None:
        BetterMatchStats.max_sequential_disparity = set_max_sequential_disparity

    # iterate through all the possible matchterms
    # to find the best match
    for matchterm in list_:

        # case insenitive matching
        matchterm = matchterm.lower()

        # ensure disparity isn't too great from the get go
        # by comparing overall length, if it is too disparate
        # then move on to the next matchterm
        # if abs(len(input_) - len(matchterm)) > max_sequential_disparity:
        #     continue

        # create object to hold the match stats
        matchstats = BetterMatchStats(matchterm)

        if len(input_) > len(matchterm):
            max_char_len = len(input_)
            inner = matchterm
            outer = input_
        else:
            max_char_len = len(matchterm)
            inner = input_
            outer = matchterm

        # run the input_ and matchterm through
        # scenarios find a potential match
        matchup_v3(inner, outer, matchstats)

        for i in (range(0, abs(max_char_len - (matchstats.match + matchstats.proximity + matchstats.disparity)))):
            matchstats.disparity = matchstats.disparity + 1

        # compare the matchstats after matchup with the current best matchstats
        # and set the better of the two to the best match so far
        # -- may the best match win...
        current_matchstats_best = matchstats.compare(current_matchstats_best)

        # >> testmatch hooman human humous humid
        # humid 90  0

    return current_matchstats_best

def matchup_v3(input_, matchterm, matchstats, depth=0):
    input_index = 0
    matchterm_index = 0
    while matchterm_index <  len(matchterm) and input_index < len(input_):
        if input_[input_index] == matchterm[matchterm_index]:
            matchstats.increment_match()
            input_index = input_index + 1
            matchterm_index = matchterm_index + 1
            continue
        elif is_in_proximity(input_[input_index], matchterm[matchterm_index]):
            matchstats.increment_proximity()
            input_index = input_index + 1
            matchterm_index = matchterm_index + 1
        else:
            # increment disparity and check if we are too disparate
            matchstats.increment_disparity()
            if matchstats.too_disparate:
                return

            # here we need to branch and try both the possibility that input_ has
            # missing or extra chars, then compare the two branches to pick the
            # best matchup

            # input_ may have bad chars, similar to the proximity solution,
            # but treats it as a disparity
            bad_char_scenario = None
            if input_index + 1 <= len(input_) and matchterm_index + 1 <= len(matchterm):
                bad_char_scenario = BetterMatchStats.copy(matchstats)
                matchup_v3(input_[input_index + 1:], matchterm[matchterm_index + 1:], bad_char_scenario, depth=depth+1)

            # input_ may have missing chars
            missing_char_scenario = None
            if matchterm_index + 1 <= len(matchterm):
                missing_char_scenario = BetterMatchStats.copy(matchstats)
                matchup_v3(input_[input_index:], matchterm[matchterm_index + 1:], missing_char_scenario, depth=depth+1)

            # input_ may have extra chars
            extra_char_scenario = None
            if input_index + 1 <= len(input_):
                extra_char_scenario = BetterMatchStats.copy(matchstats)
                matchup_v3(input_[input_index + 1:], matchterm[matchterm_index:], extra_char_scenario, depth=depth+1)

            # if both the input_ and matchterm have reached the end of their input_
            # then return
            if input_index + 1 >= len(input_) and matchterm_index + 1 >= len(matchterm):
                return

            # grab either one that is not None and compare to the other
            # one, which may be None, but one of these scenarios is
            # guaranteed to not be None by this point
            best_scenario = None
            if missing_char_scenario is not None:
                best_scenario = missing_char_scenario.compare(extra_char_scenario)
            else:
                best_scenario = extra_char_scenario.compare(missing_char_scenario)

            # compare the winner of missing vs extra with the bad chars scenario
            best_scenario = best_scenario.compare(bad_char_scenario)

            # copy the attributes from the best scenario
            # because simply setting the object makes the
            # root caller lose the changes
            matchstats.copy_attributes(best_scenario)
            return


text:
'use strict';

const { spy } = require('sinon');

/**
 * creates a cron-parser stub
 * @param {Object} config - stub configuration
 * @param {Object} config.parseExpression - method configuration
 * @param {Error} [config.parseExpression.err] - method error
 * @returns {Object} - cron-parser stub
 */
module.exports = (config = {}) => {
  function parseExpression () {
    const { data, err } = config.parseExpression || {};
    if (err) throw err;
    return data;
  }

  return { parseExpression: spy(parseExpression) };
};