<|start_filename|>codeview/src/main/java/io/github/kbiakov/codeview/highlight/FontCache.java<|end_filename|>
package io.github.kbiakov.codeview.highlight;

import android.content.Context;
import android.graphics.Typeface;
import android.util.Log;

import java.util.Map;
import java.util.WeakHashMap;

import io.github.kbiakov.codeview.adapters.AbstractCodeAdapter;

/**
 * Font cache.
 *
 * @see AbstractCodeAdapter
 * @author <NAME>
 */
public class FontCache {

    private static volatile FontCache instance;

    public static FontCache get(Context context) {
        FontCache localInstance = instance;
        if (localInstance == null) {
            synchronized (FontCache.class) {
                localInstance = instance;
                if (localInstance == null) {
                    instance = localInstance = new FontCache(context);
                }
            }
        }
        return localInstance;
    }

    private Map<String, Typeface> fonts;

    private FontCache(final Context context) {
        this.fonts = new WeakHashMap<String, Typeface>() {{
            String fontPath = getLocalFontPath(Font.Companion.getDefault());
            put(fontPath, loadFont(context, fontPath));
        }};
    }

    private static String getLocalFontPath(Font font) {
        return String.format("%s.ttf", getLocalFontPath(font.name()));
    }

    private static String getLocalFontPath(String fontName) {
        return String.format("fonts/%s", fontName);
    }

    private static Typeface loadFont(Context context, String fontPath) {
        return Typeface.createFromAsset(context.getAssets(), fontPath);
    }

    // - Public methods

    public Typeface getTypeface(Context context) {
        return getTypeface(context, Font.Companion.getDefault());
    }

    public Typeface getTypeface(Context context, Font font) {
        return getTypeface(context, getLocalFontPath(font));
    }

    public Typeface getLocalTypeface(Context context, String fontPath) {
        return getTypeface(context, getLocalFontPath(fontPath));
    }

    public Typeface getTypeface(Context context, String fontPath) {
        Typeface font = fonts.get(fontPath);
        if (font != null) {
            return font;
        } else {
            font = loadFont(context, fontPath);
            fonts.put(fontPath, font);
            return font;
        }
    }

    public void saveTypeface(Typeface fontTypeface) {
        fonts.put(fontTypeface.toString(), fontTypeface);
    }
}


<|start_filename|>codeview/src/main/java/io/github/kbiakov/codeview/highlight/prettify/lang/package-info.java<|end_filename|>
/**
 * All languages that comes with release.
 */
package prettify.lang;

<|start_filename|>codeview/src/main/java/io/github/kbiakov/codeview/highlight/prettify/lang/LangErlang.java<|end_filename|>
// Copyright (C) 2013 <NAME>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package io.github.kbiakov.codeview.highlight.prettify.lang;

import io.github.kbiakov.codeview.highlight.prettify.parser.Prettify;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;

/**
 * This is similar to the lang-erlang.js in JavaScript Prettify.
 * <p/>
 * All comments are adapted from the JavaScript Prettify.
 * <p/>
 * <p/>
 * <p/>
 * Derived from https://raw.github.com/erlang/otp/dev/lib/compiler/src/core_parse.yrl
 * Modified from Mike Samuel's Haskell plugin for google-code-prettify
 *
 * @author <EMAIL>
 */
public class LangErlang extends Lang {

    public LangErlang() {
        List<List<Object>> _shortcutStylePatterns = new ArrayList<List<Object>>();
        List<List<Object>> _fallthroughStylePatterns = new ArrayList<List<Object>>();

        // Whitespace
        // whitechar    ->    newline | vertab | space | tab | uniWhite
        // newline      ->    return linefeed | return | linefeed | formfeed
        _shortcutStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_PLAIN, Pattern.compile("\\t\\n\\x0B\\x0C\\r ]+"), null, "\t\n" + Character.toString((char) 0x0B) + Character.toString((char) 0x0C) + "\r "}));
        // Single line double-quoted strings.
        _shortcutStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_STRING, Pattern.compile("^\\\"(?:[^\\\"\\\\\\n\\x0C\\r]|\\\\[\\s\\S])*(?:\\\"|$)"), null, "\""}));

        // Handle atoms
        _shortcutStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_LITERAL, Pattern.compile("^[a-z][a-zA-Z0-9_]*")}));
        // Handle single quoted atoms
        _shortcutStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_LITERAL, Pattern.compile("^\\'(?:[^\\'\\\\\\n\\x0C\\r]|\\\\[^&])+\\'?"), null, "'"}));

        // Handle macros. Just to be extra clear on this one, it detects the ?
        // then uses the regexp to end it so be very careful about matching
        // all the terminal elements
        _shortcutStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_LITERAL, Pattern.compile("^\\?[^ \\t\\n({]+"), null, "?"}));

        // decimal      ->    digit{digit}
        // octal        ->    octit{octit}
        // hexadecimal  ->    hexit{hexit}
        // integer      ->    decimal
        //               |    0o octal | 0O octal
        //               |    0x hexadecimal | 0X hexadecimal
        // float        ->    decimal . decimal [exponent]
        //               |    decimal exponent
        // exponent     ->    (e | E) [+ | -] decimal
        _shortcutStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_LITERAL, Pattern.compile("^(?:0o[0-7]+|0x[\\da-f]+|\\d+(?:\\.\\d+)?(?:e[+\\-]?\\d+)?)", Pattern.CASE_INSENSITIVE), null, "0123456789"}));


        // TODO: catch @declarations inside comments

        // Comments in erlang are started with % and go till a newline
        _fallthroughStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_COMMENT, Pattern.compile("^%[^\\n\\r]*")}));

         // Catch macros
         //[PR['PR_TAG'], /?[^( \n)]+/],

        /**
         * %% Keywords (atoms are assumed to always be single-quoted).
         * 'module' 'attributes' 'do' 'let' 'in' 'letrec'
         * 'apply' 'call' 'primop'
         * 'case' 'of' 'end' 'when' 'fun' 'try' 'catch' 'receive' 'after'
         */
        _fallthroughStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_KEYWORD, Pattern.compile("^(?:module|attributes|do|let|in|letrec|apply|call|primop|case|of|end|when|fun|try|catch|receive|after|char|integer|float,atom,string,var)\\b")}));

        /**
         * Catch definitions (usually defined at the top of the file)
         * Anything that starts -something
         */
        _fallthroughStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_KEYWORD, Pattern.compile("^-[a-z_]+")}));

        // Catch variables
        _fallthroughStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_TYPE, Pattern.compile("^[A-Z_][a-zA-Z0-9_]*")}));

        // matches the symbol production
        _fallthroughStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_PUNCTUATION, Pattern.compile("^[.,;]")}));

        setShortcutStylePatterns(_shortcutStylePatterns);
        setFallthroughStylePatterns(_fallthroughStylePatterns);
    }

    public static List<String> getFileExtensions() {
        return Arrays.asList(new String[]{"erlang", "erl"});
    }
}


<|start_filename|>codeview/src/main/java/io/github/kbiakov/codeview/highlight/prettify/lang/Lang.java<|end_filename|>
// Copyright (C) 2011 <NAME>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package io.github.kbiakov.codeview.highlight.prettify.lang;

import java.util.ArrayList;
import java.util.List;

/**
 * Lang class for Java Prettify.
 * Note that the method {@link #getFileExtensions()} should be overridden.
 * 
 * @author <NAME> <<EMAIL>>
 */
public abstract class Lang {

  /**
   * Similar to those in JavaScript prettify.js.
   */
  protected List<List<Object>> shortcutStylePatterns;
  /**
   * Similar to those in JavaScript prettify.js.
   */
  protected List<List<Object>> fallthroughStylePatterns;
  /**
   * See {@link io.github.kbiakov.codeview.highlight.prettify.lang.LangCss} for example.
   */
  protected List<Lang> extendedLangs;

  /**
   * Constructor.
   */
  public Lang() {
    shortcutStylePatterns = new ArrayList<List<Object>>();
    fallthroughStylePatterns = new ArrayList<List<Object>>();
    extendedLangs = new ArrayList<Lang>();
  }

  /**
   * This method should be overridden by the child class.
   * This provide the file extensions list to help the parser to determine which 
   * {@link Lang} to use. See JavaScript prettify.js.
   * 
   * @return the list of file extensions
   */
  public static List<String> getFileExtensions() {
    return new ArrayList<String>();
  }

  public List<List<Object>> getShortcutStylePatterns() {
    List<List<Object>> returnList = new ArrayList<List<Object>>();
    for (List<Object> shortcutStylePattern : shortcutStylePatterns) {
      returnList.add(new ArrayList<Object>(shortcutStylePattern));
    }
    return returnList;
  }

  public void setShortcutStylePatterns(List<List<Object>> shortcutStylePatterns) {
    if (shortcutStylePatterns == null) {
      this.shortcutStylePatterns = new ArrayList<List<Object>>();
      return;
    }
    List<List<Object>> cloneList = new ArrayList<List<Object>>();
    for (List<Object> shortcutStylePattern : shortcutStylePatterns) {
      cloneList.add(new ArrayList<Object>(shortcutStylePattern));
    }
    this.shortcutStylePatterns = cloneList;
  }

  public List<List<Object>> getFallthroughStylePatterns() {
    List<List<Object>> returnList = new ArrayList<List<Object>>();
    for (List<Object> fallthroughStylePattern : fallthroughStylePatterns) {
      returnList.add(new ArrayList<Object>(fallthroughStylePattern));
    }
    return returnList;
  }

  public void setFallthroughStylePatterns(List<List<Object>> fallthroughStylePatterns) {
    if (fallthroughStylePatterns == null) {
      this.fallthroughStylePatterns = new ArrayList<List<Object>>();
      return;
    }
    List<List<Object>> cloneList = new ArrayList<List<Object>>();
    for (List<Object> fallthroughStylePattern : fallthroughStylePatterns) {
      cloneList.add(new ArrayList<Object>(fallthroughStylePattern));
    }
    this.fallthroughStylePatterns = cloneList;
  }

  /**
   * Get the extended languages list.
   * @return the list
   */
  public List<Lang> getExtendedLangs() {
    return new ArrayList<Lang>(extendedLangs);
  }

  /**
   * Set extended languages. Because we cannot register multiple languages 
   * within one {@link prettify.lang.Lang}, so it is used as an solution. See 
   * {@link prettify.lang.LangCss} for example.
   * 
   * @param extendedLangs the list of {@link prettify.lang.Lang}s
   */
  public void setExtendedLangs(List<Lang> extendedLangs) {
    this.extendedLangs = new ArrayList<Lang>(extendedLangs);
  }
}


<|start_filename|>codeview/src/main/java/io/github/kbiakov/codeview/adapters/CodeWithDiffsAdapter.kt<|end_filename|>
package io.github.kbiakov.codeview.adapters

import android.content.Context
import io.github.kbiakov.codeview.views.DiffModel
import io.github.kbiakov.codeview.views.LineDiffView

/**
 * @class CodeWithDiffsAdapter
 *
 * Code content adapter with ability to add diffs (additions & deletions) in footer.
 *
 * @author <NAME>
 */
open class CodeWithDiffsAdapter : AbstractCodeAdapter<DiffModel> {

    constructor(context: Context) : super(context)

    constructor(context: Context, code: String) : super(context, code)

    constructor(context: Context, options: Options) : super(context, options)

    /**
     * Create footer view.
     *
     * @param entity Note content
     * @param isFirst Is first footer
     */
    override fun createFooter(context: Context, entity: DiffModel, isFirst: Boolean) =
            LineDiffView.create(context, entity)
}


<|start_filename|>codeview/src/main/assets/training-set/c++/NaClFile.cpp<|end_filename|>

#define NACLFILE_CPP
#include "NaClFile.h"
#include "NaClFileSystem.h"

//#include <stdio.h>
//#define EOF -1

FILE * nacl_fopen ( const char * path, const char *mode ) {

	return  ( FILE * )NaClFileSystem::Get ()->fopen ( path, mode );
}

int nacl_fclose ( FILE *file ) {

	return NaClFileSystem::Get ()->fclose ((NaClFile *) file );
}

int nacl_fread ( void *ptr, int size, int count, FILE *file ) {

	return NaClFileSystem::Get ()->fread ( ptr, size, count, (NaClFile *) file );
}

int nacl_fwrite ( const void * ptr, int size, int count, FILE *file ) {

	return NaClFileSystem::Get ()->fwrite ( ptr, size, count, (NaClFile *) file );
}

int nacl_feof ( FILE * void_file ) {

	NaClFile * file = ( NaClFile * ) void_file;
	return ( file->mOffset == file->mSize );
}

int nacl_ferror ( FILE * void_file ) {

	//unimplemented
	return 0;
}

void nacl_clearerr ( FILE * void_file ) {
	//do nothing
}

int nacl_fgetc ( FILE * void_file ) {

	NaClFile * file = ( NaClFile * ) void_file;

	if( file && file->mIsHttpLoaded ) {

		int remainingSize = file->mSize - file->mOffset;

		if ( remainingSize ) {
			int data = file->mData [ file->mOffset ];
			file->mOffset += 1;
			return data;
		}
		else {
			return EOF;
		}
	}
	return 0;
}

int nacl_ungetc (int c, FILE *void_file) {

	NaClFile * file = ( NaClFile * ) void_file;

	if( file && file->mIsHttpLoaded ) {

		if ( file->mOffset ) {
			file->mOffset -= 1;
			file->mData [ file->mOffset ] = c;
			return file->mData [ file->mOffset ];
		}
		else {
			return EOF;
		}
	}
	return 0;
}

int nacl_fseek ( FILE * void_file, long int offset, int origin ) {

	NaClFile * file = ( NaClFile * ) void_file;

	int originPosition;
	switch ( origin ) {
		case SEEK_SET:
			originPosition = 0; 
			break;
		case SEEK_CUR:
			originPosition = file->mOffset;
			break;
		case SEEK_END:
			originPosition = file->mSize;
			break;
	}
	int position = originPosition + offset;
	if ( position <= file->mSize ) {

		file->mOffset = position;
		return 0;
	}

	return -1;
}

long int nacl_ftell ( FILE * void_file ) {

	NaClFile * file = ( NaClFile * ) void_file;

	return file->mOffset;
}

int nacl_stat ( const char *path, struct stat *s ) {

	//open file with Head
	int foundFile = NaClFileSystem::Get ()->stat ( path, s );

	if ( !foundFile ) {

		s->st_mode = S_IFREG;
		s->st_ctime = 0;
		s->st_mtime = 0;
		s->st_atime = 0;

		return 0;
	}

	return -1;
}

char *nacl_getcwd(char *buf, size_t size) {

	for ( int i = 0; i < size; ++i ) {
		buf [ i ] = ( char ) 0;
	}

	buf [ 0 ] = '/';

	return buf;
}


<|start_filename|>codeview/src/main/java/io/github/kbiakov/codeview/highlight/prettify/lang/LangAppollo.java<|end_filename|>
// Copyright (C) 2009 <NAME>.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package io.github.kbiakov.codeview.highlight.prettify.lang;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
import io.github.kbiakov.codeview.highlight.prettify.parser.Prettify;

/**
 * This is similar to the lang-appollo.js in JavaScript Prettify.
 * 
 * All comments are adapted from the JavaScript Prettify.
 * 
 * <p>
 * Registers a language handler for the AGC/AEA Assembly Language as described
 * at http://virtualagc.googlecode.com
 * <p>
 * This file could be used by goodle code to allow syntax highlight for
 * Virtual AGC SVN repository or if you don't want to commonize
 * the header for the agc/aea html assembly listing.
 *
 * @author <EMAIL>
 */
public class LangAppollo extends Lang {

  public LangAppollo() {
    List<List<Object>> _shortcutStylePatterns = new ArrayList<List<Object>>();
    List<List<Object>> _fallthroughStylePatterns = new ArrayList<List<Object>>();

    // A line comment that starts with ;
    _shortcutStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_COMMENT, Pattern.compile("^#[^\r\n]*"), null, "#"}));
    // Whitespace
    _shortcutStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_PLAIN, Pattern.compile("^[\t\n\r \\xA0]+"), null, "\t\n\r " + Character.toString((char) 0xA0)}));
    // A double quoted, possibly multi-line, string.
    _shortcutStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_STRING, Pattern.compile("^\\\"(?:[^\\\"\\\\]|\\\\[\\s\\S])*(?:\\\"|$)"), null, "\""}));
    _fallthroughStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_KEYWORD, Pattern.compile("^(?:ADS|AD|AUG|BZF|BZMF|CAE|CAF|CA|CCS|COM|CS|DAS|DCA|DCOM|DCS|DDOUBL|DIM|DOUBLE|DTCB|DTCF|DV|DXCH|EDRUPT|EXTEND|INCR|INDEX|NDX|INHINT|LXCH|MASK|MSK|MP|MSU|NOOP|OVSK|QXCH|RAND|READ|RELINT|RESUME|RETURN|ROR|RXOR|SQUARE|SU|TCR|TCAA|OVSK|TCF|TC|TS|WAND|WOR|WRITE|XCH|XLQ|XXALQ|ZL|ZQ|ADD|ADZ|SUB|SUZ|MPY|MPR|MPZ|DVP|COM|ABS|CLA|CLZ|LDQ|STO|STQ|ALS|LLS|LRS|TRA|TSQ|TMI|TOV|AXT|TIX|DLY|INP|OUT)\\s"), null}));
    _fallthroughStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_TYPE, Pattern.compile("^(?:-?GENADR|=MINUS|2BCADR|VN|BOF|MM|-?2CADR|-?[1-6]DNADR|ADRES|BBCON|[SE]?BANK\\=?|BLOCK|BNKSUM|E?CADR|COUNT\\*?|2?DEC\\*?|-?DNCHAN|-?DNPTR|EQUALS|ERASE|MEMORY|2?OCT|REMADR|SETLOC|SUBRO|ORG|BSS|BES|SYN|EQU|DEFINE|END)\\s"), null}));
    // A single quote possibly followed by a word that optionally ends with
    // = ! or ?.
    _fallthroughStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_LITERAL, Pattern.compile("^\\'(?:-*(?:\\w|\\\\[\\x21-\\x7e])(?:[\\w-]*|\\\\[\\x21-\\x7e])[=!?]?)?")}));
    // Any word including labels that optionally ends with = ! or ?.
    _fallthroughStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_PLAIN, Pattern.compile("^-*(?:[!-z_]|\\\\[\\x21-\\x7e])(?:[\\w-]*|\\\\[\\x21-\\x7e])[=!?]?", Pattern.CASE_INSENSITIVE)}));
    // A printable non-space non-special character
    _fallthroughStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_PUNCTUATION, Pattern.compile("^[^\\w\\t\\n\\r \\xA0()\\\"\\\\\\';]+")}));

    setShortcutStylePatterns(_shortcutStylePatterns);
    setFallthroughStylePatterns(_fallthroughStylePatterns);
  }

  public static List<String> getFileExtensions() {
    return Arrays.asList(new String[]{"apollo", "agc", "aea"});
  }
}


<|start_filename|>codeview/src/main/java/io/github/kbiakov/codeview/CodeView.kt<|end_filename|>
package io.github.kbiakov.codeview

import android.content.Context
import android.graphics.drawable.Drawable
import android.graphics.drawable.GradientDrawable
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.util.AttributeSet
import android.view.View
import android.widget.RelativeLayout
import io.github.kbiakov.codeview.Thread.delayed
import io.github.kbiakov.codeview.adapters.AbstractCodeAdapter
import io.github.kbiakov.codeview.adapters.CodeWithNotesAdapter
import io.github.kbiakov.codeview.adapters.Options
import io.github.kbiakov.codeview.highlight.ColorThemeData
import io.github.kbiakov.codeview.highlight.color

/**
 * @class CodeView
 *
 * View for showing code content with syntax highlighting.
 *
 * @author <NAME>
 */
class CodeView @JvmOverloads constructor(
        context: Context,
        attrs: AttributeSet? = null,
        defStyleAttr: Int = 0
) : RelativeLayout(context, attrs, defStyleAttr) {

    private val vCodeList: RecyclerView
    private val vShadows: Map<ShadowPosition, View>

    /**
     * Primary constructor.
     */
    init {
        inflate(context, R.layout.layout_code_view, this)
        attrs?.let(::checkStartAnimation)

        vCodeList = findViewById<RecyclerView>(R.id.rv_code_content).apply {
            layoutManager = LinearLayoutManager(context)
            isNestedScrollingEnabled = true
        }

        vShadows = mapOf(
                ShadowPosition.RightBorder to R.id.shadow_right_border,
                ShadowPosition.NumBottom to R.id.shadow_num_bottom,
                ShadowPosition.ContentBottom to R.id.shadow_content_bottom
        ).mapValues {
            findViewById<View>(it.value)
        }
    }

    private fun checkStartAnimation(attrs: AttributeSet) {
        if (visibility == VISIBLE && attrs.isAnimateOnStart(context)) {
            alpha = Const.Alpha.Invisible

            animate()
                    .setDuration(Const.DefaultDelay * 5)
                    .alpha(Const.Alpha.Initial)
        } else {
            alpha = Const.Alpha.Initial
        }
    }

    private fun AbstractCodeAdapter<*>.checkHighlightAnimation(action: () -> Unit) {
        if (options.animateOnHighlight) {
            animate()
                    .setDuration(Const.DefaultDelay * 2)
                    .alpha(Const.Alpha.AlmostInvisible)
            delayed {
                animate().alpha(Const.Alpha.Visible)
                action()
            }
        } else {
            action()
        }
    }

    /**
     * Highlight code with defined programming language.
     * It holds the placeholder on view until code is not highlighted.
     */
    private fun highlight() {
        getAdapter()?.apply {
            highlight {
                checkHighlightAnimation(::notifyDataSetChanged)
            }
        }
    }

    /**
     * Border shadows will shown if full listing presented.
     * It helps to see what part of code is scrolled & hidden.
     *
     * @param isVisible Is shadows visible
     */
    fun setupShadows(isVisible: Boolean) {
        val visibility = if (isVisible) VISIBLE else GONE
        val theme = getOptionsOrDefault().theme
        vShadows.forEach { (pos, view) ->
            view.visibility = visibility
            view.setSafeBackground(pos.createShadow(theme))
        }
    }

    // - Initialization

    /**
     * Prepare view with default adapter & options.
     */
    private fun prepare() = setAdapter(CodeWithNotesAdapter(context))

    /**
     * Initialize with options.
     *
     * @param options Options
     */
    fun setOptions(options: Options) = setAdapter(CodeWithNotesAdapter(context, options))

    /**
     * Initialize with adapter.
     *
     * @param adapter Adapter
     */
    fun setAdapter(adapter: AbstractCodeAdapter<*>) {
        vCodeList.adapter = adapter
        highlight()
    }

    // - Options

    /**
     * View options accessor.
     */
    fun getOptions() = getAdapter()?.options
    fun getOptionsOrDefault() = getOptions() ?: Options(context)

    /**
     * Update options or initialize if needed.
     *
     * @param options Options
     */
    fun updateOptions(options: Options) {
        getAdapter() ?: setOptions(options)
        getAdapter()?.options = options
        setupShadows(options.shadows)
    }

    fun updateOptions(body: Options.() -> Unit) {
        val options = getOptions() ?: getOptionsOrDefault()
        updateOptions(options.apply(body))
    }

    // - Adapter

    /**
     * Code adapter accessor.
     */
    fun getAdapter() = vCodeList.adapter as? AbstractCodeAdapter<*>

    /**
     * Update adapter or initialize if needed.
     *
     * @param adapter Adapter
     */
    fun updateAdapter(adapter: AbstractCodeAdapter<*>) {
        adapter.options = getOptionsOrDefault()
        setAdapter(adapter)
    }

    // - Set code

    /**
     * Set code content.
     *
     * There are two ways before code will be highlighted:
     * 1) view is not initialized (adapter or options are not set),
     *    prepare with default params & try to classify language
     * 2) view initialized with some params, language:
     *    a) is set: used defined programming language
     *    b) not set: try to classify
     *
     * @param code Code content
     */
    fun setCode(code: String) {
        getAdapter() ?: prepare()
        getAdapter()?.updateCode(code)
    }

    /**
     * Set code content.
     *
     * There are two ways before code will be highlighted:
     * 1) view is not initialized, prepare with default params
     * 2) view initialized with some params, set new language
     *
     * @param code Code content
     * @param language Programming language
     */
    fun setCode(code: String, language: String) {
        val options = getOptionsOrDefault()
        updateOptions(options.withLanguage(language))
        getAdapter()?.updateCode(code)
    }

    companion object {

        private fun AttributeSet.isAnimateOnStart(context: Context): Boolean {
            context.theme.obtainStyledAttributes(this, R.styleable.CodeView, 0, 0).apply {
                val flag = getBoolean(R.styleable.CodeView_animateOnStart, false)
                recycle()
                return@isAnimateOnStart flag
            }
            return false
        }

        private fun View.setSafeBackground(newBackground: Drawable) {
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
                background = newBackground
            }
        }
    }

    private enum class ShadowPosition {
        RightBorder,
        NumBottom,
        ContentBottom;

        fun createShadow(theme: ColorThemeData) = when (this) {
            RightBorder -> GradientDrawable.Orientation.LEFT_RIGHT to theme.bgContent
            NumBottom -> GradientDrawable.Orientation.TOP_BOTTOM to theme.bgNum
            ContentBottom -> GradientDrawable.Orientation.TOP_BOTTOM to theme.bgContent
        }.let { (orientation, color) ->
            val colors = arrayOf(android.R.color.transparent, color)
            GradientDrawable(orientation, colors.map(Int::color).toIntArray())
        }
    }
}

/**
 * Provide listener to code line clicks.
 */
interface OnCodeLineClickListener {
    fun onCodeLineClicked(n: Int, line: String)
}


<|start_filename|>codeview/src/main/java/io/github/kbiakov/codeview/highlight/parser/ParseResult.java<|end_filename|>
// Copyright (c) 2012 <NAME>
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package io.github.kbiakov.codeview.highlight.parser;

import java.util.ArrayList;
import java.util.List;

/**
 * The parser parsed result.
 * 
 * This class include the information needed to highlight the syntax. 
 * Information includes where the content located in the document (offset and 
 * length) and what style(s) should be applied on that segment of content.
 * 
 * @author <NAME> <<EMAIL>>
 */
public class ParseResult {

  /**
   * The start position of the content.
   */
  protected int offset;
  /**
   * The length of the content.
   */
  protected int length;
  /**
   * The style keys of the content. The style at higher index of the list will 
   * override the style of the lower index.
   */
  protected List<String> styleKeys;

  /**
   * Constructor.
   * 
   * @param offset the start position of the content
   * @param length the length of the content
   * @param styleKeys the style keys of the content
   */
  public ParseResult(int offset, int length, List<String> styleKeys) {
    this.offset = offset;
    this.length = length;
    this.styleKeys = new ArrayList<String>(styleKeys);
  }

  /**
   * The start position of the content.
   * @return the start position of the content
   */
  public int getOffset() {
    return offset;
  }

  /**
   * The start position of the content.
   * @param offset the start position of the content
   */
  public void setOffset(int offset) {
    this.offset = offset;
  }

  /**
   * The length of the content.
   * @return the length of the content
   */
  public int getLength() {
    return length;
  }

  /**
   * The length of the content.
   * @param length the length of the content
   */
  public void setLength(int length) {
    this.length = length;
  }

  /**
   * Get the style keys represented by one string key, see 
   * {@link Theme#getStylesAttributeSet(String)}.
   * @return the style keys of the content
   */
  public String getStyleKeysString() {
    StringBuilder sb = new StringBuilder(10);
    for (int i = 0, iEnd = styleKeys.size(); i < iEnd; i++) {
      if (i != 0) {
        sb.append(" ");
      }
      sb.append(styleKeys.get(i));
    }
    return sb.toString();
  }

  /**
   * The style keys of the content.
   * @param styleKeys the style keys of the content
   */
  public void setStyleKeys(List<String> styleKeys) {
    this.styleKeys = new ArrayList<String>(styleKeys);
  }

  /**
   * The style keys of the content.
   * @param styleKey the style key
   * @return see the return value of {@link List#add(Object)}
   */
  public boolean addStyleKey(String styleKey) {
    return styleKeys.add(styleKey);
  }

  /**
   * The style keys of the content.
   * @param styleKey the style key
   * @return see the return value of {@link List#remove(Object)}
   */
  public boolean removeStyleKey(String styleKey) {
    return styleKeys.remove(styleKey);
  }

  /**
   * The style keys of the content.
   */
  public void clearStyleKeys() {
    styleKeys.clear();
  }

  /**
   * The style keys for this matched result, see {@link syntaxhighlighter.theme}.
   * @return the style keys
   */
  public List<String> getStyleKeys() {
    return new ArrayList<String>(styleKeys);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder();

    sb.append("[");
    sb.append(offset);
    sb.append("; ");
    sb.append(length);
    sb.append("; ");
    for (int i = 0, iEnd = styleKeys.size(); i < iEnd; i++) {
      if (i != 0) {
        sb.append(", ");
      }
      sb.append(styleKeys.get(i));
    }
    sb.append("]");

    return sb.toString();
  }
}

<|start_filename|>example/src/main/java/io/github/kbiakov/codeviewexample/ListingsActivity.java<|end_filename|>
package io.github.kbiakov.codeviewexample;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

import org.jetbrains.annotations.NotNull;

import io.github.kbiakov.codeview.CodeView;
import io.github.kbiakov.codeview.OnCodeLineClickListener;
import io.github.kbiakov.codeview.adapters.CodeWithDiffsAdapter;
import io.github.kbiakov.codeview.adapters.Format;
import io.github.kbiakov.codeview.adapters.Options;
import io.github.kbiakov.codeview.highlight.ColorTheme;
import io.github.kbiakov.codeview.highlight.ColorThemeData;
import io.github.kbiakov.codeview.highlight.Font;
import io.github.kbiakov.codeview.highlight.FontCache;
import io.github.kbiakov.codeview.views.DiffModel;
import kotlin.Unit;
import kotlin.jvm.functions.Function1;

public class ListingsActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_listings);

        final CodeView codeView = (CodeView) findViewById(R.id.code_view);

//        /*
//         * 1: set code content
//         */
//
//        // auto language recognition
//        codeView.setCode(getString(R.string.listing_js));
//
//        // specify language for code listing
//        codeView.setCode(getString(R.string.listing_py), "py");
//
//        /*
//         * 2: working with options
//         */
//
//        // you can change params as follows (unsafe, initialized view only)
//        codeView.getOptions()
//                .withCode(R.string.listing_java)
//                .withTheme(ColorTheme.MONOKAI);
//
//        // short initialization with default params (can be expanded using with() methods)
//        codeView.setOptions(Options.Default.get(this)
//                .withLanguage("python")
//                .withCode(R.string.listing_py)
//                .withTheme(ColorTheme.MONOKAI)
//                .withFont(Font.Consolas));
//
//        // expanded form of initialization
//        codeView.setOptions(new Options(
//                this,                                   // context
//                getString(R.string.listing_js),         // code
//                "js",                                   // language
//                ColorTheme.MONOKAI.theme(),             // theme (data)
//                FontCache.get(this).getTypeface(this),  // font
//                Format.Default.getCompact(),            // format
//                true,                                   // animate on highlight
//                true,                                   // shadows visible
//                true,                                   // shortcut
//                getString(R.string.show_all),           // shortcut note
//                10,                                     // max lines
//                new OnCodeLineClickListener() {         // line click listener
//                    @Override
//                    public void onCodeLineClicked(int n, @NotNull String line) {
//                        Log.i("ListingsActivity", "On " + (n + 1) + " line clicked");
//                    }
//                }));
//
//        /*
//         * 3: color themes
//         */
//
//        codeView.getOptions().setTheme(ColorTheme.SOLARIZED_LIGHT);
//
//        // custom theme
//        ColorThemeData myTheme = ColorTheme.SOLARIZED_LIGHT.theme()
//                .withBgContent(android.R.color.black)
//                .withNoteColor(android.R.color.white);
//
//        codeView.getOptions().setTheme(myTheme);
//
//        /*
//         * 4: custom adapter with footer views
//         */
//
//        final CustomAdapter myAdapter = new CustomAdapter(this, getString(R.string.listing_md));
//        codeView.setAdapter(myAdapter);
//        codeView.getOptions()
//                .withLanguage("md")
//                .addCodeLineClickListener(new OnCodeLineClickListener() {
//                    @Override
//                    public void onCodeLineClicked(int n, @NotNull String line) {
//                        myAdapter.addFooterEntity(n, new CustomAdapter.CustomModel("Line " + (n + 1), line));
//                    }
//                });
//
//        /*
//         * 5: diff adapter with footer views
//         */
//
//        final CodeWithDiffsAdapter diffsAdapter = new CodeWithDiffsAdapter(this);
//        codeView.getOptions()
//                .withLanguage("python")
//                .setCode(getString(R.string.listing_py));
//        codeView.updateAdapter(diffsAdapter);
//
//        diffsAdapter.addFooterEntity(16, new DiffModel(getString(R.string.py_addition_16), true));
//        diffsAdapter.addFooterEntity(11, new DiffModel(getString(R.string.py_deletion_11), false));
//
//        /*
//         * 6: shortcut adapter with footer views
//         */
//
//        codeView.getOptions()
//                .shortcut(10, "Show all");

        // - Playground

        codeView.setCode("" +
                "package io.github.kbiakov.codeviewexample;\n" +
                "\n" +
                "import android.os.Bundle;\n" +
                "import android.support.annotation.Nullable;\n" +
                "import android.support.v7.app.AppCompatActivity;\n" +
                "import android.util.Log;\n" +
                "\n" +
                "import org.jetbrains.annotations.NotNull;\n" +
                "\n" +
                "import io.github.kbiakov.codeview.CodeView;\n" +
                "import io.github.kbiakov.codeview.OnCodeLineClickListener;\n" +
                "import io.github.kbiakov.codeview.adapters.CodeWithDiffsAdapter;\n" +
                "import io.github.kbiakov.codeview.adapters.Options;\n" +
                "import io.github.kbiakov.codeview.highlight.ColorTheme;\n" +
                "import io.github.kbiakov.codeview.highlight.ColorThemeData;\n" +
                "import io.github.kbiakov.codeview.highlight.Font;\n" +
                "import io.github.kbiakov.codeview.highlight.FontCache;\n" +
                "import io.github.kbiakov.codeview.views.DiffModel;\n" +
                "\n" +
                "public class ListingsActivity extends AppCompatActivity {\n" +
                "\n" +
                "    @Override\n" +
                "    protected void onCreate(@Nullable Bundle savedInstanceState) {\n" +
                "        super.onCreate(savedInstanceState);\n" +
                "        setContentView(R.layout.activity_listings);\n" +
                "\n" +
                "        final CodeView codeView = (CodeView) findViewById(R.id.code_view);\n" +
                "\n" +
                "        /*\n" +
                "         * 1: set code content\n" +
                "         */\n" +
                "\n" +
                "        // auto language recognition\n" +
                "        codeView.setCode(getString(R.string.listing_js));\n" +
                "\n" +
                "        // specify language for code listing\n" +
                "        codeView.setCode(getString(R.string.listing_py), \"py\");" +
                "    }\n" +
                "}", "java");
        codeView.updateOptions(new Function1<Options, Unit>() {
            @Override
            public Unit invoke(Options options) {
                options.withFont(Font.Consolas)
                        .withTheme(ColorTheme.SOLARIZED_LIGHT)
                        .withShadows()
                        .setShortcut(false);
                return null;
            }
        });
    }
}


<|start_filename|>codeview/src/main/java/io/github/kbiakov/codeview/views/LineDiffView.kt<|end_filename|>
package io.github.kbiakov.codeview.views

import android.content.Context
import android.support.v4.content.ContextCompat
import android.view.LayoutInflater
import android.widget.RelativeLayout
import android.widget.TextView
import io.github.kbiakov.codeview.R
import io.github.kbiakov.codeview.highlight.FontCache

/**
 * @class CodeDiffView
 *
 * View to present code difference (additions & deletions).
 *
 * @author <NAME>
 */
class LineDiffView(context: Context) : RelativeLayout(context) {

    private val tvLineDiff: TextView
    private val tvLineContent: TextView

    init {
        val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
        inflater.inflate(R.layout.item_code_diff, this, true)

        tvLineDiff = findViewById(R.id.tv_line_diff) as TextView
        tvLineContent = findViewById(R.id.tv_line_content) as TextView
    }

    companion object Factory {
        /**
         * Simple factory method to create code diff view.
         *
         * @param context Context
         * @param model Diff model
         * @return Created line diff view
         */
        fun create(context: Context, model: DiffModel) = LineDiffView(context).apply {
            tvLineDiff.text = if (model.isAddition) "+" else "-"
            tvLineContent.text = model.content
            tvLineContent.typeface = FontCache.get(context).getTypeface(context)

            setBackgroundColor(ContextCompat.getColor(context,
                    if (model.isAddition)
                        R.color.diff_add_background
                    else
                        R.color.diff_del_background))
        }
    }
}

/**
 * Model for code difference (additions & deletions).
 *
 * @author <NAME>
 */
data class DiffModel(val content: String, val isAddition: Boolean = true)


<|start_filename|>example/src/main/java/io/github/kbiakov/codeviewexample/CustomAdapter.java<|end_filename|>
package io.github.kbiakov.codeviewexample;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;

import org.jetbrains.annotations.NotNull;

import io.github.kbiakov.codeview.adapters.AbstractCodeAdapter;
import io.github.kbiakov.codeview.adapters.Options;
import io.github.kbiakov.codeview.highlight.ColorTheme;

public class CustomAdapter extends AbstractCodeAdapter<CustomAdapter.CustomModel> {

    public CustomAdapter(@NotNull Context context, @NotNull String code) {
        super(context, Options.Default.get(context)
                .withCode(code)
                .withTheme(ColorTheme.SOLARIZED_LIGHT));
    }

    @NotNull
    @Override
    public View createFooter(@NotNull Context context, CustomModel entity, boolean isFirst) {
        View footerView = LayoutInflater.from(context).inflate(R.layout.custom_footer, null);
        ((TextView) footerView.findViewById(R.id.tv_footer_title)).setText(entity.firstName);
        ((TextView) footerView.findViewById(R.id.tv_footer_description)).setText(entity.lastName);
        return footerView;
    }

    public static class CustomModel {
        private String firstName;
        private String lastName;

        public CustomModel(String firstName, String lastName) {
            this.firstName = firstName;
            this.lastName = lastName;
        }

        public String getFirstName() {
            return firstName;
        }

        public String getLastName() {
            return lastName;
        }
    }
}


<|start_filename|>codeview/src/main/assets/training-set/html/html.html<|end_filename|>

<!DOCTYPE html>
<html>
  <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# githubog: http://ogp.me/ns/fb/githubog#">
    <meta charset='utf-8'>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>Search · xml</title>
    <link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub" />
    <link rel="fluid-icon" href="https://github.com/fluidicon.png" title="GitHub" />
    <link rel="apple-touch-icon-precomposed" sizes="57x57" href="apple-touch-icon-114.png" />
    <link rel="apple-touch-icon-precomposed" sizes="114x114" href="apple-touch-icon-114.png" />
    <link rel="apple-touch-icon-precomposed" sizes="72x72" href="apple-touch-icon-144.png" />
    <link rel="apple-touch-icon-precomposed" sizes="144x144" href="apple-touch-icon-144.png" />
    <meta name="msapplication-TileImage" content="/windows-tile.png">
    <meta name="msapplication-TileColor" content="#ffffff">



    <link rel="icon" type="image/x-icon" href="/favicon.ico" />

    <meta content="authenticity_token" name="csrf-param" />
<meta content="2sqFFESbhj36oU/zClm7KsUIFlMcCOpDHQmV5UxK4fE=" name="csrf-token" />

    <link href="https://a248.e.akamai.net/assets.github.com/assets/github-26581c8456a7088e423db87d6ed68794e9042e29.css" media="screen" rel="stylesheet" type="text/css" />
    <link href="https://a248.e.akamai.net/assets.github.com/assets/github2-38ac9c88be26119b09e2a8dbf21887c7e34791e1.css" media="screen" rel="stylesheet" type="text/css" />



    <script src="https://a248.e.akamai.net/assets.github.com/assets/frameworks-57542e0cba19d068168099f287c117efa142863c.js" type="text/javascript"></script>
    <script src="https://a248.e.akamai.net/assets.github.com/assets/github-81433815e4751f68e04d42ec948cba14ab028c2d.js" type="text/javascript"></script>



  </head>


  <body class="logged_in  macintosh  env-production ">
    <div id="wrapper">






      <div id="header" class="true clearfix">
        <div class="container clearfix">
          <a class="site-logo " href="https://github.com/">
            <img alt="GitHub" class="github-logo-4x" height="30" src="https://a248.e.akamai.net/assets.github.com/images/modules/header/logov7@4x.png?1338956357" />
            <img alt="GitHub" class="github-logo-4x-hover" height="30" src="https://a248.e.akamai.net/assets.github.com/images/modules/header/logov7@4x-hover.png?1338956357" />
          </a>

            <a href="/notifications" class="notification-indicator tooltipped downwards" title="You have unread notifications">
              <span class="mail-status unread"></span>
            </a>


    <div class="topsearch command-bar-activated">
      <form accept-charset="UTF-8" action="/search" class="command_bar_form" id="top_search_form" method="get">
  <a href="/search/advanced" class="advanced-search tooltipped downwards command-bar-search" id="advanced_search" title="Advanced Search"><span class="mini-icon mini-icon-advanced-search "></span></a>
  <input type="text" name="q" id="command-bar" placeholder="Search or Type a Command" tabindex="1" data-username="visionmedia" autocapitalize="off" />
  <span class="mini-icon help tooltipped downwards" title="Show Command Bar Help"></span>
  <input type="hidden" name="ref" value="commandbar" />
</form>

      <ul class="top-nav">
          <li class="explore"><a href="https://github.com/explore">Explore</a></li>
          <li><a href="https://gist.github.com">Gist</a></li>
          <li><a href="/blog">Blog</a></li>
        <li><a href="http://help.github.com">Help</a></li>
      </ul>
    </div>





  <div id="userbox">
    <div id="user">
      <a href="https://github.com/visionmedia"><img height="20" src="https://secure.gravatar.com/avatar/f1e3ab214a976a39cfd713bc93deb10f?s=140&amp;d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png" width="20" /></a>
      <a href="https://github.com/visionmedia" class="name">visionmedia</a>
    </div>
    <ul id="user-links">
      <li>
        <a href="/new" id="new_repo" class="tooltipped downwards" title="Create a New Repo"><span class="mini-icon mini-icon-create"></span></a>
      </li>
      <li>
        <a href="/settings/profile" id="account_settings"
          class="tooltipped downwards"
          title="Account Settings ">
          <span class="mini-icon mini-icon-account-settings"></span>
        </a>
      </li>
      <li>
          <a href="/logout" data-method="post" id="logout" class="tooltipped downwards" title="Sign Out">
            <span class="mini-icon mini-icon-logout"></span>
          </a>
      </li>
    </ul>
  </div>




        </div>
      </div>






        <div class="site clearfix">
          <div id="site-container" class="context-loader-container" data-pjax-container>



<div class="pagehead">
  <div class="container">
    <h1>Search Results</h1>
    <ul class="tabs" data-pjax>
  <li><a href="/explore" highlight="explore_main">Explore</a></li>
  <li><a href="/repositories" highlight="explore_repos">Repositories</a></li>
  <li><a href="/languages" highlight="explore_languages">Languages</a></li>
  <li><a href="/timeline" highlight="explore_timeline">Timeline</a></li>
  <li><a href="/search" class="selected" highlight="explore_search">Search</a></li>
</ul>

<div data-pjax>


</div>

  </div>
</div>

<div class="container">


<div id="code_search">
  <form accept-charset="UTF-8" action="/search" class="search_repos" id="search_form" method="get">
    <dl class="form">
      <dt><label for="type_value">Advanced Search</label></dt>
      <dd>
          <input class="text" type="text" name="q" value="xml" style="width: 34.5em;" autocapitalize="off" />
          <input type="hidden" id="repo_value" name="repo" value="" />
        <button class="classy" type="submit">Search</button>
        <input type="hidden" id="start_value" name="p" value="1" />
      </dd>
    </dl>
    <dl class="form">
      <dt><label for="type_value">Search for</label></dt>
      <dd>
        <select id="type_value" name="type"><option value="Everything" selected="selected">Everything</option>
<option value="Repositories">Repositories</option>
<option value="Users">Users</option>
<option value="Code">Code</option></select>
      </dd>
    </dl>
    <dl class="form">
      <dt><label for="language">Search Language</label></dt>
      <dd>
        <select name="l" id="language">
          <option value=''>Any Language</option>
          <optgroup label='Popular'>
            <option value="ActionScript">ActionScript</option>

<option value="XS">XS</option>
<option value="XSLT">XSLT</option>
<option value="YAML">YAML</option>
          </optgroup>
        </select>
      </dd>
    </dl>
</form></div>
<div class="clear"></div>



  <div id="code_search_results">

  <table width="100%">
    <tr><td width="60%" valign="top">


        <div class="header">
          <div class="title">Repositories (84931)</div>
          <div class="info">(0.579 seconds)</div>
        </div>

            <div class="result">
  <h2 class="title">
    <a href="/TouchCode/TouchXML">TouchCode / TouchXML</a>
      <span class="language">(C)</span>
  </h2>
  <div class="description">
    Official &quot;clone&quot; of TouchXML from TouchCode
  </div>
  <div class="details">
    382.8 KB <span>|</span>
    95 forks <span>|</span>
    369 stars <span>|</span>
    last activity 6 months ago
  </div>
</div>

            <div class="result">
  <h2 class="title">
    <a href="/robbiehanson/KissXML">robbiehanson / KissXML</a>
      <span class="language">(Objective-C)</span>
  </h2>
  <div class="description">
    A replacement for Cocoa's NSXML cluster of classes. Based on libxml. Works on iOS.
  </div>
  <div class="details">
    183.6 KB <span>|</span>
    62 forks <span>|</span>
    223 stars <span>|</span>
    last activity 5 months ago
  </div>
</div>

            <div class="result">
  <h2 class="title">
    <a href="/ZaBlanc/RaptureXML">ZaBlanc / RaptureXML</a>
      <span class="language">(Objective-C)</span>
  </h2>
  <div class="description">
    A simple, sensible, block-based XML API for iOS and Mac development.
  </div>
  <div class="details">
    273.4 KB <span>|</span>
    33 forks <span>|</span>
    321 stars <span>|</span>
    last activity 5 months ago
  </div>
</div>

            <div class="result">
  <h2 class="title">
    <a href="/Leonidas-from-XIV/node-xml2js">Leonidas-from-XIV / node-xml2js</a>
      <span class="language">(CoffeeScript)</span>
  </h2>
  <div class="description">
    Simple XML to JavaScript object converter.
  </div>
  <div class="details">
    168 KB <span>|</span>
    49 forks <span>|</span>
    312 stars <span>|</span>
    last activity 1 day ago
  </div>
</div>

            <div class="result">
  <h2 class="title">
    <a href="/bcaccinolo/XML-to-NSDictionary">bcaccinolo / XML-to-NSDictionary</a>
      <span class="language">(Objective-C)</span>
  </h2>
  <div class="description">
    an iPhone XML to NSDictionary converter
  </div>
  <div class="details">
    183.6 KB <span>|</span>
    62 forks <span>|</span>
    145 stars <span>|</span>
    last activity almost 2 years ago
  </div>
</div>


          <div class="more"><a class="more_link" href="https://github.com/search?q=xml&amp;ref=commandbar&amp;type=Repositories">more &raquo;</a></div>


    </td><td width="40%" valign="top">


        <div class="header">
          <div class="title">Users (47)</div>
          <div class="info">(0.008 seconds)</div>
        </div>

            <div class="result">
  <div class="gravatar"><img height="30" src="https://secure.gravatar.com/avatar/2ca7247fde7f8347eff5b5acf91804e5?s=140&amp;d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png" width="30" /></div>

  <h2 class="title">
    <a href="/xml">xml</a>
  </h2>
  <div class="details">
    0 followers
    <span>|</span>
    0 repositories
  </div>
</div>

            <div class="result">
  <div class="gravatar"><img height="30" src="https://secure.gravatar.com/avatar/02c99dc465e883e3f8b29fcdb6341fb2?s=140&amp;d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png" width="30" /></div>

  <h2 class="title">
    <a href="/xmlwerks">xmlwerks</a>
      <span class="aka"> - Hank Ratzesberger.org</span>
      <span class="email">(<EMAIL>)</span>
  </h2>
  <div class="details">
    0 followers
    <span>|</span>
    1 repository
      <span>|</span>
      located in California, USA
  </div>
</div>

            <div class="result">
  <div class="gravatar"><img height="30" src="https://secure.gravatar.com/avatar/1bb69e484338161dec481e117d4aec80?s=140&amp;d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png" width="30" /></div>

  <h2 class="title">
    <a href="/xmly">xmly</a>
  </h2>
  <div class="details">
    0 followers
    <span>|</span>
    8 repositories
      <span>|</span>
      Ruby
  </div>
</div>

            <div class="result">
  <div class="gravatar"><img height="30" src="https://secure.gravatar.com/avatar/215f1ef5c917cdf83687f5c9942044ca?s=140&amp;d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png" width="30" /></div>

  <h2 class="title">
    <a href="/xmlu">xmlu</a>
      <span class="aka"> - Xiao-Ming Lu</span>
  </h2>
  <div class="details">
    0 followers
    <span>|</span>
    2 repositories
      <span>|</span>
      Ruby
  </div>
</div>

            <div class="result">
  <div class="gravatar"><img height="30" src="https://secure.gravatar.com/avatar/465fcf60b799db7b9367c66ce8e740c6?s=140&amp;d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png" width="30" /></div>

  <h2 class="title">
    <a href="/xml5">xml5</a>
  </h2>
  <div class="details">
    0 followers
    <span>|</span>
    1 repository
  </div>
</div>


          <div class="more" style="margin-left: 3.3em;"><a class="more_link" href="https://github.com/search?q=xml&amp;ref=commandbar&amp;type=Users">more &raquo;</a></div>


    </td></tr>
  </table>
  <br/>

    <div class="header">
      <div class="title">Source Code (14550850)</div>
      <div class="info">(1.464 seconds)</div>
    </div>
        <div class="result">
  <h2 class="title">
    <a href="/eed3si9n/scalaxb/tree/97924b263cda2d062c23934a261104cf5642b200/cli/src_generated/wsdl20/xmlprotocol.scala">eed3si9n/scalaxb &raquo; cli / src_generated / wsdl20 / xmlprotocol.scala</a>
    <span class="language">(Scala)</span>
  </h2>

  <div class="snippet">
    <pre>

/**
usage:
import scalaxb._
import wsdl20._

val obj = from<em>XML</em>[Foo](node)
val document = to<em>XML</em></pre>
  </div>
</div>


        <div class="result">
  <h2 class="title">
    <a href="/michifunk/sample_app2/tree/355aaa587daed4c4bfdbd4000f2a7f50c06232e0/gems/ruby/1.8/gems/nokogiri-1.4.4.1-x86-mingw32/ext/nokogiri/xml_node.c">michifunk/sample_app2 &raquo; gems / ruby / 1.8 / gems / nokogiri-1.4.4.1-x86-mingw32 / ext / nokogiri / xml_node.c</a>
    <span class="language">(C)</span>
  </h2>

  <div class="snippet">
    <pre>#include &lt;<em>xml</em>_node.h&gt;

static ID decorate, decorate_bang;

#ifdef DEBUG
static void debug_node_dealloc(<em>xml</em></pre>
  </div>
</div>


        <div class="result">
  <h2 class="title">
    <a href="/eed3si9n/scalaxb/tree/97924b263cda2d062c23934a261104cf5642b200/cli/src_generated/scalaxb/scalaxb.scala">eed3si9n/scalaxb &raquo; cli / src_generated / scalaxb / scalaxb.scala</a>
    <span class="language">(Scala)</span>
  </h2>

  <div class="snippet">
    <pre>package scalaxb

import scala.<em>xml</em>.{Node, NodeSeq, NamespaceBinding, Elem, Unprefixed</pre>
  </div>
</div>


        <div class="result">
  <h2 class="title">
    <a href="/sshwsfc/apf/tree/712e9e66a748acf9883ac459b435ec0e817ebb92/core/lib/xmldb.js">sshwsfc/apf &raquo; core / lib / xmldb.js</a>
    <span class="language">(JavaScript)</span>
  </h2>

  <div class="snippet">
    <pre>-1301 USA, or see the FSF site: http://www.fsf.org.
 *
 */

//#ifdef __WITH_XMLDATABASE

/**
 * The <em>xml</em></pre>
  </div>
</div>


        <div class="result">
  <h2 class="title">
    <a href="/sshwsfc/apf/tree/2af79d8e58cc515841f322ac4f215a68fc1327c4/databinding/lib/xmldb.js">sshwsfc/apf &raquo; databinding / lib / xmldb.js</a>
    <span class="language">(JavaScript)</span>
  </h2>

  <div class="snippet">
    <pre>_XMLDATABASE
    if (apf.xmldb)
        apf.xmldb.unbind(apf.window);
    //#endif
});

/**
 * The <em>xml</em> database object</pre>
  </div>
</div>



      <div class="more"><a class="more_link" href="https://github.com/search?q=xml&amp;ref=commandbar&amp;type=Code">more &raquo;</a></div>


  </div>
</div>

          </div>
          <div class="context-overlay"></div>
        </div>
      <div id="footer-push"></div><!-- hack for sticky footer -->
    </div><!-- end of wrapper - hack for sticky footer -->

      <!-- footer -->
      <div id="footer" >

  <div class="upper_footer">
     <div class="container clearfix">

       <h4 id="blacktocat">GitHub Links</h4>

       <ul class="footer_nav">
         <h4>GitHub</h4>
         <li><a href="https://github.com/about">About</a></li>
         <li><a href="https://github.com/blog">Blog</a></li>
         <li><a href="https://github.com/features">Features</a></li>
         <li><a href="https://github.com/contact">Contact &amp; Support</a></li>
         <li><a href="http://training.github.com/">Training</a></li>
         <li><a href="http://enterprise.github.com/">GitHub Enterprise</a></li>
         <li><a href="http://status.github.com/">Site Status</a></li>
       </ul>

       <ul class="footer_nav">
         <h4>Clients</h4>
         <li><a href="http://mac.github.com/">GitHub for Mac</a></li>
         <li><a href="http://windows.github.com/">GitHub for Windows</a></li>
         <li><a href="http://eclipse.github.com/">GitHub for Eclipse</a></li>
         <li><a href="http://mobile.github.com/">GitHub Mobile Apps</a></li>
       </ul>

       <ul class="footer_nav">
         <h4>Tools</h4>
         <li><a href="http://get.gaug.es/">Gauges: Web analytics</a></li>
         <li><a href="http://speakerdeck.com">Speaker Deck: Presentations</a></li>
         <li><a href="https://gist.github.com">Gist: Code snippets</a></li>

         <h4 class="second">Extras</h4>
         <li><a href="http://jobs.github.com/">Job Board</a></li>
         <li><a href="http://shop.github.com/">GitHub Shop</a></li>
         <li><a href="http://octodex.github.com/">The Octodex</a></li>
       </ul>

       <ul class="footer_nav">
         <h4>Documentation</h4>
         <li><a href="http://help.github.com/">GitHub Help</a></li>
         <li><a href="http://developer.github.com/">Developer API</a></li>
         <li><a href="http://github.github.com/github-flavored-markdown/">GitHub Flavored Markdown</a></li>
         <li><a href="http://pages.github.com/">GitHub Pages</a></li>
       </ul>

     </div><!-- /.site -->
  </div><!-- /.upper_footer -->

<div class="lower_footer">
  <div class="container clearfix">
    <div id="legal">
      <ul>
          <li><a href="https://github.com/site/terms">Terms of Service</a></li>
          <li><a href="https://github.com/site/privacy">Privacy</a></li>
          <li><a href="https://github.com/security">Security</a></li>
      </ul>

      <p>&copy; 2012 <span title="2.37470s from fe1.rs.github.com">GitHub</span> Inc. All rights reserved.</p>
    </div><!-- /#legal or /#legal_ie-->

  </div><!-- /.site -->
</div><!-- /.lower_footer -->


      </div><!-- /#footer -->



<div id="keyboard_shortcuts_pane" class="instapaper_ignore readability-extra" style="display:none">
  <h2>Keyboard Shortcuts <small><a href="#" class="js-see-all-keyboard-shortcuts">(see all)</a></small></h2>

  <div class="columns threecols">
    <div class="column first">
      <h3>Site wide shortcuts</h3>
      <dl class="keyboard-mappings">
        <dt>s</dt>
        <dd>Focus command bar</dd>
      </dl>
      <dl class="keyboard-mappings">
        <dt>?</dt>
        <dd>Bring up this help dialog</dd>
      </dl>
    </div><!-- /.column.first -->

    <div class="column middle" style='display:none'>
      <h3>Commit list</h3>
      <dl class="keyboard-mappings">
        <dt>j</dt>
        <dd>Move selection down</dd>
      </dl>
      <dl class="keyboard-mappings">
        <dt>k</dt>
        <dd>Move selection up</dd>
      </dl>
      <dl class="keyboard-mappings">
        <dt>c <em>or</em> o <em>or</em> enter</dt>
        <dd>Open commit</dd>
      </dl>
      <dl class="keyboard-mappings">
        <dt>y</dt>
        <dd>Expand URL to its canonical form</dd>
      </dl>
    </div><!-- /.column.first -->

    <div class="column last js-hidden-pane" style='display:none'>
      <h3>Pull request list</h3>
      <dl class="keyboard-mappings">
        <dt>j</dt>
        <dd>Move selection down</dd>
      </dl>
      <dl class="keyboard-mappings">
        <dt>k</dt>
        <dd>Move selection up</dd>
      </dl>
      <dl class="keyboard-mappings">
        <dt>o <em>or</em> enter</dt>
        <dd>Open issue</dd>
      </dl>
      <dl class="keyboard-mappings">
        <dt><span class="platform-mac">⌘</span><span class="platform-other">ctrl</span> <em>+</em> enter</dt>
        <dd>Submit comment</dd>
      </dl>
      <dl class="keyboard-mappings">
        <dt><span class="platform-mac">⌘</span><span class="platform-other">ctrl</span> <em>+</em> shift p</dt>
        <dd>Preview comment</dd>
      </dl>
    </div><!-- /.columns.last -->

  </div><!-- /.columns.equacols -->

  <div class="js-hidden-pane" style='display:none'>
    <div class="rule"></div>

    <h3>Issues</h3>

    <div class="columns threecols">
      <div class="column first">
        <dl class="keyboard-mappings">
          <dt>j</dt>
          <dd>Move selection down</dd>
        </dl>
        <dl class="keyboard-mappings">
          <dt>k</dt>
          <dd>Move selection up</dd>
        </dl>
        <dl class="keyboard-mappings">
          <dt>x</dt>
          <dd>Toggle selection</dd>
        </dl>
        <dl class="keyboard-mappings">
          <dt>o <em>or</em> enter</dt>
          <dd>Open issue</dd>
        </dl>
        <dl class="keyboard-mappings">
          <dt><span class="platform-mac">⌘</span><span class="platform-other">ctrl</span> <em>+</em> enter</dt>
          <dd>Submit comment</dd>
        </dl>
        <dl class="keyboard-mappings">
          <dt><span class="platform-mac">⌘</span><span class="platform-other">ctrl</span> <em>+</em> shift p</dt>
          <dd>Preview comment</dd>
        </dl>
      </div><!-- /.column.first -->
      <div class="column last">
        <dl class="keyboard-mappings">
          <dt>c</dt>
          <dd>Create issue</dd>
        </dl>
        <dl class="keyboard-mappings">
          <dt>l</dt>
          <dd>Create label</dd>
        </dl>
        <dl class="keyboard-mappings">
          <dt>i</dt>
          <dd>Back to inbox</dd>
        </dl>
        <dl class="keyboard-mappings">
          <dt>u</dt>
          <dd>Back to issues</dd>
        </dl>
        <dl class="keyboard-mappings">
          <dt>/</dt>
          <dd>Focus issues search</dd>
        </dl>
      </div>
    </div>
  </div>

  <div class="js-hidden-pane" style='display:none'>
    <div class="rule"></div>

    <h3>Issues Dashboard</h3>

    <div class="columns threecols">
      <div class="column first">
        <dl class="keyboard-mappings">
          <dt>j</dt>
          <dd>Move selection down</dd>
        </dl>
        <dl class="keyboard-mappings">
          <dt>k</dt>
          <dd>Move selection up</dd>
        </dl>
        <dl class="keyboard-mappings">
          <dt>o <em>or</em> enter</dt>
          <dd>Open issue</dd>
        </dl>
      </div><!-- /.column.first -->
    </div>
  </div>

  <div class="js-hidden-pane" style='display:none'>
    <div class="rule"></div>

    <h3>Network Graph</h3>
    <div class="columns equacols">
      <div class="column first">
        <dl class="keyboard-mappings">
          <dt><span class="badmono">←</span> <em>or</em> h</dt>
          <dd>Scroll left</dd>
        </dl>
        <dl class="keyboard-mappings">
          <dt><span class="badmono">→</span> <em>or</em> l</dt>
          <dd>Scroll right</dd>
        </dl>
        <dl class="keyboard-mappings">
          <dt><span class="badmono">↑</span> <em>or</em> k</dt>
          <dd>Scroll up</dd>
        </dl>
        <dl class="keyboard-mappings">
          <dt><span class="badmono">↓</span> <em>or</em> j</dt>
          <dd>Scroll down</dd>
        </dl>
        <dl class="keyboard-mappings">
          <dt>t</dt>
          <dd>Toggle visibility of head labels</dd>
        </dl>
      </div><!-- /.column.first -->
      <div class="column last">
        <dl class="keyboard-mappings">
          <dt>shift <span class="badmono">←</span> <em>or</em> shift h</dt>
          <dd>Scroll all the way left</dd>
        </dl>
        <dl class="keyboard-mappings">
          <dt>shift <span class="badmono">→</span> <em>or</em> shift l</dt>
          <dd>Scroll all the way right</dd>
        </dl>
        <dl class="keyboard-mappings">
          <dt>shift <span class="badmono">↑</span> <em>or</em> shift k</dt>
          <dd>Scroll all the way up</dd>
        </dl>
        <dl class="keyboard-mappings">
          <dt>shift <span class="badmono">↓</span> <em>or</em> shift j</dt>
          <dd>Scroll all the way down</dd>
        </dl>
      </div><!-- /.column.last -->
    </div>
  </div>

  <div class="js-hidden-pane" style='display:none'>
    <div class="rule"></div>
    <div class="columns threecols">
      <div class="column first js-hidden-pane" style='display:none'>
        <h3>Source Code Browsing</h3>
        <dl class="keyboard-mappings">
          <dt>t</dt>
          <dd>Activates the file finder</dd>
        </dl>
        <dl class="keyboard-mappings">
          <dt>l</dt>
          <dd>Jump to line</dd>
        </dl>
        <dl class="keyboard-mappings">
          <dt>w</dt>
          <dd>Switch branch/tag</dd>
        </dl>
        <dl class="keyboard-mappings">
          <dt>y</dt>
          <dd>Expand URL to its canonical form</dd>
        </dl>
      </div>
    </div>
  </div>

  <div class="js-hidden-pane" style='display:none'>
    <div class="rule"></div>
    <div class="columns threecols">
      <div class="column first">
        <h3>Browsing Commits</h3>
        <dl class="keyboard-mappings">
          <dt><span class="platform-mac">⌘</span><span class="platform-other">ctrl</span> <em>+</em> enter</dt>
          <dd>Submit comment</dd>
        </dl>
        <dl class="keyboard-mappings">
          <dt>escape</dt>
          <dd>Close form</dd>
        </dl>
        <dl class="keyboard-mappings">
          <dt>p</dt>
          <dd>Parent commit</dd>
        </dl>
        <dl class="keyboard-mappings">
          <dt>o</dt>
          <dd>Other parent commit</dd>
        </dl>
      </div>
    </div>
  </div>

  <div class="js-hidden-pane" style='display:none'>
    <div class="rule"></div>
    <h3>Notifications</h3>

    <div class="columns threecols">
      <div class="column first">
        <dl class="keyboard-mappings">
          <dt>j</dt>
          <dd>Move selection down</dd>
        </dl>
        <dl class="keyboard-mappings">
          <dt>k</dt>
          <dd>Move selection up</dd>
        </dl>
        <dl class="keyboard-mappings">
          <dt>o <em>or</em> enter</dt>
          <dd>Open notification</dd>
        </dl>
      </div><!-- /.column.first -->

      <div class="column second">
        <dl class="keyboard-mappings">
          <dt>e <em>or</em> shift i <em>or</em> y</dt>
          <dd>Mark as read</dd>
        </dl>
        <dl class="keyboard-mappings">
          <dt>shift m</dt>
          <dd>Mute thread</dd>
        </dl>
      </div><!-- /.column.first -->
    </div>
  </div>

</div>

    <div id="markdown-help" class="instapaper_ignore readability-extra">
  <h2>Markdown Cheat Sheet</h2>

  <div class="cheatsheet-content">

  <div class="mod">
    <div class="col">
      <h3>Format Text</h3>
      <p>Headers</p>
      <pre>
# This is an &lt;h1&gt; tag
## This is an &lt;h2&gt; tag
###### This is an &lt;h6&gt; tag</pre>
     <p>Text styles</p>
     <pre>
*This text will be italic*
_This will also be italic_
**This text will be bold**
__This will also be bold__

*You **can** combine them*
</pre>
    </div>
    <div class="col">
      <h3>Lists</h3>
      <p>Unordered</p>
      <pre>
* Item 1
* Item 2
  * Item 2a
  * Item 2b</pre>
     <p>Ordered</p>
     <pre>
1. Item 1
2. Item 2
3. Item 3
   * Item 3a
   * Item 3b</pre>
    </div>
    <div class="col">
      <h3>Miscellaneous</h3>
      <p>Images</p>
      <pre>
![GitHub Logo](/images/logo.png)
Format: ![Alt Text](url)
</pre>
     <p>Links</p>
     <pre>
http://github.com - automatic!
[GitHub](http://github.com)</pre>
<p>Blockquotes</p>
     <pre>
As Kanye West said:

> We're living the future so
> the present is our past.
</pre>
    </div>
  </div>
  <div class="rule"></div>

  <h3>Code Examples in Markdown</h3>
  <div class="col">
      <p>Syntax highlighting with <a href="http://github.github.com/github-flavored-markdown/" title="GitHub Flavored Markdown" target="_blank">GFM</a></p>
      <pre>
```javascript
function fancyAlert(arg) {
  if(arg) {
    $.facebox({div:'#foo'})
  }
}
```</pre>
    </div>
    <div class="col">
      <p>Or, indent your code 4 spaces</p>
      <pre>
Here is a Python code example
without syntax highlighting:

    def foo:
      if not bar:
        return true</pre>
    </div>
    <div class="col">
      <p>Inline code for comments</p>
      <pre>
I think you should use an
`&lt;addr&gt;` element here instead.</pre>
    </div>
  </div>

  </div>
</div>


    <div id="ajax-error-message" class="flash flash-error">
      <span class="mini-icon mini-icon-exclamation"></span>
      Something went wrong with that request. Please try again.
      <a href="#" class="mini-icon mini-icon-remove-close ajax-error-dismiss"></a>
    </div>

    <div id="logo-popup">
      <h2>Looking for the GitHub logo?</h2>
      <ul>
        <li>
          <h4>GitHub Logo</h4>
          <a href="http://github-media-downloads.s3.amazonaws.com/GitHub_Logos.zip"><img alt="Github_logo" src="https://a248.e.akamai.net/assets.github.com/images/modules/about_page/github_logo.png?1338956357" /></a>
          <a href="http://github-media-downloads.s3.amazonaws.com/GitHub_Logos.zip" class="minibutton download">Download</a>
        </li>
        <li>
          <h4>The Octocat</h4>
          <a href="http://github-media-downloads.s3.amazonaws.com/Octocats.zip"><img alt="Octocat" src="https://a248.e.akamai.net/assets.github.com/images/modules/about_page/octocat.png?1338956357" /></a>
          <a href="http://github-media-downloads.s3.amazonaws.com/Octocats.zip" class="minibutton download">Download</a>
        </li>
      </ul>
    </div>



    <span id='server_response_time' data-time='2.37595' data-host='fe1'></span>

  </body>
</html>


<|start_filename|>codeview/src/main/java/io/github/kbiakov/codeview/highlight/prettify/parser/CombinePrefixPattern.java<|end_filename|>
// Copyright (C) 2006 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package io.github.kbiakov.codeview.highlight.prettify.parser;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * This is similar to the combinePrefixPattern.js in JavaScript Prettify.
 * 
 * All comments are adapted from the JavaScript Prettify.
 * 
 * @author <EMAIL>
 */
public class CombinePrefixPattern {

  protected int capturedGroupIndex = 0;
  protected boolean needToFoldCase = false;

  public CombinePrefixPattern() {
  }

  /**
   * Given a group of {@link java.util.regex.Pattern}s, returns a {@code RegExp} that globally
   * matches the union of the sets of strings matched by the input RegExp.
   * Since it matches globally, if the input strings have a start-of-input
   * anchor (/^.../), it is ignored for the purposes of unioning.
   * @param regexs non multiline, non-global regexs.
   * @return Pattern a global regex.
   */
  public Pattern combinePrefixPattern(List<Pattern> regexs) throws Exception {
    boolean ignoreCase = false;

    for (int i = 0, n = regexs.size(); i < n; ++i) {
      Pattern regex = regexs.get(i);
      if ((regex.flags() & Pattern.CASE_INSENSITIVE) != 0) {
        ignoreCase = true;
      } else if (Util.test(Pattern.compile("[a-z]", Pattern.CASE_INSENSITIVE), regex.pattern().replaceAll("\\\\[Uu][0-9A-Fa-f]{4}|\\\\[Xx][0-9A-Fa-f]{2}|\\\\[^UuXx]", ""))) {
        needToFoldCase = true;
        ignoreCase = false;
        break;
      }
    }

    List<String> rewritten = new ArrayList<String>();
    for (int i = 0, n = regexs.size(); i < n; ++i) {
      Pattern regex = regexs.get(i);
      if ((regex.flags() & Pattern.MULTILINE) != 0) {
        throw new Exception(regex.pattern());
      }
      rewritten.add("(?:" + allowAnywhereFoldCaseAndRenumberGroups(regex) + ")");
    }

    return ignoreCase ? Pattern.compile(Util.join(rewritten, "|"), Pattern.CASE_INSENSITIVE) : Pattern.compile(Util.join(rewritten, "|"));
  }
  protected static final Map<Character, Integer> escapeCharToCodeUnit = new HashMap<Character, Integer>();

  static {
    escapeCharToCodeUnit.put('b', 8);
    escapeCharToCodeUnit.put('t', 9);
    escapeCharToCodeUnit.put('n', 0xa);
    escapeCharToCodeUnit.put('v', 0xb);
    escapeCharToCodeUnit.put('f', 0xc);
    escapeCharToCodeUnit.put('r', 0xf);
  }

  protected static int decodeEscape(String charsetPart) {
    Integer cc0 = charsetPart.codePointAt(0);
    if (cc0 != 92 /* \\ */) {
      return cc0;
    }
    char c1 = charsetPart.charAt(1);
    cc0 = escapeCharToCodeUnit.get(c1);
    if (cc0 != null) {
      return cc0;
    } else if ('0' <= c1 && c1 <= '7') {
      return Integer.parseInt(charsetPart.substring(1), 8);
    } else if (c1 == 'u' || c1 == 'x') {
      return Integer.parseInt(charsetPart.substring(2), 16);
    } else {
      return charsetPart.codePointAt(1);
    }
  }

  protected static String encodeEscape(int charCode) {
    if (charCode < 0x20) {
      return (charCode < 0x10 ? "\\x0" : "\\x") + Integer.toString(charCode, 16);
    }

    String ch = new String(Character.toChars(charCode));
    return (charCode == '\\' || charCode == '-' || charCode == ']' || charCode == '^')
            ? "\\" + ch : ch;
  }

  protected static String caseFoldCharset(String charSet) {
    String[] charsetParts = Util.match(Pattern.compile("\\\\u[0-9A-Fa-f]{4}"
            + "|\\\\x[0-9A-Fa-f]{2}"
            + "|\\\\[0-3][0-7]{0,2}"
            + "|\\\\[0-7]{1,2}"
            + "|\\\\[\\s\\S]"
            + "|-"
            + "|[^-\\\\]"), charSet.substring(1, charSet.length() - 1), true);
    List<List<Integer>> ranges = new ArrayList<List<Integer>>();
    boolean inverse = charsetParts[0] != null && charsetParts[0].equals("^");

    List<String> out = new ArrayList<String>(Arrays.asList(new String[]{"["}));
    if (inverse) {
      out.add("^");
    }

    for (int i = inverse ? 1 : 0, n = charsetParts.length; i < n; ++i) {
      String p = charsetParts[i];
      if (Util.test(Pattern.compile("\\\\[bdsw]", Pattern.CASE_INSENSITIVE), p)) {  // Don't muck with named groups.
        out.add(p);
      } else {
        int start = decodeEscape(p);
        int end;
        if (i + 2 < n && "-".equals(charsetParts[i + 1])) {
          end = decodeEscape(charsetParts[i + 2]);
          i += 2;
        } else {
          end = start;
        }
        ranges.add(Arrays.asList(new Integer[]{start, end}));
        // If the range might intersect letters, then expand it.
        // This case handling is too simplistic.
        // It does not deal with non-latin case folding.
        // It works for latin source code identifiers though.
        if (!(end < 65 || start > 122)) {
          if (!(end < 65 || start > 90)) {
            ranges.add(Arrays.asList(new Integer[]{Math.max(65, start) | 32, Math.min(end, 90) | 32}));
          }
          if (!(end < 97 || start > 122)) {
            ranges.add(Arrays.asList(new Integer[]{Math.max(97, start) & ~32, Math.min(end, 122) & ~32}));
          }
        }
      }
    }

    // [[1, 10], [3, 4], [8, 12], [14, 14], [16, 16], [17, 17]]
    // -> [[1, 12], [14, 14], [16, 17]]
    Collections.sort(ranges, new Comparator<List<Integer>>() {

      @Override
      public int compare(List<Integer> a, List<Integer> b) {
        return a.get(0) != b.get(0) ? (a.get(0) - b.get(0)) : (b.get(1) - a.get(1));
      }
    });
    List<List<Integer>> consolidatedRanges = new ArrayList<List<Integer>>();
//        List<Integer> lastRange = Arrays.asList(new Integer[]{0, 0});
    List<Integer> lastRange = new ArrayList<Integer>(Arrays.asList(new Integer[]{0, 0}));
    for (int i = 0; i < ranges.size(); ++i) {
      List<Integer> range = ranges.get(i);
      if (lastRange.get(1) != null && range.get(0) <= lastRange.get(1) + 1) {
        lastRange.set(1, Math.max(lastRange.get(1), range.get(1)));
      } else {
        // reference of lastRange is added
        consolidatedRanges.add(lastRange = range);
      }
    }

    for (int i = 0; i < consolidatedRanges.size(); ++i) {
      List<Integer> range = consolidatedRanges.get(i);
      out.add(encodeEscape(range.get(0)));
      if (range.get(1) > range.get(0)) {
        if (range.get(1) + 1 > range.get(0)) {
          out.add("-");
        }
        out.add(encodeEscape(range.get(1)));
      }
    }
    out.add("]");

    return Util.join(out);
  }

  protected String allowAnywhereFoldCaseAndRenumberGroups(Pattern regex) {
    // Split into character sets, escape sequences, punctuation strings
    // like ('(', '(?:', ')', '^'), and runs of characters that do not
    // include any of the above.
    String[] parts = Util.match(Pattern.compile("(?:"
            + "\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]" // a character set
            + "|\\\\u[A-Fa-f0-9]{4}" // a unicode escape
            + "|\\\\x[A-Fa-f0-9]{2}" // a hex escape
            + "|\\\\[0-9]+" // a back-reference or octal escape
            + "|\\\\[^ux0-9]" // other escape sequence
            + "|\\(\\?[:!=]" // start of a non-capturing group
            + "|[\\(\\)\\^]" // start/end of a group, or line start
            + "|[^\\x5B\\x5C\\(\\)\\^]+" // run of other characters
            + ")"), regex.pattern(), true);
    int n = parts.length;

    // Maps captured group numbers to the number they will occupy in
    // the output or to -1 if that has not been determined, or to
    // undefined if they need not be capturing in the output.
    Map<Integer, Integer> capturedGroups = new HashMap<Integer, Integer>();

    // Walk over and identify back references to build the capturedGroups
    // mapping.
    for (int i = 0, groupIndex = 0; i < n; ++i) {
      String p = parts[i];
      if (p.equals("(")) {
        // groups are 1-indexed, so max group index is count of '('
        ++groupIndex;
      } else if ('\\' == p.charAt(0)) {
        try {
          int decimalValue = Math.abs(Integer.parseInt(p.substring(1)));
          if (decimalValue <= groupIndex) {
            capturedGroups.put(decimalValue, -1);
          } else {
            // Replace with an unambiguous escape sequence so that
            // an octal escape sequence does not turn into a backreference
            // to a capturing group from an earlier regex.
            parts[i] = encodeEscape(decimalValue);
          }
        } catch (NumberFormatException ex) {
        }
      }
    }

    // Renumber groups and reduce capturing groups to non-capturing groups
    // where possible.
    for (int i : capturedGroups.keySet()) {
      if (-1 == capturedGroups.get(i)) {
        capturedGroups.put(i, ++capturedGroupIndex);
      }
    }
    for (int i = 0, groupIndex = 0; i < n; ++i) {
      String p = parts[i];
      if (p.equals("(")) {
        ++groupIndex;
        if (capturedGroups.get(groupIndex) == null) {
          parts[i] = "(?:";
        }
      } else if ('\\' == p.charAt(0)) {
        try {
          int decimalValue = Math.abs(Integer.parseInt(p.substring(1)));
          if (decimalValue <= groupIndex) {
            parts[i] = "\\" + capturedGroups.get(decimalValue);
          }
        } catch (NumberFormatException ex) {
        }
      }
    }

    // Remove any prefix anchors so that the output will match anywhere.
    // ^^ really does mean an anchored match though.
    for (int i = 0; i < n; ++i) {
      if ("^".equals(parts[i]) && !"^".equals(parts[i + 1])) {
        parts[i] = "";
      }
    }

    // Expand letters to groups to handle mixing of case-sensitive and
    // case-insensitive patterns if necessary.
    if ((regex.flags() & Pattern.CASE_INSENSITIVE) != 0 && needToFoldCase) {
      for (int i = 0; i < n; ++i) {
        String p = parts[i];
        char ch0 = p.length() > 0 ? p.charAt(0) : 0;
        if (p.length() >= 2 && ch0 == '[') {
          parts[i] = caseFoldCharset(p);
        } else if (ch0 != '\\') {
          // TODO: handle letters in numeric escapes.
          StringBuffer sb = new StringBuffer();
          Matcher _matcher = Pattern.compile("[a-zA-Z]").matcher(p);
          while (_matcher.find()) {
            int cc = _matcher.group(0).codePointAt(0);
            _matcher.appendReplacement(sb, "");
            sb.append("[").append(Character.toString((char) (cc & ~32))).append(Character.toString((char) (cc | 32))).append("]");
          }
          _matcher.appendTail(sb);
          parts[i] = sb.toString();
        }
      }
    }

    return Util.join(parts);
  }
}


<|start_filename|>codeview/src/main/assets/training-set/c++/hstest.cpp<|end_filename|>

// vim:sw=2:ai

#include <signal.h>
#include <sys/time.h>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <stdlib.h>
#include <memory>
#include <errno.h>
#include <mysql.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "util.hpp"
#include "auto_ptrcontainer.hpp"
#include "socket.hpp"
#include "thread.hpp"
#include "hstcpcli.hpp"

#if __GNUC__ >= 4
long atomic_exchange_and_add(volatile long *valp, long c)
{
  return __sync_fetch_and_add(valp, c);
}
#else
#include <bits/atomicity.h>
using namespace __gnu_cxx;
long atomic_exchange_and_add(volatile long *valp, long c)
{
  return __exchange_and_add((volatile _Atomic_word *)valp, c);
}
#endif

namespace dena {

struct auto_mysql : private noncopyable {
  auto_mysql() : db(0) {
    reset();
  }
  ~auto_mysql() {
    if (db) {
      mysql_close(db);
    }
  }
  void reset() {
    if (db) {
      mysql_close(db);
    }
    if ((db = mysql_init(0)) == 0) {
      fatal_abort("failed to initialize mysql client");
    }
  }
  operator MYSQL *() const { return db; }
 private:
  MYSQL *db;
};

struct auto_mysql_res : private noncopyable {
  auto_mysql_res(MYSQL *db) {
    res = mysql_store_result(db);
  }
  ~auto_mysql_res() {
    if (res) {
      mysql_free_result(res);
    }
  }
  operator MYSQL_RES *() const { return res; }
 private:
  MYSQL_RES *res;
};

struct auto_mysql_stmt : private noncopyable {
  auto_mysql_stmt(MYSQL *db) {
    stmt = mysql_stmt_init(db);
  }
  ~auto_mysql_stmt() {
    if (stmt) {
      mysql_stmt_close(stmt);
    }
  }
  operator MYSQL_STMT *() const { return stmt; }
 private:
  MYSQL_STMT *stmt;
};

namespace {

double
gettimeofday_double()
{
  struct timeval tv = { };
  if (gettimeofday(&tv, 0) != 0) {
    fatal_abort("gettimeofday");
  }
  return static_cast<double>(tv.tv_usec) / 1000000 + tv.tv_sec;
}

// unused
void
wait_close(int fd)
{
  char buf[1024];
  while (true) {
    int r = read(fd, buf, sizeof(buf));
    if (r <= 0) {
      break;
    }
  }
}

// unused
void
gentle_close(int fd)
{
  int r = shutdown(fd, SHUT_WR);
  if (r != 0) {
    return;
  }
  wait_close(fd);
}

};

struct hstest_shared {
  config conf;
  socket_args arg;
  int verbose;
  size_t loop;
  size_t pipe;
  char op;
  long num_threads;
  mutable volatile long count;
  mutable volatile long conn_count;
  long wait_conn;
  volatile char *keygen;
  long keygen_size;
  mutable volatile int enable_timing;
  int usleep;
  int dump;
  hstest_shared() : verbose(0), loop(0), pipe(0), op('G'), num_threads(0),
    count(0), conn_count(0), wait_conn(0), keygen(0), keygen_size(0),
    enable_timing(0), usleep(0), dump(0) { }
  void increment_count(unsigned int c = 1) const volatile {
    atomic_exchange_and_add(&count, c);
  }
  void increment_conn(unsigned int c) const volatile {
    atomic_exchange_and_add(&conn_count, c);
    while (wait_conn != 0 && conn_count < wait_conn) {
      sleep(1);
    }
    // fprintf(stderr, "wait_conn=%ld done\n", wait_conn);
  }
};

struct hstest_thread {
  struct arg_type {
    size_t id;
    const hstest_shared& sh;
    bool watch_flag;
    arg_type(size_t i, const hstest_shared& s, bool w)
      : id(i), sh(s), watch_flag(w) { }
  };
  hstest_thread(const arg_type& a) : arg(a), io_success_count(0),
    op_success_count(0), response_min(99999), response_max(0),
    response_sum(0), response_avg(0) { }
  void operator ()();
  void test_1();
  void test_2_3(int test_num);
  void test_4_5(int test_num);
  void test_6(int test_num);
  void test_7(int test_num);
  void test_8(int test_num);
  void test_9(int test_num);
  void test_10(int test_num);
  void test_11(int test_num);
  void test_12(int test_num);
  void test_21(int test_num);
  void test_22(int test_num);
  void test_watch();
  void sleep_if();
  void set_timing(double time_spent);
  arg_type arg;
  auto_file fd;
  size_t io_success_count;
  size_t op_success_count;
  double response_min, response_max, response_sum, response_avg;
};

void
hstest_thread::test_1()
{
  char buf[1024];
  unsigned int seed = arg.id;
  seed ^= arg.sh.conf.get_int("seed_xor", 0);
  std::string err;
  if (socket_connect(fd, arg.sh.arg, err) != 0) {
    fprintf(stderr, "connect: %d %s\n", errno, strerror(errno));
    return;
  }
  const char op = arg.sh.op;
  const int tablesize = arg.sh.conf.get_int("tablesize", 0);
  for (size_t i = 0; i < arg.sh.loop; ++i) {
    for (size_t j = 0; j < arg.sh.pipe; ++j) {
      int k = 0, v = 0, len = 0;
      if (op == 'G') {
	k = rand_r(&seed);
	v = rand_r(&seed); /* unused */
	if (tablesize != 0) {
	  k &= tablesize;
	}
	len = snprintf(buf, sizeof(buf), "%c\tk%d\n", op, k);
      } else {
	k = rand_r(&seed);
	v = rand_r(&seed);
	if (tablesize != 0) {
	  k &= tablesize;
	}
	len = snprintf(buf, sizeof(buf), "%c\tk%d\tv%d\n", op, k, v);
      }
      const int wlen = write(fd.get(), buf, len);
      if (wlen != len) {
	return;
      }
    }
    size_t read_cnt = 0;
    size_t read_pos = 0;
    while (read_cnt < arg.sh.pipe) {
      const int rlen = read(fd.get(), buf + read_pos, sizeof(buf) - read_pos);
      if (rlen <= 0) {
	return;
      }
      read_pos += rlen;
      while (true) {
	const char *const p = static_cast<const char *>(memchr(buf, '\n',
	  read_pos));
	if (p == 0) {
	  break;
	}
	++read_cnt;
	++io_success_count;
	arg.sh.increment_count();
	if (p != buf && buf[0] == '=') {
	  ++op_success_count;
	}
	const size_t rest_size = buf + read_pos - (p + 1);
	if (rest_size != 0) {
	  memmove(buf, p + 1, rest_size);
	}
	read_pos = rest_size;
      }
    }
  }
}

void
hstest_thread::test_2_3(int test_num)
{
#if 0
  char buf_k[128], buf_v[128];
  unsigned int seed = arg.id;
  op_base_t op = static_cast<op_base_t>(arg.sh.op);
  micli_ptr hnd;
  if (test_num == 2) {
    hnd = micli_i::create_remote(arg.sh.conf);
  } else if (test_num == 3) {
    // hnd = micli_i::create_inproc(arg.sh.localdb);
  }
  if (hnd.get() == 0) {
    return;
  }
  for (size_t i = 0; i < arg.sh.loop; ++i) {
    for (size_t j = 0; j < arg.sh.pipe; ++j) {
      int k = 0, v = 0, klen = 0, vlen = 0;
      k = rand_r(&seed);
      klen = snprintf(buf_k, sizeof(buf_k), "k%d", k);
      v = rand_r(&seed); /* unused */
      vlen = snprintf(buf_v, sizeof(buf_v), "v%d", v);
      string_ref arr[2];
      arr[0] = string_ref(buf_k, klen);
      arr[1] = string_ref(buf_v, vlen);
      pstrarr_ptr rec(arr, 2);
      if (hnd->execute(op, 0, 0, rec.get_const())) {
	++io_success_count;
	arg.sh.increment_count();
	const dataset& res = hnd->get_result_ref();
	if (res.size() == 1) {
	  ++op_success_count;
	}
      }
    }
  }
#endif
}

void
hstest_thread::test_4_5(int test_num)
{
#if 0
  char buf_k[128], buf_v[8192];
  memset(buf_v, ' ', sizeof(buf_v));
  unsigned int seed = arg.id;
  op_base_t op = static_cast<op_base_t>(arg.sh.op);
  micli_ptr hnd;
  if (test_num == 4) {
    hnd = micli_i::create_remote(arg.sh.conf);
  } else if (test_num == 5) {
    hnd = micli_i::create_inproc(arg.sh.localdb);
  }
  if (hnd.get() == 0) {
    return;
  }
  for (size_t i = 0; i < arg.sh.loop; ++i) {
    for (size_t j = 0; j < arg.sh.pipe; ++j) {
      int k = 0, klen = 0, vlen = 0;
      k = i & 0x0000ffffUL;
      if (k == 0) {
	fprintf(stderr, "k=0\n");
      }
      klen = snprintf(buf_k, sizeof(buf_k), "k%d", k);
      vlen = rand_r(&seed) % 8192;
      string_ref arr[2];
      arr[0] = string_ref(buf_k, klen);
      arr[1] = string_ref(buf_v, vlen);
      pstrarr_ptr rec(arr, 2);
      if (hnd->execute(op, 0, 0, rec.get_const())) {
	++io_success_count;
	const dataset& res = hnd->get_result_ref();
	if (res.size() == 1) {
	  ++op_success_count;
	}
      }
    }
  }
#endif
}

void
hstest_thread::test_6(int test_num)
{
  int count = arg.sh.conf.get_int("count", 1);
  auto_file fds[count];
  for (int i = 0; i < count; ++i) {
    const double t1 = gettimeofday_double();
    std::string err;
    if (socket_connect(fds[i], arg.sh.arg, err) != 0) {
      fprintf(stderr, "id=%zu i=%d err=%s\n", arg.id, i, err.c_str());
    }
    const double t2 = gettimeofday_double();
    if (t2 - t1 > 1) {
      fprintf(stderr, "id=%zu i=%d time %f\n", arg.id, i, t2 - t1);
    }
  }
}

void
hstest_thread::test_7(int num)
{
  /*
    set foo 0 0 10
    0123456789
    STORED
    get foo
    VALUE foo 0 10
    0123456789
    END
    get var
    END
   */
  char buf[1024];
  const int keep_connection = arg.sh.conf.get_int("keep_connection", 1);
  unsigned int seed = arg.id;
  seed ^= arg.sh.conf.get_int("seed_xor", 0);
  const int tablesize = arg.sh.conf.get_int("tablesize", 0);
  const char op = arg.sh.op;
  for (size_t i = 0; i < arg.sh.loop; ++i) {
    const double tm1 = gettimeofday_double();
    std::string err;
    if (fd.get() < 0 && socket_connect(fd, arg.sh.arg, err) != 0) {
      fprintf(stderr, "connect: %d %s\n", errno, strerror(errno));
      return;
    }
    for (size_t j = 0; j < arg.sh.pipe; ++j) {
      int k = 0, v = 0, len = 0;
      if (op == 'G') {
	k = rand_r(&seed);
	v = rand_r(&seed); /* unused */
	if (tablesize != 0) {
	  k &= tablesize;
	}
	len = snprintf(buf, sizeof(buf), "get k%d\r\n", k);
      } else {
	k = rand_r(&seed);
	v = rand_r(&seed);
	if (tablesize != 0) {
	  k &= tablesize;
	}
	char vbuf[1024];
	int vlen = snprintf(vbuf, sizeof(vbuf),
	  "v%d"
	  // "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
	  // "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
	  // "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
	  // "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
	  // "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
	  , v);
	len = snprintf(buf, sizeof(buf), "set k%d 0 0 %d\r\n%s\r\n",
	  k, vlen, vbuf);
      }
      const int wlen = write(fd.get(), buf, len);
      if (wlen != len) {
	return;
      }
    }
    size_t read_cnt = 0;
    size_t read_pos = 0;
    bool read_response_done = false;
    bool expect_value = false;
    while (!read_response_done) {
      const int rlen = read(fd.get(), buf + read_pos, sizeof(buf) - read_pos);
      if (rlen <= 0) {
	return;
      }
      read_pos += rlen;
      while (true) {
	const char *const p = static_cast<const char *>(memchr(buf, '\n',
	  read_pos));
	if (p == 0) {
	  break;
	}
	++read_cnt;
	if (expect_value) {
	  expect_value = false;
	} else if (p >= buf + 6 && memcmp(buf, "VALUE ", 6) == 0) {
	  expect_value = true;
	  ++op_success_count;
	} else {
	  if (p == buf + 7 && memcmp(buf, "STORED\r", 7) == 0) {
	    ++op_success_count;
	  }
	  read_response_done = true;
	}
	const size_t rest_size = buf + read_pos - (p + 1);
	if (rest_size != 0) {
	  memmove(buf, p + 1, rest_size);
	}
	read_pos = rest_size;
      }
      ++io_success_count;
    }
    arg.sh.increment_count();
    if (!keep_connection) {
      fd.close();
    }
    const double tm2 = gettimeofday_double();
    set_timing(tm2 - tm1);
    sleep_if();
  }
}

struct rec {
  std::string key;
  std::string value;
};

void
hstest_thread::test_8(int test_num)
{
#if 0
  char buf_k[128], buf_v[128];
  unsigned int seed = arg.id;
  // op_base_t op = static_cast<op_base_t>(arg.sh.op);
  using namespace boost::multi_index;
  typedef member<rec, std::string, &rec::key> rec_get_key;
  typedef ordered_unique<rec_get_key> oui;
  typedef multi_index_container< rec, indexed_by<oui> > mic;
  #if 0
  typedef std::map<std::string, std::string> m_type;
  m_type m;
  #endif
  mic m;
  for (size_t i = 0; i < arg.sh.loop; ++i) {
    for (size_t j = 0; j < arg.sh.pipe; ++j) {
      int k = 0, v = 0, klen = 0, vlen = 0;
      k = rand_r(&seed);
      klen = snprintf(buf_k, sizeof(buf_k), "k%d", k);
      v = rand_r(&seed); /* unused */
      vlen = snprintf(buf_v, sizeof(buf_v), "v%d", v);
      const std::string ks(buf_k, klen);
      const std::string vs(buf_v, vlen);
      rec r;
      r.key = ks;
      r.value = vs;
      m.insert(r);
      // m.insert(std::make_pair(ks, vs));
      ++io_success_count;
      ++op_success_count;
      arg.sh.increment_count();
    }
  }
#endif
}

struct mysqltest_thread_initobj : private noncopyable {
  mysqltest_thread_initobj() {
    mysql_thread_init();
  }
  ~mysqltest_thread_initobj() {
    mysql_thread_end();
  }
};

void
hstest_thread::test_9(int test_num)
{
  /* create table hstest
   * ( k varchar(255) not null, v varchar(255) not null, primary key(k))
   * engine = innodb; */
  auto_mysql db;
  // mysqltest_thread_initobj initobj;
  std::string err;
  const char op = arg.sh.op;
  const std::string suffix = arg.sh.conf.get_str("value_suffix", "upd");
  unsigned long long err_cnt = 0;
  unsigned long long query_cnt = 0;
  #if 0
  my_bool reconnect = 0;
  if (mysql_options(db, MYSQL_OPT_RECONNECT, &reconnect) != 0) {
    err = "mysql_options() failed";
    ++err_cnt;
    return;
  }
  #endif
  unsigned int seed = time(0) + arg.id + 1;
  seed ^= arg.sh.conf.get_int("seed_xor", 0);
  drand48_data randbuf;
  srand48_r(seed, &randbuf);
  const std::string mysql_host = arg.sh.conf.get_str("host", "localhost");
  const int mysql_port = arg.sh.conf.get_int("mysqlport", 3306);
  const int num = arg.sh.loop;
  const std::string mysql_user = arg.sh.conf.get_str("mysqluser", "root");
  const std::string mysql_passwd = arg.sh.conf.get_str("mysqlpass", "");
  const std::string mysql_dbname = arg.sh.conf.get_str("dbname", "hstest");
  const int keep_connection = arg.sh.conf.get_int("keep_connection", 1);
  const int verbose = arg.sh.conf.get_int("verbose", 1);
  const int tablesize = arg.sh.conf.get_int("tablesize", 10000);
  const int moreflds = arg.sh.conf.get_int("moreflds", 0);
  const std::string moreflds_prefix = arg.sh.conf.get_str(
    "moreflds_prefix", "column0123456789_");
  const int use_handler = arg.sh.conf.get_int("handler", 0);
  const int sched_flag = arg.sh.conf.get_int("sched", 0);
  const int use_in = arg.sh.conf.get_int("in", 0);
  const int ssps = use_in ? 0 : arg.sh.conf.get_int("ssps", 0);
  std::string flds = "v";
  for (int i = 0; i < moreflds; ++i) {
    char buf[1024];
    snprintf(buf, sizeof(buf), ",%s%d", moreflds_prefix.c_str(), i);
    flds += std::string(buf);
  }
  int connected = 0;
  std::auto_ptr<auto_mysql_stmt> stmt;
  string_buffer wbuf;
  for (int i = 0; i < num; ++i) {
    const double tm1 = gettimeofday_double();
    const int flags = 0;
    if (connected == 0) {
      if (!mysql_real_connect(db, mysql_host.c_str(),
	mysql_user.c_str(), mysql_user.empty() ? 0 : mysql_passwd.c_str(),
	mysql_dbname.c_str(), mysql_port, 0, flags)) {
	err = "failed to connect: " + std::string(mysql_error(db));
	if (verbose >= 1) {
	  fprintf(stderr, "e=[%s]\n", err.c_str());
	}
	++err_cnt;
	return;
      }
      arg.sh.increment_conn(1);
    }
    int r = 0;
    if (connected == 0 && use_handler) {
      const char *const q = "handler hstest_table1 open";
      r = mysql_real_query(db, q, strlen(q));
      if (r != 0) {
	err = 1;
      }
    }
    if (connected == 0 && ssps) {
      stmt.reset(new auto_mysql_stmt(db));
      const char *const q = "select v from hstest_table1 where k = ?";
      r = mysql_stmt_prepare(*stmt, q, strlen(q));
      if (r != 0) {
	fprintf(stderr, "ssps err\n");
	++err_cnt;
	return;
      }
    }
    connected = 1;
    std::string result_str;
    unsigned int err = 0;
    unsigned int num_flds = 0, num_affected_rows = 0;
    int got_data = 0;
    char buf_query[16384];
    int buf_query_len = 0;
    int k = 0, v = 0;
    {
      double kf = 0, vf = 0;
      drand48_r(&randbuf, &kf);
      drand48_r(&randbuf, &vf);
      k = int(kf * tablesize);
      v = int(vf * tablesize);
      #if 0
      k = rand_r(&seed);
      v = rand_r(&seed);
      if (tablesize != 0) {
	k %= tablesize;
      }
      #endif
      if (op == 'G') {
	if (use_handler) {
	  buf_query_len = snprintf(buf_query, sizeof(buf_query),
	    "handler hstest_table1 read `primary` = ( '%d' )", k);
	    // TODO: moreflds
	} else if (ssps) {
	    //
	} else if (use_in) {
	  wbuf.clear();
	  char *p = wbuf.make_space(1024);
	  int len = snprintf(p, 1024, "select %s from hstest_table1 where k in ('%d'", flds.c_str(), k);
	  wbuf.space_wrote(len);
	  for (int j = 1; j < use_in; ++j) {
	    /* generate more key */
	    drand48_r(&randbuf, &kf);
	    k = int(kf * tablesize);
	    p = wbuf.make_space(1024);
	    int len = snprintf(p, 1024, ", '%d'", k);
	    wbuf.space_wrote(len);
	  }
	  wbuf.append_literal(")");
	} else {
	  buf_query_len = snprintf(buf_query, sizeof(buf_query),
	    "select %s from hstest_table1 where k = '%d'", flds.c_str(), k);
	}
      } else if (op == 'U') {
	buf_query_len = snprintf(buf_query, sizeof(buf_query),
	  "update hstest_table1 set v = '%d_%d%s' where k = '%d'",
	    v, k, suffix.c_str(), k);
      } else if (op == 'R') {
	buf_query_len = snprintf(buf_query, sizeof(buf_query),
	  "replace into hstest_table1 values ('%d', 'v%d')", k, v);
	  // TODO: moreflds
      }
    }
    if (r == 0) {
      if (ssps) {
	MYSQL_BIND bind[1] = { };
	bind[0].buffer_type = MYSQL_TYPE_LONG;
	bind[0].buffer = (char *)&k;
	bind[0].is_null = 0;
	bind[0].length = 0;
	if (mysql_stmt_bind_param(*stmt, bind)) {
	  fprintf(stderr, "err: %s\n", mysql_stmt_error(*stmt));
	  ++err_cnt;
	  return;
	}
	r = mysql_stmt_execute(*stmt);
	// fprintf(stderr, "stmt exec\n");
      } else if (use_in) {
	r = mysql_real_query(db, wbuf.begin(), wbuf.size());
      } else {
	r = mysql_real_query(db, buf_query, buf_query_len);
	// fprintf(stderr, "real query\n");
      }
      ++query_cnt;
    }
    if (r != 0) {
      err = 1;
    } else if (ssps) {
      if (verbose >= 0) {
	char resbuf[1024];
	unsigned long res_len = 0;
	MYSQL_BIND bind[1] = { };
	bind[0].buffer_type = MYSQL_TYPE_STRING;
	bind[0].buffer = resbuf;
	bind[0].buffer_length = sizeof(resbuf);
	bind[0].length = &res_len;
	if (mysql_stmt_bind_result(*stmt, bind)) {
	  fprintf(stderr, "err: %s\n", mysql_stmt_error(*stmt));
	  ++err_cnt;
	  return;
	}
	if (mysql_stmt_fetch(*stmt)) {
	  fprintf(stderr, "err: %s\n", mysql_stmt_error(*stmt));
	  ++err_cnt;
	  return;
	}
	if (!result_str.empty()) {
	  result_str += " ";
	}
	result_str += std::string(resbuf, res_len);
	// fprintf(stderr, "SSPS RES: %s\n", result_str.c_str());
	got_data = 1;
      } else {
	got_data = 1;
      }
    } else {
      auto_mysql_res res(db);
      if (res != 0) {
	if (verbose >= 0) {
	  num_flds = mysql_num_fields(res);
	  MYSQL_ROW row = 0;
	  while ((row = mysql_fetch_row(res)) != 0) {
	    got_data += 1;
	    unsigned long *const lengths = mysql_fetch_lengths(res);
	    if (verbose >= 2) {
	      for (unsigned int i = 0; i < num_flds; ++i) {
		if (!result_str.empty()) {
		  result_str += " ";
		}
		result_str += std::string(row[i], lengths[i]);
	      }
	    }
	  }
	} else {
	  MYSQL_ROW row = 0;
	  while ((row = mysql_fetch_row(res)) != 0) {
	    got_data += 1;
	  }
	}
      } else {
	if (mysql_field_count(db) == 0) {
	  num_affected_rows = mysql_affected_rows(db);
	} else {
	  err = 1;
	}
      }
    }
    if (verbose >= 2 || (verbose >= 1 && err != 0)) {
      if (err) {
	++err_cnt;
	const char *const errstr = mysql_error(db);
	fprintf(stderr, "e=[%s] a=%u q=[%s]\n", errstr,
	  num_affected_rows, buf_query);
      } else {
	fprintf(stderr, "a=%u q=[%s] r=[%s]\n", num_affected_rows, buf_query,
	  result_str.c_str());
      }
    }
    if (err == 0) {
      ++io_success_count;
      if (num_affected_rows > 0 || got_data > 0) {
	op_success_count += got_data;
      } else {
	if (verbose >= 1) {
	  fprintf(stderr, "k=%d numaff=%u gotdata=%d\n",
	    k, num_affected_rows, got_data);
	}
      }
      arg.sh.increment_count();
    }
    if (!keep_connection) {
      if (stmt.get() != 0) {
	stmt.reset();
      }
      db.reset();
      connected = 0;
    }
    const double tm2 = gettimeofday_double();
    set_timing(tm2 - tm1);
    sleep_if();
    if (sched_flag) {
      sched_yield();
    }
  }
  if (verbose >= 1) {
    fprintf(stderr, "thread finished (error_count=%llu)\n", err_cnt);
  }
}

void
hstest_thread::test_10(int test_num)
{
  const int keep_connection = arg.sh.conf.get_int("keep_connection", 1);
  unsigned int seed = time(0) + arg.id + 1;
  seed ^= arg.sh.conf.get_int("seed_xor", 0);
  drand48_data randbuf;
  srand48_r(seed, &randbuf);
  std::string err;
  int keepconn_count = 0;
  const char op = arg.sh.op;
  const int verbose = arg.sh.conf.get_int("verbose", 1);
  const std::string suffix = arg.sh.conf.get_str("value_suffix", "upd");
  const int tablesize = arg.sh.conf.get_int("tablesize", 10000);
  const int firstkey = arg.sh.conf.get_int("firstkey", 0);
  const int sched_flag = arg.sh.conf.get_int("sched", 0);
  const int moreflds = arg.sh.conf.get_int("moreflds", 0);
  const std::string dbname = arg.sh.conf.get_str("dbname", "hstest");
  const std::string table = arg.sh.conf.get_str("table", "hstest_table1");
  const std::string index = arg.sh.conf.get_str("index", "PRIMARY");
  const std::string field = arg.sh.conf.get_str("field", "v");
  const int use_in = arg.sh.conf.get_int("in", 0);
  const std::string moreflds_prefix = arg.sh.conf.get_str(
    "moreflds_prefix", "column0123456789_");
  const int dump = arg.sh.dump;
  const int nodup = arg.sh.conf.get_int("nodup", 0);
  std::string moreflds_str;
  for (int i = 0; i < moreflds; ++i) {
    char sbuf[1024];
    snprintf(sbuf, sizeof(sbuf), ",%s%d", moreflds_prefix.c_str(), i);
    moreflds_str += std::string(sbuf);
  }
  string_buffer wbuf;
  char rbuf[16384];
  for (size_t i = 0; i < arg.sh.loop; ++i) {
    int len = 0, rlen = 0, wlen = 0;
    #if 0
    const double tm1 = gettimeofday_double();
    #endif
    if (fd.get() < 0) {
      if (socket_connect(fd, arg.sh.arg, err) != 0) {
	fprintf(stderr, "connect: %d %s\n", errno, strerror(errno));
	return;
      }
      char *wp = wbuf.make_space(1024);
      len = snprintf(wp, 1024,
	"P\t1\t%s\t%s\tPRIMARY\t%s%s\n", dbname.c_str(), table.c_str(),
	  field.c_str(), moreflds_str.c_str());
	/* pst_num, db, table, index, retflds */
      wbuf.space_wrote(len);
      wlen = write(fd.get(), wbuf.begin(), len);
      if (len != wlen) {
	fprintf(stderr, "write: %d %d\n", len, wlen);
	return;
      }
      wbuf.clear();
      rlen = read(fd.get(), rbuf, sizeof(rbuf));
      if (rlen <= 0 || rbuf[rlen - 1] != '\n') {
	fprintf(stderr, "read: rlen=%d errno=%d\n", rlen, errno);
	return;
      }
      if (rbuf[0] != '0') {
	fprintf(stderr, "failed to open table\n");
	return;
      }
      arg.sh.increment_conn(1);
    }
    const double tm1 = gettimeofday_double();
    for (size_t j = 0; j < arg.sh.pipe; ++j) {
      int k = 0, v = 0;
      {
	while (true) {
	  double kf = 0, vf = 0;
	  drand48_r(&randbuf, &kf);
	  drand48_r(&randbuf, &vf);
	  k = int(kf * tablesize) + firstkey;
	  v = int(vf * tablesize) + firstkey;
	  if (k - firstkey < arg.sh.keygen_size) {
	    volatile char *const ptr = arg.sh.keygen + (k - firstkey);
	    // int oldv = __sync_fetch_and_or(ptr, 1);
	    int oldv = *ptr;
	    *ptr += 1;
	    if (nodup && oldv != 0) {
	      if (dump) {
		fprintf(stderr, "retry\n");
	      }
	      continue;
	    }
	  } else {
	    if (nodup) {
	      if (dump) {
		fprintf(stderr, "retry2\n");
	      }
	      continue;
	    }
	  }
	  size_t len = 0;
	  if (op == 'G') {
	    if (use_in) {
	      char *wp = wbuf.make_space(1024);
	      len = snprintf(wp, 1024, "1\t=\t1\t\t%d\t0\t@\t0\t%d\t%d",
		use_in, use_in, k);
	      wbuf.space_wrote(len);
	      for (int j = 1; j < use_in; ++j) {
		drand48_r(&randbuf, &kf);
		k = int(kf * tablesize) + firstkey;
		char *wp = wbuf.make_space(1024);
		len = snprintf(wp, 1024, "\t%d", k);
		wbuf.space_wrote(len);
	      }
	      wbuf.append_literal("\n");
	    } else {
	      char *wp = wbuf.make_space(1024);
	      len = snprintf(wp, 1024, "1\t=\t1\t%d\n", k);
	      wbuf.space_wrote(len);
	    }
	  } else if (op == 'U') {
	    char *wp = wbuf.make_space(1024);
	    len = snprintf(wp, 1024,
	      "1\t=\t1\t%d\t1\t0\tU\t%d_%d%s\n", k, v, k, suffix.c_str());
	    wbuf.space_wrote(len);
	  }
	  break;
	}
      }
    }
    wlen = write(fd.get(), wbuf.begin(), wbuf.size());
    if (wlen != wbuf.size()) {
      fprintf(stderr, "write: %d %d\n", (int)wbuf.size(), wlen);
      return;
    }
    wbuf.clear();
    size_t read_cnt = 0;
    size_t read_pos = 0;
    while (read_cnt < arg.sh.pipe) {
      rlen = read(fd.get(), rbuf + read_pos, sizeof(rbuf) - read_pos);
      if (rlen <= 0) {
	fprintf(stderr, "read: %d\n", rlen);
	return;
      }
      read_pos += rlen;
      while (true) {
	const char *const nl = static_cast<const char *>(memchr(rbuf, '\n',
	  read_pos));
	if (nl == 0) {
	  break;
	}
	++read_cnt;
	++io_success_count;
	const char *t1 = static_cast<const char *>(memchr(rbuf, '\t',
	  nl - rbuf));
	if (t1 == 0) {
	  fprintf(stderr, "error \n");
	  break;
	}
	++t1;
	const char *t2 = static_cast<const char *>(memchr(t1, '\t',
	  nl - t1));
	if (t2 == 0) {
	  if (verbose > 1) {
	    fprintf(stderr, "key: notfound \n");
	  }
	  break;
	}
	++t2;
	if (t1 == rbuf + 2 && rbuf[0] == '0') {
	  if (op == 'G') {
	    ++op_success_count;
	    arg.sh.increment_count();
	  } else if (op == 'U') {
	    const char *t3 = t2;
	    while (t3 != nl && t3[0] >= 0x10) {
	      ++t3;
	    }
	    if (t3 != t2 + 1 || t2[0] != '1') {
	      const std::string mess(t2, t3);
	      fprintf(stderr, "mod: %s\n", mess.c_str());
	    } else {
	      ++op_success_count;
	      arg.sh.increment_count();
	      if (arg.sh.dump && arg.sh.pipe == 1) {
		fwrite(wbuf.begin(), wbuf.size(), 1, stderr);
	      }
	    }
	  }
	} else {
	  const char *t3 = t2;
	  while (t3 != nl && t3[0] >= 0x10) {
	    ++t3;
	  }
	  const std::string mess(t2, t3);
	  fprintf(stderr, "err: %s\n", mess.c_str());
	}
	const size_t rest_size = rbuf + read_pos - (nl + 1);
	if (rest_size != 0) {
	  memmove(rbuf, nl + 1, rest_size);
	}
	read_pos = rest_size;
      }
    }
    if (!keep_connection) {
      fd.reset();
      arg.sh.increment_conn(-1);
    } else if (keep_connection > 1 && ++keepconn_count > keep_connection) {
      keepconn_count = 0;
      fd.reset();
      arg.sh.increment_conn(-1);
    }
    const double tm2 = gettimeofday_double();
    set_timing(tm2 - tm1);
    sleep_if();
    if (sched_flag) {
      sched_yield();
    }
  }
  if (dump) {
    fprintf(stderr, "done\n");
  }
}

void
hstest_thread::sleep_if()
{
  if (arg.sh.usleep) {
    struct timespec ts = {
      arg.sh.usleep / 1000000,
      (arg.sh.usleep % 1000000) * 1000
    };
    nanosleep(&ts, 0);
  }
}

void
hstest_thread::set_timing(double time_spent)
{
  response_min = std::min(response_min, time_spent);
  response_max = std::max(response_max, time_spent);
  response_sum += time_spent;
  if (op_success_count != 0) {
    response_avg = response_sum / op_success_count;
  }
}

void
hstest_thread::test_11(int test_num)
{
  const int keep_connection = arg.sh.conf.get_int("keep_connection", 1);
  const int tablesize = arg.sh.conf.get_int("tablesize", 0);
  unsigned int seed = arg.id;
  seed ^= arg.sh.conf.get_int("seed_xor", 0);
  std::string err;
  hstcpcli_ptr cli;
  for (size_t i = 0; i < arg.sh.loop; ++i) {
    if (cli.get() == 0) {
      cli = hstcpcli_i::create(arg.sh.arg);
      cli->request_buf_open_index(0, "hstest", "hstest_table1", "", "v");
	/* pst_num, db, table, index, retflds */
      if (cli->request_send() != 0) {
	fprintf(stderr, "reuqest_send: %s\n", cli->get_error().c_str());
	return;
      }
      size_t num_flds = 0;
      if (cli->response_recv(num_flds) != 0) {
	fprintf(stderr, "reuqest_recv: %s\n", cli->get_error().c_str());
	return;
      }
      cli->response_buf_remove();
    }
    for (size_t j = 0; j < arg.sh.pipe; ++j) {
      char buf[256];
      int k = 0, v = 0, len = 0;
      {
	k = rand_r(&seed);
	v = rand_r(&seed); /* unused */
	if (tablesize != 0) {
	  k &= tablesize;
	}
	len = snprintf(buf, sizeof(buf), "%d", k);
      }
      const string_ref key(buf, len);
      const string_ref op("=", 1);
      cli->request_buf_exec_generic(0, op, &key, 1, 1, 0, string_ref(), 0, 0);
    }
    if (cli->request_send() != 0) {
      fprintf(stderr, "reuqest_send: %s\n", cli->get_error().c_str());
      return;
    }
    size_t read_cnt = 0;
    for (size_t j = 0; j < arg.sh.pipe; ++j) {
      size_t num_flds = 0;
      if (cli->response_recv(num_flds) != 0) {
	fprintf(stderr, "reuqest_recv: %s\n", cli->get_error().c_str());
	return;
      }
      {
	++read_cnt;
	++io_success_count;
	arg.sh.increment_count();
	{
	  ++op_success_count;
	}
      }
      cli->response_buf_remove();
    }
    if (!keep_connection) {
      cli.reset();
    }
  }
}

void
hstest_thread::test_watch()
{
  const int timelimit = arg.sh.conf.get_int("timelimit", 0);
  const int timelimit_offset = timelimit / 2;
  int loop = 0;
  double t1 = 0, t2 = 0;
  size_t cnt_t1 = 0, cnt_t2 = 0;
  size_t prev_cnt = 0;
  double now_f = 0;
  while (true) {
    sleep(1);
    const size_t cnt = arg.sh.count;
    const size_t df = cnt - prev_cnt;
    prev_cnt = cnt;
    const double now_prev = now_f;
    now_f = gettimeofday_double();
    if (now_prev != 0) {
      const double rps = static_cast<double>(df) / (now_f - now_prev);
      fprintf(stderr, "now: %zu cntdiff: %zu tdiff: %f rps: %f\n",
        static_cast<size_t>(now_f), df, now_f - now_prev, rps);
    }
    if (timelimit != 0) {
      if (arg.sh.wait_conn == 0 || arg.sh.conn_count >= arg.sh.wait_conn) {
	++loop;
      }
      if (loop == timelimit_offset) {
        t1 = gettimeofday_double();
        cnt_t1 = cnt;
	arg.sh.enable_timing = 1;
	fprintf(stderr, "start timing\n");
      } else if (loop == timelimit_offset + timelimit) {
        t2 = gettimeofday_double();
        cnt_t2 = cnt;
        const size_t cnt_diff = cnt_t2 - cnt_t1;
        const double tdiff = t2 - t1;
        const double qps = cnt_diff / (tdiff != 0 ? tdiff : 1);
        fprintf(stderr, "(%f: %zu, %f: %zu), %10.5f qps\n",
          t1, cnt_t1, t2, cnt_t2, qps);
	size_t keycnt = 0;
	for (int i = 0; i < arg.sh.keygen_size; ++i) {
	  if (arg.sh.keygen[i]) {
	    ++keycnt;
	  }
	}
	fprintf(stderr, "keygen=%zu\n", keycnt);
	break;
      }
    }
  }
#if 0
  int loop = 0;
  double t1 = 0, t2 = 0;
  size_t cnt_t1 = 0, cnt_t2 = 0;
  size_t prev_cnt = 0;
  while (true) {
    sleep(1);
    const size_t cnt = arg.sh.count;
    const size_t df = cnt - prev_cnt;
    prev_cnt = cnt;
    const size_t now = time(0);
    fprintf(stderr, "%zu %zu\n", now, df);
    if (timelimit != 0) {
      ++loop;
      if (loop == timelimit_offset) {
	t1 = gettimeofday_double();
	cnt_t1 = cnt;
      } else if (loop == timelimit_offset + timelimit) {
	t2 = gettimeofday_double();
	cnt_t2 = cnt;
	const size_t cnt_diff = cnt_t2 - cnt_t1;
	const double tdiff = t2 - t1;
	const double qps = cnt_diff / (tdiff != 0 ? tdiff : 1);
	fprintf(stderr, "(%f: %zu, %f: %zu), %10.5f qps\n",
	  t1, cnt_t1, t2, cnt_t2, qps);
	size_t keycnt = 0;
	for (int i = 0; i < arg.sh.keygen_size; ++i) {
	  if (arg.sh.keygen[i]) {
	    ++keycnt;
	  }
	}
	fprintf(stderr, "keygen=%zu\n", keycnt);
	_exit(0);
      }
    }
  }
#endif
}

void
hstest_thread::test_12(int test_num)
{
  /* NOTE: num_threads should be 1 */
  /* create table hstest
   * ( k varchar(255) not null, v varchar(255) not null, primary key(k))
   * engine = innodb; */
  mysqltest_thread_initobj initobj;
  auto_mysql db;
  std::string err;
  unsigned long long err_cnt = 0;
  unsigned long long query_cnt = 0;
  #if 0
  my_bool reconnect = 0;
  if (mysql_options(db, MYSQL_OPT_RECONNECT, &reconnect) != 0) {
    err = "mysql_options() failed";
    ++err_cnt;
    return;
  }
  #endif
  const std::string mysql_host = arg.sh.conf.get_str("host", "localhost");
  const int mysql_port = arg.sh.conf.get_int("mysqlport", 3306);
  const unsigned int num = arg.sh.loop;
  const size_t pipe = arg.sh.pipe;
  const std::string mysql_user = arg.sh.conf.get_str("mysqluser", "root");
  const std::string mysql_passwd = arg.sh.conf.get_str("mysqlpass", "");
  const std::string mysql_dbname = arg.sh.conf.get_str("db", "hstest");
  const int keep_connection = arg.sh.conf.get_int("keep_connection", 1);
  const int verbose = arg.sh.conf.get_int("verbose", 1);
  const int use_handler = arg.sh.conf.get_int("handler", 0);
  int connected = 0;
  unsigned int k = 0;
  string_buffer buf;
  for (unsigned int i = 0; i < num; ++i) {
    const int flags = 0;
    if (connected == 0 && !mysql_real_connect(db, mysql_host.c_str(),
      mysql_user.c_str(), mysql_user.empty() ? 0 : mysql_passwd.c_str(),
      mysql_dbname.c_str(), mysql_port, 0, flags)) {
      err = "failed to connect: " + std::string(mysql_error(db));
      if (verbose >= 1) {
	fprintf(stderr, "e=[%s]\n", err.c_str());
      }
      ++err_cnt;
      return;
    }
    int r = 0;
    if (connected == 0 && use_handler) {
      const char *const q = "handler hstest open";
      r = mysql_real_query(db, q, strlen(q));
      if (r != 0) {
	err = 1;
      }
    }
    connected = 1;
    std::string result_str;
    unsigned int err = 0;
    unsigned int num_flds = 0, num_affected_rows = 0;
    int got_data = 0;
    buf.clear();
    buf.append_literal("insert into hstest values ");
    for (size_t j = 0; j < pipe; ++j) {
      const unsigned int v = ~k;
      if (j != 0) {
	buf.append_literal(",");
      }
      char *wp = buf.make_space(64);
      int buf_query_len = snprintf(wp, 64, "('k%u', 'v%u')", k, v);
      buf.space_wrote(buf_query_len);
      ++k;
    }
    if (r == 0) {
      r = mysql_real_query(db, buf.begin(), buf.size());
      ++query_cnt;
    }
    if (r != 0) {
      err = 1;
    } else {
      auto_mysql_res res(db);
      if (res != 0) {
	if (verbose >= 0) {
	  num_flds = mysql_num_fields(res);
	  MYSQL_ROW row = 0;
	  while ((row = mysql_fetch_row(res)) != 0) {
	    got_data = 1;
	    unsigned long *const lengths = mysql_fetch_lengths(res);
	    if (verbose >= 2) {
	      for (unsigned int i = 0; i < num_flds; ++i) {
		if (!result_str.empty()) {
		  result_str += " ";
		}
		result_str += std::string(row[i], lengths[i]);
	      }
	    }
	  }
	}
      } else {
	if (mysql_field_count(db) == 0) {
	  num_affected_rows = mysql_affected_rows(db);
	} else {
	  err = 1;
	}
      }
    }
    if (verbose >= 2 || (verbose >= 1 && err != 0)) {
      if (err) {
	++err_cnt;
	const char *const errstr = mysql_error(db);
	fprintf(stderr, "e=[%s] a=%u q=[%s]\n", errstr,
	  num_affected_rows, std::string(buf.begin(), buf.size()).c_str());
      } else {
	fprintf(stderr, "a=%u q=[%s] r=[%s]\n", num_affected_rows,
	  std::string(buf.begin(), buf.size()).c_str(),
	  result_str.c_str());
      }
    }
    if (err == 0) {
      ++io_success_count;
      if (num_affected_rows > 0 || got_data > 0) {
	++op_success_count;
      }
      arg.sh.increment_count(pipe);
    }
    if (!keep_connection) {
      db.reset();
      connected = 0;
    }
  }
  if (verbose >= 1) {
    fprintf(stderr, "thread finished (error_count=%llu)\n", err_cnt);
  }
}

void
hstest_thread::test_21(int num)
{
  /* fsync test */
  unsigned int id = arg.id;
  std::string err;
  #if 0
  if (socket_connect(fd, arg.sh.arg, err) != 0) {
    fprintf(stderr, "connect: %d %s\n", errno, strerror(errno));
    return;
  }
  #endif
  auto_file logfd;
  char fname[1024];
  snprintf(fname, sizeof(fname), "synctest_%u", id);
  int open_flags = O_WRONLY | O_CREAT | O_TRUNC | O_APPEND;
  logfd.reset(open(fname, open_flags, 0644));
  if (logfd.get() < 0) {
    fprintf(stderr, "open: %s: %d %s\n", fname, errno, strerror(errno));
    return;
  }
  char buf[1024];
  unsigned long long count = 0;
  while (true) {
    snprintf(buf, sizeof(buf), "%u %llu\n", id, count);
    const size_t len = strlen(buf);
    if (write(logfd.get(), buf, len) != (ssize_t)len) {
      fprintf(stderr, "write: %s: %d %s\n", fname, errno, strerror(errno));
      return;
    }
    #if 0
    if (write(fd.get(), buf, len) != (ssize_t)len) {
      fprintf(stderr, "write(sock): %d %s\n", errno, strerror(errno));
      return;
    }
    #endif
    if (fdatasync(logfd.get()) != 0) {
      fprintf(stderr, "fsync: %s: %d %s\n", fname, errno, strerror(errno));
      return;
    }
    ++count;
    ++op_success_count;
    arg.sh.increment_count();
  }
}

void
hstest_thread::test_22(int num)
{
  /* dd if=/dev/zero of=dummy.dat bs=1024M count=100 */
  unsigned int id = arg.id;
  std::string err;
  auto_file filefd;
  char fname[1024];
  snprintf(fname, sizeof(fname), "dummy.dat");
  int open_flags = O_RDONLY | O_DIRECT;
  filefd.reset(open(fname, open_flags, 0644));
  if (filefd.get() < 0) {
    fprintf(stderr, "open: %s: %d %s\n", fname, errno, strerror(errno));
    return;
  }
  char buf_x[4096 * 2];
  char *const buf = (char *)(size_t(buf_x + 4096) / 4096 * 4096);
  unsigned long long count = 0;
  drand48_data randbuf;
  unsigned long long seed = time(0);
  seed *= 10;
  seed += id;
  srand48_r(seed, &randbuf);
  for (unsigned int i = 0; i < arg.sh.loop; ++i) {
    double kf = 0;
    drand48_r(&randbuf, &kf);
    kf *= (209715200 / 1);
    // fprintf(stderr, "v=%f\n", kf);
    off_t v = static_cast<off_t>(kf);
    v %= (209715200 / 1);
    v *= (512 * 1);
    const double tm1 = gettimeofday_double();
    const ssize_t r = pread(filefd.get(), buf, (512 * 1), v);
    const double tm2 = gettimeofday_double();
    if (r < 0) {
      fprintf(stderr, "pread: %s: %d %s\n", fname, errno, strerror(errno));
      return;
    }
    ++count;
    ++op_success_count;
    arg.sh.increment_count();
    set_timing(tm2 - tm1);
  }
}

void
hstest_thread::operator ()()
{
  if (arg.watch_flag) {
    return test_watch();
  }
  int test_num = arg.sh.conf.get_int("test", 1);
  if (test_num == 1) {
    test_1();
  } else if (test_num == 2 || test_num == 3) {
    test_2_3(test_num);
  } else if (test_num == 4 || test_num == 5) {
    test_4_5(test_num);
  } else if (test_num == 6) {
    test_6(test_num);
  } else if (test_num == 7) {
    test_7(test_num);
  } else if (test_num == 8) {
    test_8(test_num);
  } else if (test_num == 9) {
    test_9(test_num);
  } else if (test_num == 10) {
    test_10(test_num);
  } else if (test_num == 11) {
    test_11(test_num);
  } else if (test_num == 12) {
    test_12(test_num);
  } else if (test_num == 21) {
    test_21(test_num);
  } else if (test_num == 22) {
    test_22(test_num);
  }
  const int halt = arg.sh.conf.get_int("halt", 0);
  if (halt) {
    fprintf(stderr, "thread halted\n");
    while (true) {
      sleep(100000);
    }
  }
  fprintf(stderr, "thread finished\n");
}

int
hstest_main(int argc, char **argv)
{
  ignore_sigpipe();
  hstest_shared shared;
  parse_args(argc, argv, shared.conf);
  shared.conf["port"] = shared.conf["hsport"];
  shared.arg.set(shared.conf);
  shared.loop = shared.conf.get_int("num", 1000);
  shared.pipe = shared.conf.get_int("pipe", 1);
  shared.verbose = shared.conf.get_int("verbose", 1);
  const int tablesize = shared.conf.get_int("tablesize", 0);
  std::vector<char> keygen(tablesize);
  shared.keygen = &keygen[0];
  shared.keygen_size = tablesize;
  shared.usleep = shared.conf.get_int("usleep", 0);
  shared.dump = shared.conf.get_int("dump", 0);
  shared.num_threads = shared.conf.get_int("num_threads", 10);
  shared.wait_conn = shared.conf.get_int("wait_conn", 0);
  const std::string op = shared.conf.get_str("op", "G");
  if (op.size() > 0) {
    shared.op = op[0];
  }
  #if 0
  const int localdb_flag = shared.conf.get_int("local", 0);
  if (localdb_flag) {
    shared.localdb = database_i::create(shared.conf);
  }
  #endif
  const int num_thrs = shared.num_threads;
  typedef thread<hstest_thread> thread_type;
  typedef std::auto_ptr<thread_type> thread_ptr;
  typedef auto_ptrcontainer< std::vector<thread_type *> > thrs_type;
  thrs_type thrs;
  for (int i = 0; i < num_thrs; ++i) {
    const hstest_thread::arg_type arg(i, shared, false);
    thread_ptr thr(new thread<hstest_thread>(arg));
    thrs.push_back_ptr(thr);
  }
  for (size_t i = 0; i < thrs.size(); ++i) {
    thrs[i]->start();
  }
  thread_ptr watch_thread;
  const int timelimit = shared.conf.get_int("timelimit", 0);
  {
    const hstest_thread::arg_type arg(0, shared, true);
    watch_thread = thread_ptr(new thread<hstest_thread>(arg));
    watch_thread->start();
  }
  size_t iocnt = 0, opcnt = 0;
  double respmin = 999999, respmax = 0;
  double respsum = 0;
  if (timelimit != 0) {
    watch_thread->join();
  }
  for (size_t i = 0; i < thrs.size(); ++i) {
    if (timelimit == 0) {
      thrs[i]->join();
    }
    iocnt += (*thrs[i])->io_success_count;
    opcnt += (*thrs[i])->op_success_count;
    respmin = std::min(respmin, (*thrs[i])->response_min);
    respmax = std::max(respmax, (*thrs[i])->response_max);
    respsum += (*thrs[i])->response_sum;
  }
  fprintf(stderr, "io_success_count=%zu op_success_count=%zu\n", iocnt, opcnt);
  fprintf(stderr, "respmin=%f respmax=%f respsum=%f respavg=%f\n",
    respmin, respmax, respsum, respsum / opcnt);
  size_t keycnt = 0;
  for (size_t i = 0; i < keygen.size(); ++i) {
    if (keygen[i]) {
      ++keycnt;
    }
  }
  fprintf(stderr, "keycnt=%zu\n", keycnt);
  _exit(0);
  return 0;
}

};

int
main(int argc, char **argv)
{
  return dena::hstest_main(argc, argv);
}



<|start_filename|>codeview/src/main/java/io/github/kbiakov/codeview/views/BidirectionalScrollView.kt<|end_filename|>
package io.github.kbiakov.codeview.views

import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.view.View.MeasureSpec.makeMeasureSpec
import android.widget.HorizontalScrollView
import io.github.kbiakov.codeview.dpToPx

/**
 * @class BidirectionalScrollView
 *
 * Combines vertical & horizontal scroll to implement bidirectional
 * scrolling behavior (like a map view, for example).
 *
 * @author <NAME>
 */
class BidirectionalScrollView : HorizontalScrollView {

    private var currentX = 0
    private var currentY = 0
    private var isMoved = false

    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

    override fun dispatchTouchEvent(event: MotionEvent): Boolean {
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                currentX = event.rawX.toInt()
                currentY = event.rawY.toInt()
                return super.dispatchTouchEvent(event)
            }
            MotionEvent.ACTION_MOVE -> {
                val deltaX = Math.abs(currentX - event.rawX)
                val deltaY = Math.abs(currentY - event.rawY)
                scroll(event)

                val movedOnDistance = dpToPx(context, 2)
                if (deltaX > movedOnDistance || deltaY > movedOnDistance) {
                    isMoved = true
                }
            }
            MotionEvent.ACTION_UP -> {
                if (!isMoved) {
                    return super.dispatchTouchEvent(event)
                }
                isMoved = false
            }
            MotionEvent.ACTION_CANCEL -> {
                isMoved = false
            }
        }
        return true
    }

    private fun scroll(event: MotionEvent) {
        val x2 = event.rawX.toInt()
        val y2 = event.rawY.toInt()
        val posX = currentX - x2
        val posY = currentY - y2
        scrollBy(posX, posY)

        currentX = x2
        currentY = y2
    }

    override fun measureChild(child: View, parentWidthMeasureSpec: Int, parentHeightMeasureSpec: Int) {
        val zeroMeasureSpec = makeMeasureSpec(0)
        child.measure(zeroMeasureSpec, zeroMeasureSpec)
    }

    override fun measureChildWithMargins(
            child: View,
            parentWidthMeasureSpec: Int, widthUsed: Int,
            parentHeightMeasureSpec: Int, heightUsed: Int
    ) = with(child.layoutParams as MarginLayoutParams) {
        val widthMeasureSpec = makeMeasureSpec(leftMargin + rightMargin, MeasureSpec.UNSPECIFIED)
        val heightMeasureSpec = makeMeasureSpec(topMargin + bottomMargin, MeasureSpec.UNSPECIFIED)
        child.measure(widthMeasureSpec, heightMeasureSpec)
    }

    private fun makeMeasureSpec(size: Int) = makeMeasureSpec(size, MeasureSpec.UNSPECIFIED)
}


<|start_filename|>codeview/src/main/java/io/github/kbiakov/codeview/highlight/prettify/lang/LangMd.java<|end_filename|>
package io.github.kbiakov.codeview.highlight.prettify.lang;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
import io.github.kbiakov.codeview.highlight.prettify.parser.Prettify;

/**
 * Registers a language handler for markdown.
 *
 * @author <NAME> (<EMAIL>)
 */
public class LangMd extends Lang {

    public LangMd() {
        List<List<Object>> _shortcutStylePatterns = new ArrayList<List<Object>>();
        List<List<Object>> _fallthroughStylePatterns = new ArrayList<List<Object>>();

        _fallthroughStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_DECLARATION, Pattern.compile("^#.*?[\\n\\r]")}));
        _fallthroughStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_STRING, Pattern.compile("^```[\\s\\S]*?(?:```|$)")}));

        setShortcutStylePatterns(_shortcutStylePatterns);
        setFallthroughStylePatterns(_fallthroughStylePatterns);
    }

    public static List<String> getFileExtensions() {
        return Arrays.asList(new String[]{"md", "markdown"});
    }
}


<|start_filename|>codeview/src/main/assets/training-set/csharp/csharp.cs<|end_filename|>
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using CodeClassifier.StringTokenizer;

namespace CodeClassifier
{
	public class CodeClassifier
	{
		private static CodeClassifier _instance;

		private const double SCORE_MULTIPLIER_PER_LEVEL = 2;
		private const double SCORE_MULTIPLIER_FOR_EXACT_MATCH = 5;

		private static List<MatchTree> _matchTrees;

		private CodeClassifier()
		{
			string trainingSetPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			if (trainingSetPath == null)
			{
				throw new DirectoryNotFoundException("Could not find the training-set folder.");
			}

			// Train classifier
			string path = Path.Combine(trainingSetPath, "training-set");
			string[] folders = Directory.GetDirectories(path);
			foreach (string folder in folders)
			{
				string[] files = Directory.GetFiles(folder);
				_matchTrees = new List<MatchTree>();
				foreach (string filePath in files)
				{
					string languageName = Path.GetFileNameWithoutExtension(filePath);
					if (languageName != null)
					{
						// Calculate the total possible score to normalize the score results
						double totalPossibleScore;
						TokenNode rootNode = BuildMatchTree(File.ReadAllText(filePath), out totalPossibleScore);
						_matchTrees.Add(new MatchTree(rootNode, languageName, totalPossibleScore));
					}
				}
			}
		}

		private static TokenNode BuildMatchTree(string trainingCode, out double totalScorePossible)
		{
			List<Token> tokens = GetAllTokens(trainingCode);

			// Recursivly build the tree
			TokenNode root = new TokenNode(TokenKind.Unknown, 0, 1, null);
			double totalScore = 0;
			for (int index = 0; index < tokens.Count-1; index++)
			{
				totalScore += AddTokens(root, tokens, index);
			}

			totalScorePossible = totalScore;
			return root;
		}

		private static double AddTokens(TokenNode tokenNode, IList<Token> tokens, int index)
		{
			double totalScore = 0;
			while (index < tokens.Count && tokenNode.Level < 10)
			{
				Token codeToken = tokens[index];
				TokenNode nextTreeToken = tokenNode.NextTokens.FirstOrDefault(nt => nt.Kind == codeToken.Kind);
				if (nextTreeToken == null)
				{
					// Token doesn't exist on this tree level yet
					var newToken = new TokenNode(codeToken.Kind, tokenNode.Level + 1, tokenNode.Score * SCORE_MULTIPLIER_PER_LEVEL, codeToken.Value);
					totalScore += tokenNode.Score * SCORE_MULTIPLIER_PER_LEVEL;
					tokenNode.NextTokens.Add(newToken);
					tokenNode = newToken;
				}
				else
				{
					// Token already exists on this level
					nextTreeToken.Examples.Add(codeToken.Value);
					tokenNode = nextTreeToken;
				}
				index++;
			}
			return totalScore;
		}

		private static List<Token> GetAllTokens(string code)
		{
			StringTokenizer.StringTokenizer stringTokenizer = new StringTokenizer.StringTokenizer(code);

			List<Token> tokens = new List<Token>();
			Token token;
			do
			{
				token = stringTokenizer.Next();
				tokens.Add(token);
			} while (token.Kind != TokenKind.Eof);
			return tokens;
		}

		public static string Classify(string snippet  )
		{
			// ReSharper disable once RedundantAssignment
			Dictionary<string, double> scores;
			return Classify(snippet, out scores);
		}

		public static string Classify(string snippet, out Dictionary<string, double> scores  )
		{
			if (_instance == null)
			{
				_instance = new CodeClassifier();
			}

			scores = new Dictionary<string, double>();

			List<Token> tokens = GetAllTokens(snippet);
			double maxScore = 0;
			string bestMatchLanguage = null;

			foreach (MatchTree matchTree in _matchTrees)
			{
				double score = 0;
				for (int index = 0; index < tokens.Count; index++)
				{
					score += ScoreTokens(matchTree.MatchTreeRoot, tokens, index);
				}
				score = score / tokens.Count() / matchTree.TotalPossibleScore;

				//Console.WriteLine(matchTree.Language + "\t" + score);
				scores.Add(matchTree.Language, score);
				if (score > maxScore)
				{
					maxScore = score;
					bestMatchLanguage = matchTree.Language;
				}
			}
			return bestMatchLanguage;
		}

		private static double ScoreTokens(TokenNode tokenNode, IList<Token> tokens, int index)
		{
			Token codeToken = tokens[index];
			TokenNode nextToken = tokenNode.NextTokens.FirstOrDefault(nt => nt.Kind == codeToken.Kind);
			if (nextToken != null)
			{
				// Token exists in match tree => points !!!
				double score = nextToken.Examples.Contains(codeToken.Value) ?
									SCORE_MULTIPLIER_FOR_EXACT_MATCH:
									SCORE_MULTIPLIER_PER_LEVEL;

				if (index < tokens.Count() - 1)
				{
					return score * ScoreTokens(nextToken, tokens, index + 1);
				}
				return score;
			}
			// Token did not exist => no points
			return 1;
		}
	}
}

<|start_filename|>codeview/src/main/java/io/github/kbiakov/codeview/highlight/prettify/lang/LangCss.java<|end_filename|>
// Copyright (C) 2009 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package io.github.kbiakov.codeview.highlight.prettify.lang;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
import io.github.kbiakov.codeview.highlight.prettify.parser.Prettify;

/**
 * This is similar to the lang-css.js in JavaScript Prettify.
 * 
 * All comments are adapted from the JavaScript Prettify.
 * 
 * <p>
 * Registers a language handler for CSS.
 *
 *
 * To use, include prettify.js and this file in your HTML page.
 * Then put your code in an HTML tag like
 *      <pre class="prettyprint lang-css"></pre>
 *
 *
 * http://www.w3.org/TR/CSS21/grammar.html Section G2 defines the lexical
 * grammar.  This scheme does not recognize keywords containing escapes.
 *
 * @author <EMAIL>
 */
public class LangCss extends Lang {

  public LangCss() {
    List<List<Object>> _shortcutStylePatterns = new ArrayList<List<Object>>();
    List<List<Object>> _fallthroughStylePatterns = new ArrayList<List<Object>>();

    // The space production <s>
    _shortcutStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_PLAIN, Pattern.compile("^[ \t\r\n\f]+"), null, " \t\r\n\f"}));
    // Quoted strings.  <string1> and <string2>
    _fallthroughStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_STRING, Pattern.compile("^\\\"(?:[^\n\r\f\\\\\\\"]|\\\\(?:\r\n?|\n|\f)|\\\\[\\s\\S])*\\\""), null}));
    _fallthroughStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_STRING, Pattern.compile("^\\'(?:[^\n\r\f\\\\\\']|\\\\(?:\r\n?|\n|\f)|\\\\[\\s\\S])*\\'"), null}));
    _fallthroughStylePatterns.add(Arrays.asList(new Object[]{"lang-css-str", Pattern.compile("^url\\(([^\\)\\\"\\']+)\\)", Pattern.CASE_INSENSITIVE)}));
    _fallthroughStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_KEYWORD, Pattern.compile("^(?:url|rgb|\\!important|@import|@page|@media|@charset|inherit)(?=[^\\-\\w]|$)", Pattern.CASE_INSENSITIVE), null}));
    // A property name -- an identifier followed by a colon.
    _fallthroughStylePatterns.add(Arrays.asList(new Object[]{"lang-css-kw", Pattern.compile("^(-?(?:[_a-z]|(?:\\\\[0-9a-f]+ ?))(?:[_a-z0-9\\-]|\\\\(?:\\\\[0-9a-f]+ ?))*)\\s*:", Pattern.CASE_INSENSITIVE)}));
    // A C style block comment.  The <comment> production.
    _fallthroughStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_COMMENT, Pattern.compile("^\\/\\*[^*]*\\*+(?:[^\\/*][^*]*\\*+)*\\/")}));
    // Escaping text spans
    _fallthroughStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_COMMENT, Pattern.compile("^(?:<!--|-->)")}));
    // A number possibly containing a suffix.
    _fallthroughStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_LITERAL, Pattern.compile("^(?:\\d+|\\d*\\.\\d+)(?:%|[a-z]+)?", Pattern.CASE_INSENSITIVE)}));
    // A hex color
    _fallthroughStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_LITERAL, Pattern.compile("^#(?:[0-9a-f]{3}){1,2}\\b", Pattern.CASE_INSENSITIVE)}));
    // An identifier
    _fallthroughStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_PLAIN, Pattern.compile("^-?(?:[_a-z]|(?:\\\\[\\da-f]+ ?))(?:[_a-z\\d\\-]|\\\\(?:\\\\[\\da-f]+ ?))*", Pattern.CASE_INSENSITIVE)}));
    // A run of punctuation
    _fallthroughStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_PUNCTUATION, Pattern.compile("^[^\\s\\w\\'\\\"]+", Pattern.CASE_INSENSITIVE)}));

    setShortcutStylePatterns(_shortcutStylePatterns);
    setFallthroughStylePatterns(_fallthroughStylePatterns);

    setExtendedLangs(Arrays.asList(new Lang[]{new LangCssKeyword(), new LangCssString()}));
  }

  public static List<String> getFileExtensions() {
    return Arrays.asList(new String[]{"css"});
  }

  protected static class LangCssKeyword extends Lang {

    public LangCssKeyword() {
      List<List<Object>> _shortcutStylePatterns = new ArrayList<List<Object>>();
      List<List<Object>> _fallthroughStylePatterns = new ArrayList<List<Object>>();

      _fallthroughStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_KEYWORD, Pattern.compile("^-?(?:[_a-z]|(?:\\\\[\\da-f]+ ?))(?:[_a-z\\d\\-]|\\\\(?:\\\\[\\da-f]+ ?))*", Pattern.CASE_INSENSITIVE)}));

      setShortcutStylePatterns(_shortcutStylePatterns);
      setFallthroughStylePatterns(_fallthroughStylePatterns);
    }

    public static List<String> getFileExtensions() {
      return Arrays.asList(new String[]{"css-kw"});
    }
  }

  protected static class LangCssString extends Lang {

    public LangCssString() {
      List<List<Object>> _shortcutStylePatterns = new ArrayList<List<Object>>();
      List<List<Object>> _fallthroughStylePatterns = new ArrayList<List<Object>>();

      _fallthroughStylePatterns.add(Arrays.asList(new Object[]{Prettify.PR_STRING, Pattern.compile("^[^\\)\\\"\\']+")}));

      setShortcutStylePatterns(_shortcutStylePatterns);
      setFallthroughStylePatterns(_fallthroughStylePatterns);
    }

    public static List<String> getFileExtensions() {
      return Arrays.asList(new String[]{"css-str"});
    }
  }
}


<|start_filename|>codeview/src/main/assets/training-set/csharp/MemberIdentifier.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using JSIL.Ast;
using Mono.Cecil;

namespace JSIL.Internal {
    public struct MemberIdentifier {
        public class Comparer : IEqualityComparer<MemberIdentifier> {
            public readonly ITypeInfoSource TypeInfo;

            public Comparer (ITypeInfoSource typeInfo) {
                TypeInfo = typeInfo;
            }

            public bool Equals (MemberIdentifier x, MemberIdentifier y) {
                /*
                if (x == null)
                    return x == y;
                 */

                return x.Equals(y, TypeInfo);
            }

            public int GetHashCode (MemberIdentifier obj) {
                return obj.GetHashCode();
            }
        }

        public enum MemberType : byte {
            Field = 0,
            Method = 1,
            Property = 2,
            Event = 3,
        }

        public readonly bool IsStatic;
        public readonly MemberType Type;
        public readonly string Name;
        public readonly TypeReference ReturnType;
        public readonly TypeReference[] ParameterTypes;
        public readonly int GenericArgumentCount;

        private readonly int HashCode;

        public static readonly TypeReference[] AnyParameterTypes = { };

        public static MemberIdentifier New (ITypeInfoSource ti, MemberReference mr) {
            MethodReference method;
            PropertyReference property;
            EventReference evt;
            FieldReference field;

            if ((method = mr as MethodReference) != null)
                return new MemberIdentifier(ti, method);
            else if ((field = mr as FieldReference) != null)
                return new MemberIdentifier(ti, field);
            else if ((property = mr as PropertyReference) != null)
                return new MemberIdentifier(ti, property);
            else if ((evt = mr as EventReference) != null)
                return new MemberIdentifier(ti, evt);
            else
                throw new NotImplementedException(String.Format(
                    "Unsupported member reference type: {0}",
                    mr
                ));
        }

        private MemberIdentifier (
            bool isStatic,
            MemberType type,
            string name,
            TypeReference returnType,
            TypeReference[] parameterTypes,
            int genericArgumentCount
        ) {
            IsStatic = isStatic;
            Type = type;
            Name = name;
            ReturnType = returnType;
            ParameterTypes = parameterTypes;
            GenericArgumentCount = genericArgumentCount;

            HashCode = Type.GetHashCode() ^ Name.GetHashCode();
        }

        public MemberIdentifier (ITypeInfoSource ti, MethodReference mr, string newName = null) {
            IsStatic = !mr.HasThis;
            Type = MemberType.Method;
            Name = newName ?? mr.Name;
            ReturnType = mr.ReturnType;
            ParameterTypes = GetParameterTypes(mr.Parameters);

            if (mr is GenericInstanceMethod)
                GenericArgumentCount = ((GenericInstanceMethod)mr).GenericArguments.Count;
            else if (mr.HasGenericParameters)
                GenericArgumentCount = mr.GenericParameters.Count;
            else
                GenericArgumentCount = 0;

            ti.CacheProxyNames(mr);

            HashCode = Type.GetHashCode() ^ Name.GetHashCode();
        }

        public MemberIdentifier (ITypeInfoSource ti, PropertyReference pr) {
            Type = MemberType.Property;
            Name = pr.Name;
            ReturnType = pr.PropertyType;
            GenericArgumentCount = 0;
            ParameterTypes = null;
            ti.CacheProxyNames(pr);

            var pd = pr.Resolve();
            if (pd != null) {
                IsStatic = !pd.HasThis;
                if (pd.GetMethod != null) {
                    ParameterTypes = GetParameterTypes(pd.GetMethod.Parameters);
                } else if (pd.SetMethod != null) {
                    ParameterTypes = GetParameterTypes(pd.SetMethod.Parameters)
                        .Take(pd.SetMethod.Parameters.Count - 1).ToArray();
                }
            } else {
                // FIXME
                IsStatic = false;
            }

            HashCode = Type.GetHashCode() ^ Name.GetHashCode();
        }

        public MemberIdentifier (ITypeInfoSource ti, FieldReference fr) {
            Type = MemberType.Field;
            Name = fr.Name;
            ReturnType = fr.FieldType;
            GenericArgumentCount = 0;
            ParameterTypes = null;
            ti.CacheProxyNames(fr);

            var resolved = fr.Resolve();
            if (resolved != null) {
                IsStatic = resolved.IsStatic;
            } else {
                // FIXME
                IsStatic = false;
            }

            HashCode = Type.GetHashCode() ^ Name.GetHashCode();
        }

        public MemberIdentifier (ITypeInfoSource ti, EventReference er) {
            Type = MemberType.Event;
            Name = er.Name;
            ReturnType = er.EventType;
            GenericArgumentCount = 0;
            ParameterTypes = null;
            ti.CacheProxyNames(er);

            var ed = er.Resolve();
            if (ed != null) {
                if (ed.AddMethod != null) {
                    IsStatic = ed.AddMethod.IsStatic;
                } else if (ed.RemoveMethod != null) {
                    IsStatic = ed.RemoveMethod.IsStatic;
                } else {
                    // FIXME
                    IsStatic = false;
                }
            } else {
                // FIXME
                IsStatic = false;
            }

            HashCode = Type.GetHashCode() ^ Name.GetHashCode();
        }

        static TypeReference[] GetParameterTypes (IList<ParameterDefinition> parameters) {
            if (parameters.Count == 0)
                return null;

            if (parameters.Count == 1) {
                var p = parameters[0];
                for (int c = p.CustomAttributes.Count, i = 0; i < c; i++) {
                    var ca = p.CustomAttributes[i];
                    if ((ca.AttributeType.Name == "ParamArrayAttribute") && (ca.AttributeType.Namespace == "System")) {
                        var t = JSExpression.DeReferenceType(parameters[0].ParameterType);
                        var at = t as ArrayType;
                        if ((at != null) && IsAnyType(at.ElementType))
                            return AnyParameterTypes;
                    }
                }
            }

            {
                int c = parameters.Count;
                var result = new TypeReference[c];
                for (int i = 0; i < c; i++) {
                    TypeReference parameterType = parameters[i].ParameterType, expandedParameterType;

                    if (TypeUtil.ExpandPositionalGenericParameters(parameterType, out expandedParameterType))
                        result[i] = expandedParameterType;
                    else
                        result[i] = parameterType;
                }

                return result;
            }
        }

        public static bool IsAnyType (TypeReference t) {
            if (t == null)
                return false;

            return (t.Name == "AnyType" && t.Namespace == "JSIL.Proxy");
        }

        public static bool TypesAreEqual (ITypeInfoSource typeInfo, TypeReference lhs, TypeReference rhs) {
            bool shallowMatch;

            if (lhs == rhs)
                return true;
            else if (lhs == null || rhs == null)
                return false;
            else if (TypeUtil.TypesAreTriviallyEqual(lhs, rhs, out shallowMatch))
                return true;

            var lhsReference = lhs as ByReferenceType;
            var rhsReference = rhs as ByReferenceType;

            if ((lhsReference != null) || (rhsReference != null)) {
                if ((lhsReference == null) || (rhsReference == null))
                    return false;

                return TypesAreEqual(typeInfo, lhsReference.ElementType, rhsReference.ElementType);
            }

            var lhsArray = lhs as ArrayType;
            var rhsArray = rhs as ArrayType;

            if ((lhsArray != null) || (rhsArray != null)) {
                if ((lhsArray == null) || (rhsArray == null))
                    return false;

                return TypesAreEqual(typeInfo, lhsArray.ElementType, rhsArray.ElementType);
            }

            var lhsGit = lhs as GenericInstanceType;
            var rhsGit = rhs as GenericInstanceType;

            if ((lhsGit != null) && (rhsGit != null)) {
                if (lhsGit.GenericArguments.Count != rhsGit.GenericArguments.Count)
                    return false;

                if (!TypesAreEqual(typeInfo, lhsGit.ElementType, rhsGit.ElementType))
                    return false;

                using (var eLeft = lhsGit.GenericArguments.GetEnumerator())
                using (var eRight = rhsGit.GenericArguments.GetEnumerator())
                    while (eLeft.MoveNext() && eRight.MoveNext()) {
                        if (!TypesAreEqual(typeInfo, eLeft.Current, eRight.Current))
                            return false;
                    }

                return true;
            }

            ArraySegment<string> proxyTargets;
            if (
                typeInfo.TryGetProxyNames(lhs, out proxyTargets) &&
                (proxyTargets.Array != null) &&
                proxyTargets.ToEnumerable().Contains(rhs.FullName)
            ) {
                return true;
            } else if (
                typeInfo.TryGetProxyNames(rhs, out proxyTargets) &&
                (proxyTargets.Array != null) &&
                proxyTargets.ToEnumerable().Contains(lhs.FullName)
            ) {
                return true;
            }

            if (IsAnyType(lhs) || IsAnyType(rhs))
                return true;

            return TypeUtil.TypesAreEqual(lhs, rhs);
        }

        public bool Equals (MemberIdentifier rhs, ITypeInfoSource typeInfo) {
            /*
            if (this == rhs)
                return true;
             */

            if (IsStatic != rhs.IsStatic)
                return false;

            if (Type != rhs.Type)
                return false;

            if (GenericArgumentCount != rhs.GenericArgumentCount)
                return false;

            if (!String.Equals(Name, rhs.Name))
                return false;

            if (!TypesAreEqual(typeInfo, ReturnType, rhs.ReturnType))
                return false;

            if ((ParameterTypes == AnyParameterTypes) || (rhs.ParameterTypes == AnyParameterTypes)) {
            } else if ((ParameterTypes == null) || (rhs.ParameterTypes == null)) {
                if (ParameterTypes != rhs.ParameterTypes)
                    return false;
            } else {
                if (ParameterTypes.Length != rhs.ParameterTypes.Length)
                    return false;

                for (int i = 0, c = ParameterTypes.Length; i < c; i++) {
                    if (!TypesAreEqual(typeInfo, ParameterTypes[i], rhs.ParameterTypes[i]))
                        return false;
                }
            }

            return true;
        }

        public MemberIdentifier Getter {
            get {
                if (Type != MemberType.Property)
                    throw new InvalidOperationException();

                return new MemberIdentifier(
                    IsStatic, MemberType.Method,
                    "get_" + Name,
                    ReturnType, ParameterTypes,
                    0
                );
            }
        }

        public MemberIdentifier Setter {
            get {
                if (Type != MemberType.Property)
                    throw new InvalidOperationException();

                TypeReference[] parameterTypes;
                if (ParameterTypes == null)
                    parameterTypes = new [] { ReturnType };
                else
                    parameterTypes = ParameterTypes.Concat(new [] { ReturnType }).ToArray();

                return new MemberIdentifier(
                    IsStatic, MemberType.Method,
                    "set_" + Name,
                    null, parameterTypes,
                    0
                );
            }
        }

        public override bool Equals (object obj) {
            throw new InvalidOperationException("Use MemberIdentifier.Equals(...) explicitly.");
        }

        public override int GetHashCode () {
            return HashCode;
        }

        public string ToString (string name) {
            if (GenericArgumentCount != 0)
                name = String.Format("{0}`{1}", name, GenericArgumentCount);

            if (ParameterTypes != null)
                return String.Format(
                    "{0} {1} ( {2} )", ReturnType, name,
                    String.Join(", ", (from p in ParameterTypes select p.ToString()).ToArray())
                );
            else
                return String.Format(
                    "{0} {1}", ReturnType, name
                );
        }

        public override string ToString () {
            return ToString(Name);
        }
    }

    public struct QualifiedMemberIdentifier {
        public class Comparer : IEqualityComparer<QualifiedMemberIdentifier> {
            public readonly ITypeInfoSource TypeInfo;

            public Comparer (ITypeInfoSource typeInfo) {
                TypeInfo = typeInfo;
            }

            public bool Equals (QualifiedMemberIdentifier x, QualifiedMemberIdentifier y) {
                /*
                if (x == null)
                    return x == y;
                 */

                return x.Equals(y, TypeInfo);
            }

            public int GetHashCode (QualifiedMemberIdentifier obj) {
                return obj.GetHashCode();
            }
        }

        public readonly TypeIdentifier Type;
        public readonly MemberIdentifier Member;

        public QualifiedMemberIdentifier (TypeIdentifier type, MemberIdentifier member) {
            Type = type;
            Member = member;
        }

        public override int GetHashCode () {
            return Type.GetHashCode() ^ Member.GetHashCode();
        }

        public bool Equals (MemberReference lhs, MemberReference rhs, ITypeInfoSource typeInfo) {
            if ((lhs == null) || (rhs == null))
                return lhs == rhs;

            if (lhs == rhs)
                return true;

            var declaringType = rhs.DeclaringType.Resolve();
            if (declaringType == null)
                return false;

            var rhsType = new TypeIdentifier(declaringType);

            if (!Type.Equals(rhsType))
                return false;

            var rhsMember = MemberIdentifier.New(typeInfo, rhs);

            return Member.Equals(rhsMember, typeInfo);
        }

        public bool Equals (QualifiedMemberIdentifier rhs, ITypeInfoSource typeInfo) {
            if (!Type.Equals(rhs.Type))
                return false;

            return Member.Equals(rhs.Member, typeInfo);
        }

        public override bool Equals (object obj) {
            throw new InvalidOperationException("Use QualifiedMemberIdentifier.Equals(...) explicitly.");
        }

        public override string ToString () {
            return String.Format("{0} {1}", Type, Member);
        }
    }
}


<|start_filename|>codeview/src/main/java/io/github/kbiakov/codeview/views/LineNoteView.kt<|end_filename|>
package io.github.kbiakov.codeview.views

import android.content.Context
import android.widget.TextView
import io.github.kbiakov.codeview.R
import io.github.kbiakov.codeview.dpToPx

/**
 * @class LineNoteView
 *
 * Note view for code line. Default footer view.
 *
 * @author <NAME>
 */
class LineNoteView(context: Context?) : TextView(context) {

    companion object Factory {
        /**
         * Simple factory method to create note view.
         *
         * @param context Context
         * @param text Note text
         * @param isFirst Is first footer view
         * @param bgColor Background color
         * @param textColor Text Color
         * @return Created line note view
         */
        fun create(context: Context, text: String, isFirst: Boolean, bgColor: Int, textColor: Int): LineNoteView {
            val noteView = LineNoteView(context)
            noteView.textSize = 12f
            noteView.text = text
            noteView.setTextColor(textColor)
            noteView.setBackgroundColor(bgColor)

            val dp8 = dpToPx(context, 8)

            val leftPadding = context.resources.getDimension(
                    R.dimen.line_num_width).toInt() + dpToPx(context, 14)

            val topPadding = if (isFirst) dp8 else 0

            noteView.setPadding(leftPadding, topPadding, dp8, dp8)

            return noteView
        }
    }
}


<|start_filename|>codeview/src/main/java/io/github/kbiakov/codeview/classifier/CodeProcessor.java<|end_filename|>
package io.github.kbiakov.codeview.classifier;

import android.content.Context;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * @class CodeProcessor
 *
 * Provides easy interface to code classifier. It response for train
 * code classifier & classifying code by code snippet. Both tasks
 * delegated to code classifier, but wrapped in extremely simple
 * interface to avoid possible errors.
 *
 * @author <NAME>
 */
public class CodeProcessor {

    private static final String TAG = "CodeClassifier";

    private static volatile CodeProcessor sInstance;
    private static Future<CodeProcessor> sTrainingTaskFuture;

    /**
     * Thread-safe code processor getter.
     *
     * If instance was not created or trained, it performs necessary operations.
     *
     * @param context Context
     * @return Code processor instance
     */
    public static CodeProcessor getInstance(Context context) {
        if (notInstanceAvailable()) {
            synchronized (CodeClassifier.class) {
                if (notInstanceAvailable()) {
                    sInstance = new CodeProcessor(context);
                }
            }
        }
        return sInstance;
    }

    /**
     * Private (and only one) constructor.
     *
     * Code processor creation instantiate code classifier training task.
     *
     * @param context Context
     */
    private CodeProcessor(Context context) {
        CodeClassifier.INSTANCE.train(context);
    }

    /**
     * Code processor should be created ones at start. But processor creation
     * is not guarantee that classifier is available. Not trained classifier
     * is not ready to use & must be trained soon as possible.
     *
     * The main cases why code processor is not available is:
     * 1) processor is not created yet & classifier not trained
     * 2) processor created, but occurs an error on classifier train
     * 3) processor created, classifier start train, but not finished
     *
     * (3rd case is ok, it's temporary unavailability & awaiting for training)
     *
     * In 3rd case, user awaiting for train accomplish to get code processor
     * and then take classifier to perform language classifying (see below).
     *
     * @return Flag indicates that classifier instance is not available.
     */
    private static boolean notInstanceAvailable() {
        if (sInstance == null) {
            if (!sTrainingTaskFuture.isDone()) {
                try {
                    sInstance = sTrainingTaskFuture.get();
                    return false;
                } catch (InterruptedException | ExecutionException e) {
                    e.printStackTrace();
                    return true;
                }
            } else {
                return true;
            }
        }
        return false;
    }

    /**
     * If training task future is exists, then classifier was started
     * to train or already trained & classifier is ready to use.
     *
     * @return If classifier was trained.
     */
    public boolean isTrained() {
        return sTrainingTaskFuture != null;
    }

    /**
     * Start point for apps that use code classifying. Called ones at app start.
     * It creates training task for code classifier.
     *
     * @param context Context
     */
    public static void init(Context context) {
        if (sInstance == null) {
            final ExecutorService service = Executors.newSingleThreadExecutor();
            sTrainingTaskFuture = service.submit(new TrainingTask(context));
        } else {
            throw new IllegalStateException("Attempt to train code classifier twice.\n" +
                    "It should be initialized once at start to make train asynchronously.");
        }
    }

    /**
     * Creates code snippet language classifying task.
     *
     * @param snippet Code snippet to classify.
     * @return Classified language wrapped in Future.
     */
    public Future<String> classify(String snippet) {
        final ExecutorService service = Executors.newSingleThreadExecutor();
        return service.submit(new ClassifyingTask(snippet));
    }

    /**
     * @class TrainingTask
     *
     * Classifier training task.
     *
     * @author <NAME>
     */
    private static class TrainingTask implements Callable<CodeProcessor> {
        private Context context;

        public TrainingTask(Context context) {
            this.context = context;
        }

        @Override
        public CodeProcessor call() {
            return new CodeProcessor(context);
        }
    }

    /**
     * @class ClassifyingTask
     *
     * Language classifying task for presented code snippet.
     *
     * @author <NAME>
     */
    private static class ClassifyingTask implements Callable<String> {
        private String snippet;

        public ClassifyingTask(String snippet) {
            this.snippet = snippet;
        }

        @Override
        public String call() {
            return CodeClassifier.INSTANCE.classify(snippet);
        }
    }
}


<|start_filename|>codeview/src/main/assets/training-set/c/c.c<|end_filename|>

//
// mon.c
//
// Copyright (c) 2012 <NAME> <<EMAIL>>
//

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <fcntl.h>
#include <signal.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include "commander.h"
#include "ms.h"

/*
 * Program version.
 */

#define VERSION "1.1.1"

/*
 * Log prefix.
 */

static const char *prefix = NULL;

/*
 * Monitor.
 */

typedef struct {
	const char *pidfile;
	const char *mon_pidfile;
	const char *logfile;
	const char *on_error;
	const char *on_restart;
	int64_t last_restart_at;
	int64_t clock;
	int daemon;
	int sleepsec;
	int max_attempts;
	int attempts;
} monitor_t;

/*
 * Logger.
 */

#define log(fmt, args...) \
  do { \
    if (prefix) { \
      printf("mon : %s : " fmt "\n", prefix, ##args); \
	    } else { \
      printf("mon : " fmt "\n", ##args); \
	    } \
    } while(0)

/*
 * Output error `msg`.
 */

void
error(char *msg) {
	fprintf(stderr, "Error: %s\n", msg);
	exit(1);
}

/*
 * Check if process of `pid` is alive.
 */

int
alive(pid_t pid) {
	return 0 == kill(pid, 0);
}

/*
 * Graceful exit, signal process group.
 */

void
graceful_exit(int sig) {
	pid_t pid = getpid();
	log("shutting down");
	log("kill(-%d, %d)", pid, sig);
	kill(-pid, sig);
	log("bye :)");
	exit(0);
}

/*
 * Return a timestamp in milliseconds.
 */

int64_t
timestamp() {
	struct timeval tv;
	int ret = gettimeofday(&tv, NULL);
	if (-1 == ret) return -1;
	return (int64_t) ((int64_t) tv.tv_sec * 1000 + (int64_t) tv.tv_usec / 1000);
}

/*
 * Write `pid` to `file`.
 */

void
write_pidfile(const char *file, pid_t pid) {
	char buf[32] = { 0 };
	snprintf(buf, 32, "%d", pid);
	int fd = open(file, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
	if (fd < 0) perror("open()");
	write(fd, buf, 32);
	close(fd);
}

/*
 * Output status of `pidfile`.
 */

void
show_status_of(const char *pidfile) {
	off_t size;
	struct stat s;

	// stat
	if (stat(pidfile, &s) < 0) {
		perror("stat()");
		exit(1);
	}

	size = s.st_size;

	// opens
	int fd = open(pidfile, O_RDONLY, 0);
	if (fd < 0) {
		perror("open()");
		exit(1);
	}

	// read
	char buf[size];
	if (size != read(fd, buf, size)) {
		perror("read()");
		exit(1);
	}

	// uptime
	time_t modified = s.st_mtime;

	struct timeval t;
	gettimeofday(&t, NULL);
	time_t now = t.tv_sec;
	time_t secs = now - modified;

	// status
	pid_t pid = atoi(buf);

	if (alive(pid)) {
		char *str = milliseconds_to_long_string(secs * 1000);
		printf("\e[90m%d\e[0m : \e[32malive\e[0m : uptime %s\e[m\n", pid, str);
		free(str);
	}
	else {
		printf("\e[90m%d\e[0m : \e[31mdead\e[0m\n", pid);
	}

	close(fd);
}

/*
 * Redirect stdio to `file`.
 */

void
redirect_stdio_to(const char *file) {
	int logfd = open(file, O_WRONLY | O_CREAT | O_APPEND, 0755);
	int nullfd = open("/dev/null", O_RDONLY, 0);

	if (-1 == logfd) {
		perror("open()");
		exit(1);
	}

	if (-1 == nullfd) {
		perror("open()");
		exit(1);
	}

	dup2(nullfd, 0);
	dup2(logfd, 1);
	dup2(logfd, 2);
}

/*
 * Daemonize the program.
 */

void
daemonize() {
	if (fork()) exit(0);

	if (setsid() < 0) {
		perror("setsid()");
		exit(1);
	}
}

/*
 * Invoke the --on-restart command.
 */

void
exec_restart_command(monitor_t *monitor) {
	log("on restart `%s`", monitor->on_restart);
	int status = system(monitor->on_restart);
	if (status) log("exit(%d)", status);
}

/*
 * Invoke the --on-error command.
 */

void
exec_error_command(monitor_t *monitor) {
	log("on error `%s`", monitor->on_error);
	int status = system(monitor->on_error);
	if (status) log("exit(%d)", status);
}

/*
 * Return the ms since the last restart.
 */

int64_t
ms_since_last_restart(monitor_t *monitor) {
	if (0 == monitor->last_restart_at) return 0;
	int64_t now = timestamp();
	return now - monitor->last_restart_at;
}

/*
 * Check if the maximum restarts within 60 seconds
 * have been exceeded and return 1, 0 otherwise.
 */

int
attempts_exceeded(monitor_t *monitor, int64_t ms) {
	monitor->attempts++;
	monitor->clock -= ms;

	// reset
	if (monitor->clock <= 0) {
		monitor->clock = 60000;
		monitor->attempts = 0;
		return 0;
	}

	// all good
	if (monitor->attempts < monitor->max_attempts) return 0;

	return 1;
}

/*
 * Monitor the given `cmd`.
 */

void
start(const char *cmd, monitor_t *monitor) {
exec: {
	pid_t pid = fork();
	int status;

	switch (pid) {
	case -1:
		perror("fork()");
		exit(1);
	case 0:
		signal(SIGTERM, SIG_DFL);
		signal(SIGQUIT, SIG_DFL);
		log("sh -c \"%s\"", cmd);
		execl("/bin/sh", "sh", "-c", cmd, 0);
		perror("execl()");
		exit(1);
	default:
		log("child %d", pid);

		// write pidfile
		if (monitor->pidfile) {
			log("write pid to %s", monitor->pidfile);
			write_pidfile(monitor->pidfile, pid);
		}

		// wait for exit
		waitpid(pid, &status, 0);

		// signalled
		if (WIFSIGNALED(status)) {
			log("signal(%s)", strsignal(WTERMSIG(status)));
			log("sleep(%d)", monitor->sleepsec);
			sleep(monitor->sleepsec);
			goto error;
		}

		// check status
		if (WEXITSTATUS(status)) {
			log("exit(%d)", WEXITSTATUS(status));
			log("sleep(%d)", monitor->sleepsec);
			sleep(monitor->sleepsec);
			goto error;
		}

		// restart
	error: {
		if (monitor->on_restart) exec_restart_command(monitor);
		int64_t ms = ms_since_last_restart(monitor);
		monitor->last_restart_at = timestamp();
		log("last restart %s ago", milliseconds_to_long_string(ms));
		log("%d attempts remaining", monitor->max_attempts - monitor->attempts);

		if (attempts_exceeded(monitor, ms)) {
			char *time = milliseconds_to_long_string(60000 - monitor->clock);
			log("%d restarts within %s, bailing", monitor->max_attempts, time);
			exec_error_command(monitor);
			log("bye :)");
			exit(2);
		}

		goto exec;
	}
	}
}
}

/*
 * --log <path>
 */

static void
on_log(command_t *self) {
	monitor_t *monitor = (monitor_t *) self->data;
	monitor->logfile = self->arg;
}

/*
 * --sleep <sec>
 */

static void
on_sleep(command_t *self) {
	monitor_t *monitor = (monitor_t *) self->data;
	monitor->sleepsec = atoi(self->arg);
}

/*
 * --daemonize
 */

static void
on_daemonize(command_t *self) {
	monitor_t *monitor = (monitor_t *) self->data;
	monitor->daemon = 1;
}

/*
 * --pidfile <path>
 */

static void
on_pidfile(command_t *self) {
	monitor_t *monitor = (monitor_t *) self->data;
	monitor->pidfile = self->arg;
}

/*
 * --mon-pidfile <path>
 */

static void
on_mon_pidfile(command_t *self) {
	monitor_t *monitor = (monitor_t *) self->data;
	monitor->mon_pidfile = self->arg;
}

/*
 * --status
 */

static void
on_status(command_t *self) {
	monitor_t *monitor = (monitor_t *) self->data;
	if (!monitor->pidfile) error("--pidfile required");
	show_status_of(monitor->pidfile);
	exit(0);
}

/*
 * --prefix
 */

static void
on_prefix(command_t *self) {
	monitor_t *monitor = (monitor_t *) self->data;
	prefix = self->arg;
}

/*
 * --on-restart <cmd>
 */

static void
on_restart(command_t *self) {
	monitor_t *monitor = (monitor_t *) self->data;
	monitor->on_restart = self->arg;
}

/*
 * --on-error <cmd>
 */

static void
on_error(command_t *self) {
	monitor_t *monitor = (monitor_t *) self->data;
	monitor->on_error = self->arg;
}

/*
 * --attempts <n>
 */

static void
on_attempts(command_t *self) {
	monitor_t *monitor = (monitor_t *) self->data;
	monitor->max_attempts = atoi(self->arg);
}

/*
 * [options] <cmd>
 */

int
main(int argc, char **argv){
	monitor_t monitor;
	monitor.pidfile = NULL;
	monitor.mon_pidfile = NULL;
	monitor.on_restart = NULL;
	monitor.on_error = NULL;
	monitor.logfile = "mon.log";
	monitor.daemon = 0;
	monitor.sleepsec = 1;
	monitor.max_attempts = 10;
	monitor.attempts = 0;
	monitor.last_restart_at = 0;
	monitor.clock = 60000;

	command_t program;
	command_init(&program, "mon", VERSION);
	program.data = &monitor;
	program.usage = "[options] <command>";
	command_option(&program, "-l", "--log <path>", "specify logfile [mon.log]", on_log);
	command_option(&program, "-s", "--sleep <sec>", "sleep seconds before re-executing [1]", on_sleep);
	command_option(&program, "-S", "--status", "check status of --pidfile", on_status);
	command_option(&program, "-p", "--pidfile <path>", "write pid to <path>", on_pidfile);
	command_option(&program, "-m", "--mon-pidfile <path>", "write mon(1) pid to <path>", on_mon_pidfile);
	command_option(&program, "-P", "--prefix <str>", "add a log prefix", on_prefix);
	command_option(&program, "-d", "--daemonize", "daemonize the program", on_daemonize);
	command_option(&program, "-a", "--attempts <n>", "retry attempts within 60 seconds [10]", on_attempts);
	command_option(&program, "-R", "--on-restart <cmd>", "execute <cmd> on restarts", on_restart);
	command_option(&program, "-E", "--on-error <cmd>", "execute <cmd> on error", on_error);
	command_parse(&program, argc, argv);

	// command required
	if (!program.argc) error("<cmd> required");
	const char *cmd = program.argv[0];

	// signals
	signal(SIGTERM, graceful_exit);
	signal(SIGQUIT, graceful_exit);

	// daemonize
	if (monitor.daemon) {
		daemonize();
		redirect_stdio_to(monitor.logfile);
	}

	// write mon pidfile
	if (monitor.mon_pidfile) {
		log("write mon pid to %s", monitor.mon_pidfile);
		write_pidfile(monitor.mon_pidfile, getpid());
	}

	start(cmd, &monitor);

	return 0;
}



//
// term.c
//
// Copyright (c) 2012 <NAME> <<EMAIL>>
//

#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include "term.h"

/*
 * X pos.
 */

static int _x = 0;

/*
 * Y pos.
 */

static int _y = 0;

/*
 * Move to `(x, y)`.
 */

void
term_move_to(int x, int y) {
	_x = x;
	_y = y;
	printf("\e[%d;%d;f", y, x);
}

/*
 * Move by `(x, y)`.
 */

void
term_move_by(int x, int y) {
	term_move_to(_x + x, _y + y);
}

/*
 * Set `w` and `h` to the terminal dimensions.
 */

int
term_size(int *w, int *h) {
	struct winsize ws;
	int ret = ioctl(0, TIOCGWINSZ, &ws);
	if (ret < 0) return ret;
	*w = ws.ws_col;
	*h = ws.ws_row;
}

/*
 * Return the erase code for `name` or -1.
 */

const char *
term_erase_from_name(const char *name) {
	if (!strcmp("end", name)) return "K";
	if (!strcmp("start", name)) return "1K";
	if (!strcmp("line", name)) return "2K";
	if (!strcmp("up", name)) return "1J";
	if (!strcmp("down", name)) return "J";
	if (!strcmp("screen", name)) return "1J";
	return NULL;
}

/*
 * Erase with `name`:
 *
 *   - "end"
 *   - "start"
 *   - "line"
 *   - "up"
 *   - "down"
 *   - "screen"
 *
 */

int
term_erase(const char *name) {
	const char *s = term_erase_from_name(name);
	if (!s) return -1;
	printf("\e[%s", s);
	return 0;
}

/*
 * Return the color code for `name` or -1.
 */

int
term_color_from_name(const char *name) {
	if (!strcmp("black", name)) return 0;
	if (!strcmp("red", name)) return 1;
	if (!strcmp("green", name)) return 2;
	if (!strcmp("yellow", name)) return 3;
	if (!strcmp("blue", name)) return 4;
	if (!strcmp("magenta", name)) return 5;
	if (!strcmp("cyan", name)) return 6;
	if (!strcmp("white", name)) return 7;
	return -1;
}

/*
 * Set color by `name` or return -1.
 */

int
term_color(const char *name) {
	// TODO: refactor term_color_from_name()
	if (!strcmp("gray", name) || !strcmp("grey", name)) {
		printf("\e[90m");
		return 0;
	}

	int n = term_color_from_name(name);
	if (-1 == n) return n;
	printf("\e[3%dm", n);
	return 0;
}

/*
 * Set background color by `name` or return -1.
 */

int
term_background(const char *name) {
	int n = term_color_from_name(name);
	if (-1 == n) return n;
	printf("\e[4%dm", n);
	return 0;
}

//
// ms.c
//
// Copyright (c) 2012 <NAME> <<EMAIL>>
//

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "ms.h"

// microseconds

#define US_SEC 1000000
#define US_MIN 60 * US_SEC
#define US_HOUR 60 * US_MIN
#define US_DAY 24 * US_HOUR
#define US_WEEK 7 * US_HOUR
#define US_YEAR 52 * US_WEEK

// milliseconds

#define MS_SEC 1000
#define MS_MIN 60000
#define MS_HOUR 3600000
#define MS_DAY 86400000
#define MS_WEEK 604800000
#define MS_YEAR 31557600000

/*
 * Convert the given `str` representation to microseconds,
 * for example "10ms", "5s", "2m", "1h" etc.
 */

long long
string_to_microseconds(const char *str) {
	size_t len = strlen(str);
	long long val = strtoll(str, NULL, 10);
	if (!val) return -1;
	switch (str[len - 1]) {
	case 's': return  'm' == str[len - 2] ? val * 1000 : val * US_SEC;
	case 'm': return val * US_MIN;
	case 'h': return val * US_HOUR;
	case 'd': return val * US_DAY;
	case 'w': return val * US_WEEK;
	case 'y': return val * US_YEAR;
	default:  return val;
	}
}

/*
 * Convert the given `str` representation to milliseconds,
 * for example "10ms", "5s", "2m", "1h" etc.
 */

long long
string_to_milliseconds(const char *str) {
	size_t len = strlen(str);
	long long val = strtoll(str, NULL, 10);
	if (!val) return -1;
	switch (str[len - 1]) {
	case 's': return  'm' == str[len - 2] ? val : val * 1000;
	case 'm': return val * MS_MIN;
	case 'h': return val * MS_HOUR;
	case 'd': return val * MS_DAY;
	case 'w': return val * MS_WEEK;
	case 'y': return val * MS_YEAR;
	default:  return val;
	}
}

/*
 * Convert the given `str` representation to seconds.
 */

long long
string_to_seconds(const char *str) {
	long long ret = string_to_milliseconds(str);
	if (-1 == ret) return ret;
	return ret / 1000;
}

/*
 * Convert the given `ms` to a string. This
 * value must be `free()`d by the developer.
 */

char *
milliseconds_to_string(long long ms) {
	char *str = malloc(MS_MAX);
	if (!str) return NULL;
	long div = 1;
	char *fmt;

	if (ms < MS_SEC) fmt = "%lldms";
	else if (ms < MS_MIN) { fmt = "%llds"; div = MS_SEC; }
	else if (ms < MS_HOUR) { fmt = "%lldm"; div = MS_MIN; }
	else if (ms < MS_DAY) { fmt = "%lldh"; div = MS_HOUR; }
	else if (ms < MS_WEEK) { fmt = "%lldd"; div = MS_DAY; }
	else if (ms < MS_YEAR) { fmt = "%lldw"; div = MS_WEEK; }
	else { fmt = "%lldy"; div = MS_YEAR; }
	snprintf(str, MS_MAX, fmt, ms / div);

	return str;
}

/*
 * Convert the given `ms` to a long string. This
 * value must be `free()`d by the developer.
 */

char *
milliseconds_to_long_string(long long ms) {
	long div;
	char *name;

	char *str = malloc(MS_MAX);
	if (!str) return NULL;

	if (ms < MS_SEC) {
		sprintf(str, "less than one second");
		return str;
	}

	if (ms < MS_MIN) { name = "second"; div = MS_SEC; }
	else if (ms < MS_HOUR) { name = "minute"; div = MS_MIN; }
	else if (ms < MS_DAY) { name = "hour"; div = MS_HOUR; }
	else if (ms < MS_WEEK) { name = "day"; div = MS_DAY; }
	else if (ms < MS_YEAR) { name = "week"; div = MS_WEEK; }
	else { name = "year"; div = MS_YEAR; }

	long long val = ms / div;
	char *fmt = 1 == val
		? "%lld %s"
		: "%lld %ss";

	snprintf(str, MS_MAX, fmt, val, name);
	return str;
}

// tests

#ifdef TEST_MS

#include <assert.h>

void
equal(char *a, char *b) {
	if (strcmp(a, b)) {
		printf("expected: %s\n", a);
		printf("actual: %s\n", b);
		exit(1);
	}
}

void
test_string_to_microseconds() {
	assert(string_to_microseconds("") == -1);
	assert(string_to_microseconds("s") == -1);
	assert(string_to_microseconds("hey") == -1);
	assert(string_to_microseconds("5000") == 5000);
	assert(string_to_microseconds("1ms") == 1000);
	assert(string_to_microseconds("5ms") == 5000);
	assert(string_to_microseconds("1s") == 1000000);
	assert(string_to_microseconds("5s") == 5000000);
	assert(string_to_microseconds("1m") == 60000000);
	assert(string_to_microseconds("1h") == 3600000000);
	assert(string_to_microseconds("2d") == 2 * 24 * 3600000000);
}

void
test_string_to_milliseconds() {
	assert(string_to_milliseconds("") == -1);
	assert(string_to_milliseconds("s") == -1);
	assert(string_to_milliseconds("hey") == -1);
	assert(string_to_milliseconds("5000") == 5000);
	assert(string_to_milliseconds("1ms") == 1);
	assert(string_to_milliseconds("5ms") == 5);
	assert(string_to_milliseconds("1s") == 1000);
	assert(string_to_milliseconds("5s") == 5000);
	assert(string_to_milliseconds("1m") == 60 * 1000);
	assert(string_to_milliseconds("1h") == 60 * 60 * 1000);
	assert(string_to_milliseconds("1d") == 24 * 60 * 60 * 1000);
}

void
test_string_to_seconds() {
	assert(string_to_seconds("") == -1);
	assert(string_to_seconds("s") == -1);
	assert(string_to_seconds("hey") == -1);
	assert(string_to_seconds("5000") == 5);
	assert(string_to_seconds("1ms") == 0);
	assert(string_to_seconds("5ms") == 0);
	assert(string_to_seconds("1s") == 1);
	assert(string_to_seconds("5s") == 5);
	assert(string_to_seconds("1m") == 60);
	assert(string_to_seconds("1h") == 60 * 60);
	assert(string_to_seconds("1d") == 24 * 60 * 60);
}

void
test_milliseconds_to_string() {
	equal("500ms", milliseconds_to_string(500));
	equal("5s", milliseconds_to_string(5000));
	equal("2s", milliseconds_to_string(2500));
	equal("1m", milliseconds_to_string(MS_MIN));
	equal("5m", milliseconds_to_string(5 * MS_MIN));
	equal("1h", milliseconds_to_string(MS_HOUR));
	equal("2d", milliseconds_to_string(2 * MS_DAY));
	equal("2w", milliseconds_to_string(15 * MS_DAY));
	equal("3y", milliseconds_to_string(3 * MS_YEAR));
}

void
test_milliseconds_to_long_string() {
	equal("less than one second", milliseconds_to_long_string(500));
	equal("5 seconds", milliseconds_to_long_string(5000));
	equal("2 seconds", milliseconds_to_long_string(2500));
	equal("1 minute", milliseconds_to_long_string(MS_MIN));
	equal("5 minutes", milliseconds_to_long_string(5 * MS_MIN));
	equal("1 hour", milliseconds_to_long_string(MS_HOUR));
	equal("2 days", milliseconds_to_long_string(2 * MS_DAY));
	equal("2 weeks", milliseconds_to_long_string(15 * MS_DAY));
	equal("1 year", milliseconds_to_long_string(MS_YEAR));
	equal("3 years", milliseconds_to_long_string(3 * MS_YEAR));
}

int
main(){
	test_string_to_microseconds();
	test_string_to_milliseconds();
	test_string_to_seconds();
	test_milliseconds_to_string();
	test_milliseconds_to_long_string();
	printf("\n  \e[32m\u2713 \e[90mok\e[0m\n\n");
	return 0;
}

#endif


<|start_filename|>codeview/src/main/assets/training-set/c++/c++.cpp<|end_filename|>
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.


#include "node.h"
#include "node_buffer.h"

#include "v8.h"
#include "v8-profiler.h"

#include <assert.h>
#include <stdlib.h> // malloc, free
#include <string.h> // memcpy

#ifdef __POSIX__
# include <arpa/inet.h> // htons, htonl
#endif

#define MIN(a,b) ((a) < (b) ? (a) : (b))

#define BUFFER_CLASS_ID (0xBABE)

namespace node {

using namespace v8;

#define SLICE_ARGS(start_arg, end_arg)                               \
  if (!start_arg->IsInt32() || !end_arg->IsInt32()) {                \
    return ThrowException(Exception::TypeError(                      \
          String::New("Bad argument.")));                            \
  }                                                                  \
  int32_t start = start_arg->Int32Value();                           \
  int32_t end = end_arg->Int32Value();                               \
  if (start < 0 || end < 0) {                                        \
    return ThrowException(Exception::TypeError(                      \
          String::New("Bad argument.")));                            \
  }                                                                  \
  if (!(start <= end)) {                                             \
    return ThrowException(Exception::Error(                          \
          String::New("Must have start <= end")));                   \
  }                                                                  \
  if ((size_t)end > parent->length_) {                               \
    return ThrowException(Exception::Error(                          \
          String::New("end cannot be longer than parent.length")));  \
  }


static Persistent<String> length_symbol;
static Persistent<String> chars_written_sym;
static Persistent<String> write_sym;
Persistent<FunctionTemplate> Buffer::constructor_template;


static inline size_t base64_decoded_size(const char *src, size_t size) {
  const char *const end = src + size;
  const int remainder = size % 4;

  size = (size / 4) * 3;
  if (remainder) {
    if (size == 0 && remainder == 1) {
      // special case: 1-byte input cannot be decoded
      size = 0;
    } else {
      // non-padded input, add 1 or 2 extra bytes
      size += 1 + (remainder == 3);
    }
  }

  // check for trailing padding (1 or 2 bytes)
  if (size > 0) {
    if (end[-1] == '=') size--;
    if (end[-2] == '=') size--;
  }

  return size;
}


static size_t ByteLength (Handle<String> string, enum encoding enc) {
  HandleScope scope;

  if (enc == UTF8) {
    return string->Utf8Length();
  } else if (enc == BASE64) {
    String::Utf8Value v(string);
    return base64_decoded_size(*v, v.length());
  } else if (enc == UCS2) {
    return string->Length() * 2;
  } else if (enc == HEX) {
    return string->Length() / 2;
  } else {
    return string->Length();
  }
}


Handle<Object> Buffer::New(Handle<String> string) {
  HandleScope scope;

  // get Buffer from global scope.
  Local<Object> global = v8::Context::GetCurrent()->Global();
  Local<Value> bv = global->Get(String::NewSymbol("Buffer"));
  assert(bv->IsFunction());
  Local<Function> b = Local<Function>::Cast(bv);

  Local<Value> argv[1] = { Local<Value>::New(string) };
  Local<Object> instance = b->NewInstance(1, argv);

  return scope.Close(instance);
}


Buffer* Buffer::New(size_t length) {
  HandleScope scope;

  Local<Value> arg = Integer::NewFromUnsigned(length);
  Local<Object> b = constructor_template->GetFunction()->NewInstance(1, &arg);
  if (b.IsEmpty()) return NULL;

  return ObjectWrap::Unwrap<Buffer>(b);
}


Buffer* Buffer::New(char* data, size_t length) {
  HandleScope scope;

  Local<Value> arg = Integer::NewFromUnsigned(0);
  Local<Object> obj = constructor_template->GetFunction()->NewInstance(1, &arg);

  Buffer *buffer = ObjectWrap::Unwrap<Buffer>(obj);
  buffer->Replace(data, length, NULL, NULL);

  return buffer;
}


Buffer* Buffer::New(char *data, size_t length,
                    free_callback callback, void *hint) {
  HandleScope scope;

  Local<Value> arg = Integer::NewFromUnsigned(0);
  Local<Object> obj = constructor_template->GetFunction()->NewInstance(1, &arg);

  Buffer *buffer = ObjectWrap::Unwrap<Buffer>(obj);
  buffer->Replace(data, length, callback, hint);

  return buffer;
}


Handle<Value> Buffer::New(const Arguments &args) {
  if (!args.IsConstructCall()) {
    return FromConstructorTemplate(constructor_template, args);
  }

  HandleScope scope;

  if (!args[0]->IsUint32()) return ThrowTypeError("Bad argument");

  size_t length = args[0]->Uint32Value();
  if (length > Buffer::kMaxLength) {
    return ThrowRangeError("length > kMaxLength");
  }
  new Buffer(args.This(), length);

  return args.This();
}


Buffer::Buffer(Handle<Object> wrapper, size_t length) : ObjectWrap() {
  Wrap(wrapper);

  length_ = 0;
  callback_ = NULL;
  handle_.SetWrapperClassId(BUFFER_CLASS_ID);

  Replace(NULL, length, NULL, NULL);
}


Buffer::~Buffer() {
  Replace(NULL, 0, NULL, NULL);
}


void Buffer::Replace(char *data, size_t length,
                     free_callback callback, void *hint) {
  HandleScope scope;

  if (callback_) {
    callback_(data_, callback_hint_);
  } else if (length_) {
    delete [] data_;
    V8::AdjustAmountOfExternalAllocatedMemory(
        -static_cast<intptr_t>(sizeof(Buffer) + length_));
  }

  length_ = length;
  callback_ = callback;
  callback_hint_ = hint;

  if (callback_) {
    data_ = data;
  } else if (length_) {
    data_ = new char[length_];
    if (data)
      memcpy(data_, data, length_);
    V8::AdjustAmountOfExternalAllocatedMemory(sizeof(Buffer) + length_);
  } else {
    data_ = NULL;
  }

  handle_->SetIndexedPropertiesToExternalArrayData(data_,
                                                   kExternalUnsignedByteArray,
                                                   length_);
  handle_->Set(length_symbol, Integer::NewFromUnsigned(length_));
}


Handle<Value> Buffer::BinarySlice(const Arguments &args) {
  HandleScope scope;
  Buffer *parent = ObjectWrap::Unwrap<Buffer>(args.This());
  SLICE_ARGS(args[0], args[1])

  char *data = parent->data_ + start;
  //Local<String> string = String::New(data, end - start);

  Local<Value> b =  Encode(data, end - start, BINARY);

  return scope.Close(b);
}


Handle<Value> Buffer::AsciiSlice(const Arguments &args) {
  HandleScope scope;
  Buffer *parent = ObjectWrap::Unwrap<Buffer>(args.This());
  SLICE_ARGS(args[0], args[1])

  char* data = parent->data_ + start;
  Local<String> string = String::New(data, end - start);

  return scope.Close(string);
}


Handle<Value> Buffer::Utf8Slice(const Arguments &args) {
  HandleScope scope;
  Buffer *parent = ObjectWrap::Unwrap<Buffer>(args.This());
  SLICE_ARGS(args[0], args[1])
  char *data = parent->data_ + start;
  Local<String> string = String::New(data, end - start);
  return scope.Close(string);
}

Handle<Value> Buffer::Ucs2Slice(const Arguments &args) {
  HandleScope scope;
  Buffer *parent = ObjectWrap::Unwrap<Buffer>(args.This());
  SLICE_ARGS(args[0], args[1])
  uint16_t *data = (uint16_t*)(parent->data_ + start);
  Local<String> string = String::New(data, (end - start) / 2);
  return scope.Close(string);
}

static const char *base64_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                                  "abcdefghijklmnopqrstuvwxyz"
                                  "0123456789+/";

// supports regular and URL-safe base64
static const int unbase64_table[] =
  {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-2,-1,-1
  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
  ,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,62,-1,63
  ,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1
  ,-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14
  ,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,63
  ,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40
  ,41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1
  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
  ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
  };
#define unbase64(x) unbase64_table[(uint8_t)(x)]


Handle<Value> Buffer::Base64Slice(const Arguments &args) {
  HandleScope scope;
  Buffer *parent = ObjectWrap::Unwrap<Buffer>(args.This());
  SLICE_ARGS(args[0], args[1])

  int n = end - start;
  int out_len = (n + 2 - ((n + 2) % 3)) / 3 * 4;
  char *out = new char[out_len];

  uint8_t bitbuf[3];
  int i = start; // data() index
  int j = 0; // out index
  char c;
  bool b1_oob, b2_oob;

  while (i < end) {
    bitbuf[0] = parent->data_[i++];

    if (i < end) {
      bitbuf[1] = parent->data_[i];
      b1_oob = false;
    }  else {
      bitbuf[1] = 0;
      b1_oob = true;
    }
    i++;

    if (i < end) {
      bitbuf[2] = parent->data_[i];
      b2_oob = false;
    }  else {
      bitbuf[2] = 0;
      b2_oob = true;
    }
    i++;


    c = bitbuf[0] >> 2;
    assert(c < 64);
    out[j++] = base64_table[(int)c];
    assert(j < out_len);

    c = ((bitbuf[0] & 0x03) << 4) | (bitbuf[1] >> 4);
    assert(c < 64);
    out[j++] = base64_table[(int)c];
    assert(j < out_len);

    if (b1_oob) {
      out[j++] = '=';
    } else {
      c = ((bitbuf[1] & 0x0F) << 2) | (bitbuf[2] >> 6);
      assert(c < 64);
      out[j++] = base64_table[(int)c];
    }
    assert(j < out_len);

    if (b2_oob) {
      out[j++] = '=';
    } else {
      c = bitbuf[2] & 0x3F;
      assert(c < 64);
      out[j++]  = base64_table[(int)c];
    }
    assert(j <= out_len);
  }

  Local<String> string = String::New(out, out_len);
  delete [] out;
  return scope.Close(string);
}


// buffer.fill(value, start, end);
Handle<Value> Buffer::Fill(const Arguments &args) {
  HandleScope scope;

  if (!args[0]->IsInt32()) {
    return ThrowException(Exception::Error(String::New(
            "value is not a number")));
  }
  int value = (char)args[0]->Int32Value();

  Buffer *parent = ObjectWrap::Unwrap<Buffer>(args.This());
  SLICE_ARGS(args[1], args[2])

  memset( (void*)(parent->data_ + start),
          value,
          end - start);

  return Undefined();
}


// var bytesCopied = buffer.copy(target, targetStart, sourceStart, sourceEnd);
Handle<Value> Buffer::Copy(const Arguments &args) {
  HandleScope scope;

  Buffer *source = ObjectWrap::Unwrap<Buffer>(args.This());

  if (!Buffer::HasInstance(args[0])) {
    return ThrowException(Exception::TypeError(String::New(
            "First arg should be a Buffer")));
  }

  Local<Object> target = args[0]->ToObject();
  char* target_data = Buffer::Data(target);
  size_t target_length = Buffer::Length(target);
  size_t target_start = args[1]->Uint32Value();
  size_t source_start = args[2]->Uint32Value();
  size_t source_end = args[3]->IsUint32() ? args[3]->Uint32Value()
                                          : source->length_;

  if (source_end < source_start) {
    return ThrowException(Exception::Error(String::New(
            "sourceEnd < sourceStart")));
  }

  // Copy 0 bytes; we're done
  if (source_end == source_start) {
    return scope.Close(Integer::New(0));
  }

  if (target_start >= target_length) {
    return ThrowException(Exception::Error(String::New(
            "targetStart out of bounds")));
  }

  if (source_start >= source->length_) {
    return ThrowException(Exception::Error(String::New(
            "sourceStart out of bounds")));
  }

  if (source_end > source->length_) {
    return ThrowException(Exception::Error(String::New(
            "sourceEnd out of bounds")));
  }

  size_t to_copy = MIN(MIN(source_end - source_start,
                           target_length - target_start),
                           source->length_ - source_start);

  // need to use slightly slower memmove is the ranges might overlap
  memmove((void *)(target_data + target_start),
          (const void*)(source->data_ + source_start),
          to_copy);

  return scope.Close(Integer::New(to_copy));
}


// var charsWritten = buffer.utf8Write(string, offset, [maxLength]);
Handle<Value> Buffer::Utf8Write(const Arguments &args) {
  HandleScope scope;
  Buffer *buffer = ObjectWrap::Unwrap<Buffer>(args.This());

  if (!args[0]->IsString()) {
    return ThrowException(Exception::TypeError(String::New(
            "Argument must be a string")));
  }

  Local<String> s = args[0]->ToString();

  size_t offset = args[1]->Uint32Value();

  int length = s->Length();

  if (length == 0) {
    constructor_template->GetFunction()->Set(chars_written_sym,
                                             Integer::New(0));
    return scope.Close(Integer::New(0));
  }

  if (length > 0 && offset >= buffer->length_) {
    return ThrowException(Exception::TypeError(String::New(
            "Offset is out of bounds")));
  }

  size_t max_length = args[2]->IsUndefined() ? buffer->length_ - offset
                                             : args[2]->Uint32Value();
  max_length = MIN(buffer->length_ - offset, max_length);

  char* p = buffer->data_ + offset;

  int char_written;

  int written = s->WriteUtf8(p,
                             max_length,
                             &char_written,
                             (String::HINT_MANY_WRITES_EXPECTED |
                              String::NO_NULL_TERMINATION));

  constructor_template->GetFunction()->Set(chars_written_sym,
                                           Integer::New(char_written));

  return scope.Close(Integer::New(written));
}


// var charsWritten = buffer.ucs2Write(string, offset, [maxLength]);
Handle<Value> Buffer::Ucs2Write(const Arguments &args) {
  HandleScope scope;
  Buffer *buffer = ObjectWrap::Unwrap<Buffer>(args.This());

  if (!args[0]->IsString()) {
    return ThrowException(Exception::TypeError(String::New(
            "Argument must be a string")));
  }

  Local<String> s = args[0]->ToString();

  size_t offset = args[1]->Uint32Value();

  if (s->Length() > 0 && offset >= buffer->length_) {
    return ThrowException(Exception::TypeError(String::New(
            "Offset is out of bounds")));
  }

  size_t max_length = args[2]->IsUndefined() ? buffer->length_ - offset
                                             : args[2]->Uint32Value();
  max_length = MIN(buffer->length_ - offset, max_length) / 2;

  uint16_t* p = (uint16_t*)(buffer->data_ + offset);

  int written = s->Write(p,
                         0,
                         max_length,
                         (String::HINT_MANY_WRITES_EXPECTED |
                          String::NO_NULL_TERMINATION));

  constructor_template->GetFunction()->Set(chars_written_sym,
                                           Integer::New(written));

  return scope.Close(Integer::New(written * 2));
}


// var charsWritten = buffer.asciiWrite(string, offset);
Handle<Value> Buffer::AsciiWrite(const Arguments &args) {
  HandleScope scope;

  Buffer *buffer = ObjectWrap::Unwrap<Buffer>(args.This());

  if (!args[0]->IsString()) {
    return ThrowException(Exception::TypeError(String::New(
            "Argument must be a string")));
  }

  Local<String> s = args[0]->ToString();
  size_t length = s->Length();
  size_t offset = args[1]->Int32Value();

  if (length > 0 && offset >= buffer->length_) {
    return ThrowException(Exception::TypeError(String::New(
            "Offset is out of bounds")));
  }

  size_t max_length = args[2]->IsUndefined() ? buffer->length_ - offset
                                             : args[2]->Uint32Value();
  max_length = MIN(length, MIN(buffer->length_ - offset, max_length));

  char *p = buffer->data_ + offset;

  int written = s->WriteAscii(p,
                              0,
                              max_length,
                              (String::HINT_MANY_WRITES_EXPECTED |
                               String::NO_NULL_TERMINATION));

  constructor_template->GetFunction()->Set(chars_written_sym,
                                           Integer::New(written));

  return scope.Close(Integer::New(written));
}


// var bytesWritten = buffer.base64Write(string, offset, [maxLength]);
Handle<Value> Buffer::Base64Write(const Arguments &args) {
  HandleScope scope;

  Buffer *buffer = ObjectWrap::Unwrap<Buffer>(args.This());

  if (!args[0]->IsString()) {
    return ThrowException(Exception::TypeError(String::New(
            "Argument must be a string")));
  }

  String::AsciiValue s(args[0]);
  size_t length = s.length();
  size_t offset = args[1]->Int32Value();
  size_t max_length = args[2]->IsUndefined() ? buffer->length_ - offset
                                             : args[2]->Uint32Value();
  max_length = MIN(length, MIN(buffer->length_ - offset, max_length));

  if (max_length && offset >= buffer->length_) {
    return ThrowException(Exception::TypeError(String::New(
            "Offset is out of bounds")));
  }

  char a, b, c, d;
  char* start = buffer->data_ + offset;
  char* dst = start;
  char* const dstEnd = dst + max_length;
  const char* src = *s;
  const char* const srcEnd = src + s.length();

  while (src < srcEnd && dst < dstEnd) {
    int remaining = srcEnd - src;

    while (unbase64(*src) < 0 && src < srcEnd) src++, remaining--;
    if (remaining == 0 || *src == '=') break;
    a = unbase64(*src++);

    while (unbase64(*src) < 0 && src < srcEnd) src++, remaining--;
    if (remaining <= 1 || *src == '=') break;
    b = unbase64(*src++);

    *dst++ = (a << 2) | ((b & 0x30) >> 4);
    if (dst == dstEnd) break;

    while (unbase64(*src) < 0 && src < srcEnd) src++, remaining--;
    if (remaining <= 2 || *src == '=') break;
    c = unbase64(*src++);

    *dst++ = ((b & 0x0F) << 4) | ((c & 0x3C) >> 2);
    if (dst == dstEnd) break;

    while (unbase64(*src) < 0 && src < srcEnd) src++, remaining--;
    if (remaining <= 3 || *src == '=') break;
    d = unbase64(*src++);

    *dst++ = ((c & 0x03) << 6) | (d & 0x3F);
  }

  constructor_template->GetFunction()->Set(chars_written_sym,
                                           Integer::New(dst - start));

  return scope.Close(Integer::New(dst - start));
}


Handle<Value> Buffer::BinaryWrite(const Arguments &args) {
  HandleScope scope;

  Buffer *buffer = ObjectWrap::Unwrap<Buffer>(args.This());

  if (!args[0]->IsString()) {
    return ThrowException(Exception::TypeError(String::New(
            "Argument must be a string")));
  }

  Local<String> s = args[0]->ToString();
  size_t length = s->Length();
  size_t offset = args[1]->Int32Value();

  if (s->Length() > 0 && offset >= buffer->length_) {
    return ThrowException(Exception::TypeError(String::New(
            "Offset is out of bounds")));
  }

  char *p = (char*)buffer->data_ + offset;

  size_t max_length = args[2]->IsUndefined() ? buffer->length_ - offset
                                             : args[2]->Uint32Value();
  max_length = MIN(length, MIN(buffer->length_ - offset, max_length));

  int written = DecodeWrite(p, max_length, s, BINARY);

  constructor_template->GetFunction()->Set(chars_written_sym,
                                           Integer::New(written));

  return scope.Close(Integer::New(written));
}


// var nbytes = Buffer.byteLength("string", "utf8")
Handle<Value> Buffer::ByteLength(const Arguments &args) {
  HandleScope scope;

  if (!args[0]->IsString()) {
    return ThrowException(Exception::TypeError(String::New(
            "Argument must be a string")));
  }

  Local<String> s = args[0]->ToString();
  enum encoding e = ParseEncoding(args[1], UTF8);

  return scope.Close(Integer::New(node::ByteLength(s, e)));
}


Handle<Value> Buffer::MakeFastBuffer(const Arguments &args) {
  HandleScope scope;

  if (!Buffer::HasInstance(args[0])) {
    return ThrowException(Exception::TypeError(String::New(
            "First argument must be a Buffer")));
  }

  Buffer *buffer = ObjectWrap::Unwrap<Buffer>(args[0]->ToObject());
  Local<Object> fast_buffer = args[1]->ToObject();;
  uint32_t offset = args[2]->Uint32Value();
  uint32_t length = args[3]->Uint32Value();

  fast_buffer->SetIndexedPropertiesToExternalArrayData(buffer->data_ + offset,
                                                       kExternalUnsignedByteArray,
                                                       length);

  return Undefined();
}


bool Buffer::HasInstance(v8::Handle<v8::Value> val) {
  if (!val->IsObject()) return false;
  v8::Local<v8::Object> obj = val->ToObject();

  if (obj->GetIndexedPropertiesExternalArrayDataType() == kExternalUnsignedByteArray)
    return true;

  // Also check for SlowBuffers that are empty.
  if (constructor_template->HasInstance(obj))
    return true;

  return false;
}


class RetainedBufferInfo: public v8::RetainedObjectInfo {
public:
  RetainedBufferInfo(Buffer* buffer);
  virtual void Dispose();
  virtual bool IsEquivalent(RetainedObjectInfo* other);
  virtual intptr_t GetHash();
  virtual const char* GetLabel();
  virtual intptr_t GetSizeInBytes();
private:
  Buffer* buffer_;
  static const char label[];
};

const char RetainedBufferInfo::label[] = "Buffer";


RetainedBufferInfo::RetainedBufferInfo(Buffer* buffer): buffer_(buffer) {
}


void RetainedBufferInfo::Dispose() {
  buffer_ = NULL;
  delete this;
}


bool RetainedBufferInfo::IsEquivalent(RetainedObjectInfo* other) {
  return label == other->GetLabel() &&
         buffer_ == static_cast<RetainedBufferInfo*>(other)->buffer_;
}


intptr_t RetainedBufferInfo::GetHash() {
  return reinterpret_cast<intptr_t>(buffer_);
}


const char* RetainedBufferInfo::GetLabel() {
  return label;
}


intptr_t RetainedBufferInfo::GetSizeInBytes() {
  return Buffer::Length(buffer_);
}


RetainedObjectInfo* WrapperInfo(uint16_t class_id, Handle<Value> wrapper) {
  assert(class_id == BUFFER_CLASS_ID);
  assert(Buffer::HasInstance(wrapper));
  Buffer* buffer = Buffer::Unwrap<Buffer>(wrapper.As<Object>());
  return new RetainedBufferInfo(buffer);
}


void Buffer::Initialize(Handle<Object> target) {
  HandleScope scope;

  // sanity checks
  assert(unbase64('/') == 63);
  assert(unbase64('+') == 62);
  assert(unbase64('T') == 19);
  assert(unbase64('Z') == 25);
  assert(unbase64('t') == 45);
  assert(unbase64('z') == 51);
  assert(unbase64(' ') == -2);
  assert(unbase64('\n') == -2);
  assert(unbase64('\r') == -2);

  length_symbol = NODE_PSYMBOL("length");
  chars_written_sym = NODE_PSYMBOL("_charsWritten");

  Local<FunctionTemplate> t = FunctionTemplate::New(Buffer::New);
  constructor_template = Persistent<FunctionTemplate>::New(t);
  constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
  constructor_template->SetClassName(String::NewSymbol("SlowBuffer"));

  // copy free
  NODE_SET_PROTOTYPE_METHOD(constructor_template, "binarySlice", Buffer::BinarySlice);
  NODE_SET_PROTOTYPE_METHOD(constructor_template, "asciiSlice", Buffer::AsciiSlice);
  NODE_SET_PROTOTYPE_METHOD(constructor_template, "base64Slice", Buffer::Base64Slice);
  NODE_SET_PROTOTYPE_METHOD(constructor_template, "ucs2Slice", Buffer::Ucs2Slice);
  // TODO NODE_SET_PROTOTYPE_METHOD(t, "utf16Slice", Utf16Slice);
  // copy
  NODE_SET_PROTOTYPE_METHOD(constructor_template, "utf8Slice", Buffer::Utf8Slice);

  NODE_SET_PROTOTYPE_METHOD(constructor_template, "utf8Write", Buffer::Utf8Write);
  NODE_SET_PROTOTYPE_METHOD(constructor_template, "asciiWrite", Buffer::AsciiWrite);
  NODE_SET_PROTOTYPE_METHOD(constructor_template, "binaryWrite", Buffer::BinaryWrite);
  NODE_SET_PROTOTYPE_METHOD(constructor_template, "base64Write", Buffer::Base64Write);
  NODE_SET_PROTOTYPE_METHOD(constructor_template, "ucs2Write", Buffer::Ucs2Write);
  NODE_SET_PROTOTYPE_METHOD(constructor_template, "fill", Buffer::Fill);
  NODE_SET_PROTOTYPE_METHOD(constructor_template, "copy", Buffer::Copy);

  NODE_SET_METHOD(constructor_template->GetFunction(),
                  "byteLength",
                  Buffer::ByteLength);
  NODE_SET_METHOD(constructor_template->GetFunction(),
                  "makeFastBuffer",
                  Buffer::MakeFastBuffer);

  target->Set(String::NewSymbol("SlowBuffer"), constructor_template->GetFunction());

  HeapProfiler::DefineWrapperClass(BUFFER_CLASS_ID, WrapperInfo);
}


}  // namespace node

NODE_MODULE(node_buffer, node::Buffer::Initialize)
//
//          Copyright <NAME> 2009-2010
// Distributed under the Boost Software License, Version 1.0.
//    (See accompanying file LICENSE_1_0.txt or copy at
//          http://www.boost.org/LICENSE_1_0.txt)
//
//

#ifndef _BOOST_MIME_HPP
#define _BOOST_MIME_HPP

#include <list>
#include <string>
#include <vector>
#include <iosfwd>

#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/std_pair.hpp>
#include <boost/spirit/include/phoenix.hpp>  // pulls in all of Phoenix
#include <boost/spirit/include/support_istream_iterator.hpp>
#include <boost/fusion/adapted/struct.hpp>

#include <boost/shared_ptr.hpp>
#include <boost/format.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string.hpp>


// #define  DUMP_MIME_DATA  1


namespace boost { namespace mime {

//  Errors are reported using this exception class
class mime_parsing_error : public std::runtime_error {
public:
    explicit mime_parsing_error ( const std::string & msg ) : std::runtime_error ( msg ) {}
  };

template <class traits> class basic_mime;

namespace detail {

  static const char *k_crlf         = "\015\012";
  static const char *k_package_name     = "Proposed.Boost.Mime";
  static const char *k_package_version    = "0.1";
  static const char *k_content_type_header  = "Content-Type";
  static const char *k_mime_version_header  = "Mime-Version";

  struct default_types {
    typedef std::string string_type;
  //  typedef std::pair < std::string, string_type > header_type;
    typedef std::vector<char> body_type;
    };


  template<typename string_type>
  struct find_mime_header {
    find_mime_header ( const char *str ) : searchFor ( str ) {}
    bool operator () ( const std::pair<std::string, string_type> &val ) const { return boost::iequals ( val.first, searchFor ); }
  private:
    const char *searchFor;
    };


#ifdef  DUMP_MIME_DATA
  struct tracer {
    tracer ( const char *fn ) : fn_ (fn) { std::cout << "->" << fn_ << std::endl; }
    ~tracer () { std::cout << "<-" << fn_ << std::endl; }
    const char *fn_;
    };
#else
  struct tracer {
    tracer ( const char * ) {}
    ~tracer () {}
    };
#endif

//  Parsing a Content-Type header
  typedef std::pair<std::string, std::string> phrase_t;
  typedef std::vector < phrase_t > phrase_container_t;
  struct mime_content_type {
    std::string     type;
    std::string     sub_type;
    phrase_container_t  phrases;
    };
  

  namespace qi  = boost::spirit::qi;
  namespace phx = boost::phoenix;
  using boost::spirit::_val;
  using boost::spirit::_1;
  
  template <typename Iterator, typename Container>
  struct mime_header_parser : qi::grammar<Iterator, Container()>
  {
    mime_header_parser() : mime_header_parser::base_type(mime_headerList)
    {
      mime_headerList = *(mime_header) >> crlf;
      mime_header   = token >> qi::lit ( ':' ) >> value >> crlf;
      token     = qi::char_("a-zA-Z") >> *qi::char_("a-zA-Z_0-9\\-");

    //  In Classifieds/000001, a header begins with a CRLF
      value     = ( valuePart [ _val = _1 ] | qi::eps ) >> *(valueCont [ _val += "\015\012" + _1 ]);
      valueCont   = crlf >> contWS [ _val += _1 ] >> valuePart [ _val += _1 ];
      valuePart   = +qi::char_("\t -~");
      
      contWS      = +qi::char_( " \t");
      crlf      = qi::lit ( k_crlf );

    /*  mime_headerList.name("mime-header-list");
      mime_header.name    ("mime-header");
      token.name          ("mime-token");
      valuePart.name      ("mime-value-part");
      value.name          ("mime-value");

      qi::on_error<qi::fail> ( mime_headerList, 
        std::cout
          << phoenix::val("Error! Expecting ") 
          << qi::labels::_4 
          << phoenix::val(" here: \"") 
          << phoenix::construct<std::string>(qi::labels::_3, qi::labels::_2) 
          << phoenix::val("\"")
          << std::endl
        );
    */  
    }
    
    qi::rule<Iterator, Container()> mime_headerList ;
    qi::rule<Iterator, typename Container::value_type()> mime_header;
    qi::rule<Iterator, std::string()> token, value, valueCont, valuePart, contWS;
    qi::rule<Iterator> crlf;
  };
  
  template<typename Container, typename Iterator>
  static Container read_headers ( Iterator &begin, Iterator end ) {
    tracer t ( __func__ );
    Container retVal;

    mime_header_parser<Iterator, Container> mh_parser;
    bool b = qi::parse ( begin, end, mh_parser, retVal );
    if ( !b )
      throw mime_parsing_error ( "Failed to parse headers" );
      
#ifdef  DUMP_MIME_DATA
    std::cout             << "******Headers*******" << std::endl;
    for ( typename Container::const_iterator iter = retVal.begin (); iter != retVal.end (); ++iter ) {
      std::string val = iter->second;
      size_t idx;
      while ( std::string::npos != ( idx = val.find ( k_crlf )))
        val.replace ( idx, std::strlen ( k_crlf ), "\n" );
      std::cout << iter->first << ": " << val << std::endl;
      }
    std::cout << std::endl << "******Headers*******" << std::endl;
#endif

    return retVal;
    }

//  The structure of a Content-Type mime header is taken from RFC 2045
//    http://www.ietf.org/rfc/rfc2045.txt, section 5.1

  template <typename Iterator>
  struct mime_content_type_parser : qi::grammar<Iterator, mime_content_type()>
  {
    mime_content_type_parser() : mime_content_type_parser::base_type(content_type_header)
    {
        content_type_header =  *qi::lit(' ') >> part >> '/' >> sub_part >> *phrase ;
  
        part        =  token | extension_token;
        sub_part      =  token | extension_token;
  
        phrase        =  qi::lit ( ';' ) >> +ws >> attribute >> '=' >> value >> *ws;
        ws          =  qi::char_( " \t") | line_sep | comment;
        line_sep      =  qi::lexeme[ qi::lit ( k_crlf ) ];
        
        attribute     = token.alias();
        value       = token | quoted_string;
        
        token       = +(qi::char_( " -~" ) - qi::char_( " ()<>@,;:\\\"/[]?=" ));
        comment       =  qi::lit ('(') >> +(qi::char_(" -~" ) - ')' ) >> qi::lit(')');
        quoted_string   =  qi::lit ('"') >> +(qi::char_(" -~" ) - '"' ) >> qi::lit('"');
        extension_token   =  qi::char_ ( "Xx" ) >> qi::lit ( '-' ) >> token;
    }
    
    qi::rule<Iterator, mime_content_type()> content_type_header ;
    qi::rule<Iterator, phrase_t()> phrase ;
    qi::rule<Iterator, std::string()> part, sub_part, token, attribute, value, quoted_string, extension_token;
    qi::rule<Iterator> ws, line_sep, comment;
  };
  
  template<typename string_type>
  mime_content_type parse_content_type ( const string_type &theHeader ) {
    tracer t ( __func__ );
    mime_content_type retVal;
    typename string_type::const_iterator first = theHeader.begin ();
    mime_content_type_parser<typename string_type::const_iterator> ct_parser;
    bool b = qi::parse ( first, theHeader.end (), ct_parser, retVal );
    if (!b)
      throw mime_parsing_error ( "Failed to parse the 'Content-Type' header" );
    
    return retVal;
    }

  template<typename string_type>
  static string_type get_ct_value ( const string_type &ctString, const char *key ) {
    tracer t ( __func__ );
    mime_content_type mc = parse_content_type ( ctString );
    for ( phrase_container_t::const_iterator iter = mc.phrases.begin (); iter != mc.phrases.end (); ++iter )
      if ( boost::iequals ( iter->first, key ))
        return iter->second;
    
    throw std::runtime_error ( str ( boost::format ( "Couldn't find Content-Type phrase (%s)" ) % key ));
    }
  

  //  Replace this with a spirit thing later.
  //  we're looking for '; boundary="<somevalue>".*'
  std::string get_boundary ( const std::string &ctString ) {
    tracer t ( __func__ );
    return get_ct_value ( ctString, "boundary" );
    }


  //  Read the body of a multipart 
  //  Return a Container of containers, where the first is the actual body,
  //  and the rest are the sub-parts.
  //  Note that the body of the multipart can be empty.
  //  If this is the case, then the first separator need not have a crlf

  //  if the marker is "abcde", we could have:
  //    Note that the separators are really CRLF--abcdeCRLF and CRLF--abcde--CRLF
  //
  //  multipart body
  //  --abcde
  //    sub part #1
  //  --abcde
  //    sub part #2
  //  --abcde--
  //
  //  ** or **
  //  In this case, the first separator is --abcdeCRLF
  //
  //  --abcde   (no multipart body!)
  //    sub part #1
  //  --abcde
  //    sub part #2
  //  --abcde--
  
  typedef std::vector<char>   sub_part_t;
  typedef std::vector<sub_part_t> sub_parts_t;

  template<typename bodyContainer>
  struct multipart_body_type {
    bool              prolog_is_missing;
    bodyContainer         body_prolog;
    sub_parts_t           sub_parts;
     bodyContainer          body_epilog;  
    };


  //  Parse a mulitpart body.
  //  Either "--boundaryCRLF" -- in which case the body is empty
  //  or    <some sequence of chars> "CRLF--boundaryCRLF" -- in which case we return the sequence
  //  
  //  I am deliberately not checking for a termination separator here
  template <typename Iterator, typename Container>
  struct multipart_body_parser : qi::grammar<Iterator, Container()> {
    multipart_body_parser( const std::string &boundary, bool &isMissing ) : multipart_body_parser::base_type(mimeBody), m_is_missing ( isMissing ) {
      m_is_missing = false;
    //  Thanks to <NAME> for the hint to get this working
      mimeBody  %= bareSep [ phx::ref ( m_is_missing ) = true ] | (+(qi::char_ - sep) >> sep ) ;
      bareSep     = qi::lit("--") >> boundary >> crlf;
      sep         = crlf >> bareSep;
      crlf    = qi::lit ( k_crlf );
      }
  
    bool &m_is_missing;
    qi::rule<Iterator, Container()> mimeBody;
    qi::rule<Iterator> bareSep, sep, crlf;
    };
  
  
  //  Break up a multi-part into its' constituent sub parts.
  template <typename Iterator, typename Container>
  struct multipart_part_parser : qi::grammar<Iterator, Container()> {
    multipart_part_parser( const std::string &boundary ) : multipart_part_parser::base_type(mimeParts) {
      mimeParts = (+(qi::char_ - sep) % (sep >> crlf)) > terminator ;
      sep         = crlf >> qi::lit("--") >> boundary ;
      terminator  = sep >> qi::lit("--") >> crlf ;
      crlf    = qi::lit ( k_crlf );
      }
    qi::rule<Iterator, Container()> mimeParts;
    qi::rule<Iterator> sep, terminator, crlf;
    };


  template<typename Iterator, typename bodyContainer>
  static void read_multipart_body ( Iterator &begin, Iterator end, multipart_body_type<bodyContainer> &mp_body, const std::string &separator ) {
    tracer t ( __func__ );
    typedef bodyContainer innerC;
    innerC mpBody;
    multipart_body_parser <Iterator, innerC> mb_parser (separator, mp_body.prolog_is_missing );
    if ( !qi::parse ( begin, end, mb_parser, mp_body.body_prolog ))
      throw mime_parsing_error ("Failed to parse mime body(1)");
    
    multipart_part_parser <Iterator, sub_parts_t> mp_parser ( separator );
    if ( !qi::parse ( begin, end, mp_parser, mp_body.sub_parts ))
      throw mime_parsing_error ( "Failed to parse mime body(2)");
    std::copy ( begin, end, std::back_inserter ( mp_body.body_epilog ));
    
  #ifdef  DUMP_MIME_DATA
      std::cout << std::endl << ">>****Multipart Body*******" << std::endl;
      std::cout << str ( boost::format ( "Body size %d, sub part count = %d, trailer size = %d %s" ) % mp_body.body_prolog.size () % mp_body.sub_parts.size () % mp_body.body_epilog.size () % ( mp_body.prolog_is_missing ? "(missing)" : "" )) << std::endl;
      std::cout << std::endl << "****** Multipart Body Prolog *******" << std::endl;
      std::copy ( mp_body.body_prolog.begin (), mp_body.body_prolog.end(), std::ostream_iterator<char> ( std::cout ));
      std::cout << std::endl << "****** Multipart Body Epilog *******" << std::endl;
      std::copy ( mp_body.body_epilog.begin (), mp_body.body_epilog.end(), std::ostream_iterator<char> ( std::cout ));
      std::cout << std::endl << "<<****Multipart Body*******" << std::endl;
  #endif
    }


  template<typename Container, typename Iterator>
  static Container read_simplepart_body ( Iterator &begin, Iterator end ) {
    tracer t ( __func__ );
    Container retVal;
    std::copy ( begin, end, std::back_inserter(retVal));
    
#ifdef  DUMP_MIME_DATA
    std::cout << std::endl << ">>****SinglePart Body*******" << std::endl;
    std::cout << str ( boost::format ( "Body size %d" ) % retVal.size ()) << std::endl;
    std::copy ( retVal.begin (), retVal.end(), std::ostream_iterator<char> ( std::cout ));
    std::cout << std::endl << "<<****SinglePart Body*******" << std::endl;
#endif
    return retVal;
    }

//  FIXME: Need to break the headers at 80 chars...
  template<typename headerList>
  void write_headers ( std::ostream &out, const headerList &headers ) {
    if ( headers.size () > 0 ) {
      for ( typename headerList::const_iterator iter = headers.begin (); iter != headers.end (); ++iter )
        out << iter->first << ':' << iter->second << detail::k_crlf;
      }
    out << detail::k_crlf;
    }
  
  template <typename bodyContainer>
  void write_body ( std::ostream &out, const bodyContainer &body ) {
    std::copy ( body.begin (), body.end (), std::ostream_iterator<char> ( out ));
    }
  
  inline void write_boundary ( std::ostream &out, std::string boundary, bool isLast, bool leadingCR = true ) {
    if ( leadingCR )
      out << detail::k_crlf;
    out << "--" << boundary;
    if ( isLast )
      out << "--";
    out << detail::k_crlf;
    }


  template<typename Iterator, typename traits>
  static boost::shared_ptr< basic_mime<traits> > parse_mime ( Iterator &begin, Iterator end, const char *default_content_type = "text/plain" );
  }


template <class traits = detail::default_types>
class basic_mime {
public:

  typedef enum { simple_part, multi_part, message_part } part_kind;
//  Types for headers
  typedef typename traits::string_type      string_type;
  typedef std::pair< std::string, string_type>  headerEntry;
  typedef std::list<headerEntry>          headerList;
  typedef typename headerList::iterator          headerIter;
  typedef typename headerList::const_iterator   constHeaderIter;

//  Types for the parts
  typedef boost::shared_ptr<basic_mime>   mimePtr;
  typedef std::vector<mimePtr>        partList;
  typedef typename partList::iterator        partIter;
  typedef typename partList::const_iterator constPartIter;

//  Type for the body
  typedef typename traits::body_type      bodyContainer;
  typedef boost::shared_ptr<bodyContainer>  mimeBody;
  
// -----------------------------------------------------------
//  Constructors, destructor, assignment, and swap
// -----------------------------------------------------------

  basic_mime ( const char *type, const char *subtype )
    : m_body_prolog_is_missing ( false ), m_body ( new bodyContainer ), m_body_epilog ( new bodyContainer ) {
    if ( NULL == type || NULL == subtype || 0 == std::strlen ( type ) || 0 == std::strlen ( subtype ))
      throw std::runtime_error ( "Can't create a mime part w/o a type or subtype" );
    
  //  We start with just two headers, "Content-Type:" and "Mime-Version"
  //  Everything else is optional.
    m_part_kind = part_kind_from_string_pair ( type, subtype );
    std::string ctString = str ( boost::format ( "%s/%s" ) % type % subtype );
    set_header_value ( detail::k_content_type_header, ctString );
    set_header_value ( detail::k_mime_version_header, str ( boost::format ( "1.0 (%s %s)" ) % detail::k_package_name % detail::k_package_version ));
    }
  
  basic_mime ( const headerList &theHeaders, const string_type &default_content_type )
    : m_body_prolog_is_missing ( false ), m_body ( new bodyContainer ), m_body_epilog ( new bodyContainer ),
      m_default_content_type ( default_content_type ) {
    string_type ct = m_default_content_type;
  
    constHeaderIter found = std::find_if ( theHeaders.begin (), theHeaders.end (), 
                  detail::find_mime_header<string_type> ( detail::k_content_type_header ));
    if ( found != theHeaders.end ())
      ct = found->second;
    
    detail::mime_content_type mct = detail::parse_content_type ( ct );
    m_part_kind = part_kind_from_string_pair ( mct.type, mct.sub_type );
    m_headers = theHeaders;
    }
  
  basic_mime ( const basic_mime &rhs )
      : m_part_kind ( rhs.m_part_kind ), m_headers ( rhs.m_headers ), m_body_prolog_is_missing ( rhs.m_body_prolog_is_missing ), 
        m_body ( new bodyContainer ( *rhs.m_body )), m_body_epilog ( new bodyContainer ( *rhs.m_body_epilog )),
    /*  m_subparts ( rhs.m_subparts ), */ m_default_content_type ( rhs.m_default_content_type )
    {
  //  Copy the parts -- not just the shared pointers
    for ( typename partList::const_iterator iter = rhs.subpart_begin (); iter != rhs.subpart_end (); ++iter )
      m_subparts.push_back ( mimePtr ( new basic_mime ( **iter )));
    }

//  Simple, copy constructor-based assignment
//  If this is not efficient enough, then I can optimize it later
  basic_mime & operator = ( const basic_mime &rhs ) {
    basic_mime temp ( rhs );
    this->swap ( temp );
    return *this;
    } 

  void swap ( basic_mime &rhs ) throw () {
    std::swap ( m_part_kind,        rhs.m_part_kind );
    std::swap ( m_headers,          rhs.m_headers );
    std::swap ( m_body_prolog_is_missing, rhs.m_body_prolog_is_missing );
    std::swap ( m_body,           rhs.m_body );
    std::swap ( m_body_epilog,        rhs.m_body_epilog );
    std::swap ( m_subparts,         rhs.m_subparts );
    std::swap ( m_default_content_type,   rhs.m_default_content_type );
    }

  ~basic_mime () {}
  

//  What kind of part is this (simple, multi, message)
  part_kind get_part_kind () const { return m_part_kind; }

//  Sub-part information
//  FIXME: Need some error checking here
//    No sub-parts for simple parts, for example.
  size_t part_count () const { return m_subparts.size (); }

  boost::shared_ptr <basic_mime> operator [] ( std::size_t idx ) const {
    check_subpart_index ( idx );
    return m_subparts [ idx ];
    }

  void append_part ( boost::shared_ptr<basic_mime> newPart ) {
    check_subpart_append ();
    m_subparts.push_back ( newPart );
    }
  
  partIter    subpart_begin ()    { return m_subparts.begin (); }
  partIter    subpart_end   ()    { return m_subparts.end   (); }
  constPartIter subpart_begin () const  { return m_subparts.begin (); }
  constPartIter subpart_end   () const  { return m_subparts.end   (); }
  
//  Reading the raw headers
  headerIter    header_begin ()     { return m_headers.begin (); }
  headerIter    header_end   ()     { return m_headers.end   (); }
  constHeaderIter header_begin () const { return m_headers.begin (); }
  constHeaderIter header_end   () const { return m_headers.end   (); }

// -----------------------------------------------------------
//  Header manipulation
// -----------------------------------------------------------

//  The 'tag' part of the header is still a std::string
  bool header_exists ( const char *key ) const {
    return header_end () != find_header ( key );
    }
    
  string_type header_value  ( const char *key ) const  {
    constHeaderIter found = find_header ( key );
    if ( found == header_end ())
      throw std::runtime_error ( "'header_value' not found" );
    return found->second;
    }
  
  void set_header_value  ( const char *key, const string_type &value, bool replace = false ) {
    if ( !replace )
      m_headers.push_back ( std::make_pair ( std::string ( key ), value ));
    else {
      headerIter found = find_header ( key );
      if ( found == m_headers.end ())
        throw std::runtime_error ( "'header_value' not found - can't replace" );
      found->second = value;
      }
    }

    
  string_type get_content_type_header () const {
    constHeaderIter found = find_header ( detail::k_content_type_header );
    return found != header_end () ? found->second : m_default_content_type;
    }
  
  
  string_type get_content_type () const {
    detail::mime_content_type mct = detail::parse_content_type ( get_content_type_header ());
    return string_type ( mct.type ) + '/' + mct.sub_type;
    }
  

//  Special purpose helper routine
  void  append_phrase_to_content_type ( const char *key, const string_type &value ) {
    headerIter found = find_header ( detail::k_content_type_header );
  
  //  Create a Content-Type header if there isn't one
    if ( m_headers.end () == found ) {
      m_headers.push_back ( std::make_pair ( std::string ( detail::k_content_type_header ), m_default_content_type ));
      found = find_header ( detail::k_content_type_header );
      }
  
    detail::mime_content_type mct = detail::parse_content_type ( found->second );
    detail::phrase_container_t::const_iterator p_found =
      std::find_if ( mct.phrases.begin (), mct.phrases.end (), 
        detail::find_mime_header<std::string> ( key ));
    if ( p_found != mct.phrases.end ())
      throw std::runtime_error ( "phrase already exists" );
    found->second += str ( boost::format ( "; %s=\"%s\"" ) % key % value );
  } 
  
  
//  Body get/set methods
  mimeBody body ()    const { return m_body; }
  mimeBody body_prolog () const { return m_body; }
  mimeBody body_epilog () const { return m_body_epilog; }

  std::size_t body_size () const { return m_body->size (); }

  template <typename Iterator>
  void set_body ( Iterator begin, Iterator end ) {
    bodyContainer temp;
    std::copy ( begin, end, std::back_inserter ( temp ));
    m_body->swap ( temp );
    }

  void set_body ( const char *contents, size_t sz ) { set_body ( contents, contents + sz ); }
  void set_body ( std::istream &in )                { set_body ( std::istream_iterator<char> ( in ), std::istream_iterator<char> ()); }
  void set_body ( const bodyContainer &new_body )   { *m_body = new_body; }

  void set_multipart_prolog_is_missing ( bool isMissing ) { m_body_prolog_is_missing = isMissing; }
  void set_body_prolog ( const bodyContainer &new_body_prolog ) { *m_body        = new_body_prolog; }
  void set_body_epilog ( const bodyContainer &new_body_epilog ) { *m_body_epilog = new_body_epilog; }

// -----------------------------------------------------------
//  Output
// -----------------------------------------------------------
  void stream_out ( std::ostream &out ) { // called by operator << 
    if ( m_part_kind == simple_part ) {
      detail::write_headers ( out, m_headers );
      detail::write_body ( out, *m_body );
      }
    else if ( m_part_kind == message_part ) {
      if ( m_subparts.size () != 1 )
        throw std::runtime_error ( "message part w/wrong number of sub-parts - should be 1" );
        
      detail::write_headers ( out, m_headers );
      m_subparts [ 0 ]->stream_out ( out );
      }
    else { // multi-part
    //  Find or invent a boundary string
      std::string boundary;
      try { boundary = detail::get_boundary ( get_content_type_header ()); }
      catch ( std::runtime_error & ) {
      //  FIXME: Make boundary strings (more?) unique
        boundary = str ( boost::format ( "------=_NextPart-%s.%08ld" ) % detail::k_package_name % std::clock ());
        append_phrase_to_content_type ( "boundary", boundary );
        }
      
    //  If the body prolog is missing, we don't want a CRLF on the front of the first sub-part.
    //  Note that there's a (subtle) difference between an zero length body and a missing one.
    //  See the comments in the parser code for more information.
      detail::write_headers ( out, m_headers );
      bool writeCR = body_prolog ()->size () > 0 || !m_body_prolog_is_missing;
      detail::write_body ( out, *body_prolog ());
      for ( typename partList::const_iterator iter = m_subparts.begin (); iter != m_subparts.end (); ++iter ) {
        detail::write_boundary ( out, boundary, false, writeCR );
        (*iter)->stream_out ( out );
        writeCR = true;
        }
      detail::write_boundary ( out, boundary, true );
      detail::write_body ( out, *body_epilog ());
      }
  //  out << detail::k_crlf;
    }
  
//  Build a simple mime part
  template <typename Iterator>
  static basic_mime make_simple_part ( const char *type, const char *subtype, Iterator begin, Iterator end ) {
    basic_mime retval ( type, subtype );
    retval.set_body ( begin, end );
    return retval;
    }

//  Build a mime part from a pair of iterators
  template <typename Iterator>
  static boost::shared_ptr< basic_mime<traits> > parse_mime ( Iterator &begin, Iterator end ) {
    return detail::parse_mime<Iterator, traits> ( begin, end );
    }

//  Build a mime part from a stream
  static boost::shared_ptr < basic_mime > parse_mime ( std::istream &in ) {
    boost::spirit::istream_iterator first (in);
    boost::spirit::istream_iterator last;
    return parse_mime ( first, last );
    }
    

private:
  basic_mime ();  // Can't create a part w/o a type

  headerIter  find_header ( const char *key ) {
    return std::find_if ( header_begin (), header_end (), detail::find_mime_header<string_type> ( key ));
    }
  
  constHeaderIter find_header ( const char *key ) const {
    return std::find_if ( header_begin (), header_end (), detail::find_mime_header<string_type> ( key ));
    }

  static part_kind part_kind_from_string_pair ( const std::string &type, const std::string &sub_type ) {
    if ( boost::iequals ( type, "multipart" ))
      return multi_part;
      
    part_kind retVal = simple_part;
  //  I expect that this will get more complicated as time goes on....
  //
  //  message/delivery-status is a simple type.
  //  RFC 3464 defines message/delivery-status <http://www.faqs.org/rfcs/rfc3464.html>
  //  The body of a message/delivery-status consists of one or more
  //     "fields" formatted according to the ABNF of RFC 822 header "fields"
  //     (see [RFC822]).  
    if ( boost::iequals ( type, "message" ))
      if ( !boost::iequals ( sub_type, "delivery-status" ))
        retVal = message_part;
    return retVal;
    }
  
  void check_subpart_index ( size_t idx ) const {
    if ( get_part_kind () == simple_part )
      throw std::runtime_error ( "Simple Mime parts don't have sub-parts" );
    else if ( get_part_kind () == multi_part ) {
        if ( idx >= m_subparts.size ())
          throw std::runtime_error ( 
            str ( boost::format ( "Trying to access part %d (of %d) sub-part to a multipart/xxx mime part" ) % idx %  m_subparts.size ()));
      }
    else {  // message-part
      if ( get_part_kind () == message_part )
        if ( m_subparts.size () > 1 )
          throw std::runtime_error ( "How did a message/xxx mime parts get more than one sub-part?" );

      if ( idx >= m_subparts.size ())
        throw std::runtime_error ( 
          str ( boost::format ( "Trying to access part %d (of %d) sub-part to a message/xxx mime part" ) % idx %  m_subparts.size ()));
      }
    }

  void check_subpart_append () const {
    if ( get_part_kind () == simple_part )
      throw std::runtime_error ( "Simple Mime parts don't have sub-parts" );
    else if ( get_part_kind () == message_part ) {
      if ( m_subparts.size () > 0 )
        throw std::runtime_error ( "Can't add a second sub-part to a message/xxx mime part" );
      }
  //  else { /* Multi-part */ } // We can always add to a multi-part
    }
  
  part_kind m_part_kind;
  headerList  m_headers;
  bool    m_body_prolog_is_missing; // only for multiparts
  mimeBody  m_body;
  mimeBody  m_body_epilog;        // only for multiparts
  partList  m_subparts;         // only for multiparts or message
  string_type m_default_content_type;
  };


namespace detail {

  template<typename Iterator, typename traits>
  static boost::shared_ptr< basic_mime<traits> > parse_mime ( Iterator &begin, Iterator end, const char *default_content_type ) {
    tracer t ( __func__ );
    typedef typename boost::mime::basic_mime<traits>  mime_part;
    
    shared_ptr < mime_part > retVal (
      new mime_part ( detail::read_headers<typename mime_part::headerList> ( begin, end ), default_content_type ));
  
    std::string content_type = retVal->get_content_type ();

#ifdef  DUMP_MIME_DATA
    std::cout << "Content-Type: " << content_type << std::endl;
    std::cout << str ( boost::format ( "retVal->get_part_kind () = %d" ) % ((int) retVal->get_part_kind ())) << std::endl;
#endif

    if ( retVal->get_part_kind () == mime_part::simple_part )
      retVal->set_body ( detail::read_simplepart_body<typename mime_part::bodyContainer, Iterator> ( begin, end ));
    else if ( retVal->get_part_kind () == mime_part::message_part ) {
    //  If we've got a message/xxxx, then there is no body, and we have a single
    //  embedded mime_part (which, of course, could be a multipart)
      retVal->append_part ( parse_mime<Iterator, traits> ( begin, end ));
      }
    else /* multi_part */ {
    //  Find or invent a boundary string
      std::string part_separator = detail::get_boundary ( retVal->get_content_type_header ());
      const char *cont_type = boost::iequals ( content_type, "multipart/digest" ) ? "message/rfc822" : "text/plain";
      
      detail::multipart_body_type<typename traits::body_type> body_and_subParts;
      detail::read_multipart_body ( begin, end, body_and_subParts, part_separator );

      retVal->set_body_prolog ( body_and_subParts.body_prolog );
      retVal->set_multipart_prolog_is_missing ( body_and_subParts.prolog_is_missing );
      for ( typename sub_parts_t::const_iterator iter = body_and_subParts.sub_parts.begin ();
          iter != body_and_subParts.sub_parts.end (); ++iter ) {
        typedef typename sub_part_t::const_iterator iter_type;
        iter_type b = iter->begin ();
        iter_type e = iter->end ();
        retVal->append_part ( parse_mime<iter_type, traits> ( b, e, cont_type ));
        }
      retVal->set_body_epilog ( body_and_subParts.body_epilog );
      }
    
    return retVal;
    } 
  
  }


// -----------------------------------------------------------
//
//  Streaming
//
// -----------------------------------------------------------

template<typename traits>
inline std::ostream & operator << ( std::ostream &stream, basic_mime<traits> &part ) {
  part.stream_out ( stream );
  return stream;
  }

template<typename traits>
inline std::ostream & operator << ( std::ostream &stream, boost::shared_ptr <basic_mime<traits> > part ) {
  return stream << *part;
  }


    
}}

BOOST_FUSION_ADAPT_STRUCT(
   boost::mime::detail::mime_content_type,
   (std::string, type)
   (std::string, sub_type)
   (boost::mime::detail::phrase_container_t, phrases)
)

#endif  // _BOOST_MIME_HPP


<|start_filename|>codeview/src/main/java/io/github/kbiakov/codeview/adapters/CodeWithNotesAdapter.kt<|end_filename|>
package io.github.kbiakov.codeview.adapters

import android.content.Context
import io.github.kbiakov.codeview.highlight.color
import io.github.kbiakov.codeview.views.LineNoteView

/**
 * @class CodeWithNotesAdapter
 *
 * Default code content adapter.
 *
 * @author <NAME>
 */
open class CodeWithNotesAdapter : AbstractCodeAdapter<String> {

    constructor(context: Context) : super(context)

    constructor(context: Context, code: String) : super(context, code)

    constructor(context: Context, options: Options) : super(context, options)

    /**
     * Create footer view.
     *
     * @param entity Note content
     * @param isFirst Is first footer view
     */
    override fun createFooter(context: Context, entity: String, isFirst: Boolean) =
            LineNoteView.create(context,
                    text = entity,
                    isFirst = isFirst,
                    bgColor = options.theme.bgNum.color(),
                    textColor = options.theme.noteColor.color())
}


<|start_filename|>example/src/main/java/io/github/kbiakov/codeviewexample/BaseApplication.java<|end_filename|>
package io.github.kbiakov.codeviewexample;

import android.app.Application;

import io.github.kbiakov.codeview.classifier.CodeProcessor;

public class BaseApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        // train classifier on app start
        CodeProcessor.init(this);
    }
}


<|start_filename|>codeview/src/main/assets/training-set/css/css.css<|end_filename|>

html {
	margin: 0;
	padding: 0;
	border: 0;
	-moz-transition: all;
	-o-transition: all;
	-webkit-transition: all;
	transition: all;
}

.hidden {
	display: none !important;
	visibility: hidden !important;
}

body {
	stroke: #eee;
	stroke-width: 2;
	stroke-dasharray: 0;
}

a {
	text-align: center;
	font-size: 1.1rem;
	padding: 12px 0;
}

li {
	-webkit-touch-callout: none;
	-moz-user-select: none;
	-ms-user-select: none;
	-webkit-user-select: none;
	user-select: none;
}

/* points of interest */
ul > li {
	stroke: steelblue;
	stroke-width: 2;
	fill: #FFF;
	-moz-transform-origin: center;
	-ms-transform-origin: center;
	-o-transform-origin: center;
	-webkit-transform-origin: center;
	transform-origin: center;
}

a + div {
	background-size: cover;
}



div {
	background: #fff;
}

.n2-charts-close {
	font-size: 32px;
	position: absolute;
	top: 20px;
	right: 20px;
	padding: 2px 12px;
	cursor: pointer;
}

/* Landscape styles */
@media screen and (orientation:landscape) {

	.chart.fullscreen {
		font-size: 32px;
		position: absolute;
		top: 20px;
		right: 20px;
		padding: 2px 12px;
		cursor: pointer;
	}
}

@-moz-keyframes n2-poi-blink {
	0% {
		-moz-transform: scale(1);
		-ms-transform: scale(1);
		-o-transform: scale(1);
		-webkit-transform: scale(1);
		transform: scale(1);
	}

	100% {
		-moz-transform: scale(1);
		-ms-transform: scale(1);
		-o-transform: scale(1);
		-webkit-transform: scale(1);
		transform: scale(1);
	}
}

@-ms-keyframes n2-poi-blink {
	0% {
		-moz-transform: scale(1);
		-ms-transform: scale(1);
		-o-transform: scale(1);
		-webkit-transform: scale(1);
		transform: scale(1);
	}

	100% {
		-moz-transform: scale(1);
		-ms-transform: scale(1);
		-o-transform: scale(1);
		-webkit-transform: scale(1);
		transform: scale(1);
	}
}

@-webkit-keyframes n2-poi-blink {
	0% {
		-moz-transform: scale(1);
		-ms-transform: scale(1);
		-o-transform: scale(1);
		-webkit-transform: scale(1);
		transform: scale(1);
	}

	100% {
		-moz-transform: scale(1);
		-ms-transform: scale(1);
		-o-transform: scale(1);
		-webkit-transform: scale(1);
		transform: scale(1);
	}
}

@keyframes n2-poi-blink {
	0% {
		-moz-transform: scale(1);
		-ms-transform: scale(1);
		-o-transform: scale(1);
		-webkit-transform: scale(1);
		transform: scale(1);
	}

	100% {
		-moz-transform: scale(1);
		-ms-transform: scale(1);
		-o-transform: scale(1);
		-webkit-transform: scale(1);
		transform: scale(1);
	}
}
