text:
package mini

import (
	"github.com/stretchr/testify/assert"
	"os"
	"path"
	"strings"
	"testing"
)

func TestSimpleIniFile(t *testing.T) {

	simpleIni := `first=alpha
second=beta
third="gamma bamma"
fourth = 'delta'
int=32
float=3.14
true=true
false=false
#comment
; comment`

	filepath := path.Join(os.TempDir(), "simpleini.txt")
	f, err := os.Create(filepath)
	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(filepath)
	if _, err := f.WriteString(simpleIni); err != nil {
		t.Fatal(err)
	}
	if err := f.Close(); err != nil {
		t.Fatal(err)
	}

	config, err := LoadConfiguration(filepath)

	assert.Nil(t, err, "Simple configuration should load without error.")

	assert.Equal(t, config.String("first", ""), "alpha", "Read value of first wrong")
	assert.Equal(t, config.String("second", ""), "beta", "Read value of second wrong")
	assert.Equal(t, config.String("third", ""), "gamma bamma", "Read value of third wrong")
	assert.Equal(t, config.String("fourth", ""), "delta", "Read value of fourth wrong")
	assert.Equal(t, config.Integer("int", 0), int64(32), "Read value of int wrong")
	assert.Equal(t, config.Float("float", 0), 3.14, "Read value of float wrong")
	assert.Equal(t, config.Boolean("true", false), true, "Read true wrong")
	assert.Equal(t, config.Boolean("false", true), false, "Read false wrong")

	assert.Equal(t, len(config.Keys()), 8, "Simple ini contains 8 fields")
}

func TestSimpleIniFileFromReader(t *testing.T) {

	simpleIni := `first=alpha
second=beta
third="gamma bamma"
fourth = 'delta'
int=32
float=3.14
true=true
false=false
#comment
; comment`

	config, err := LoadConfigurationFromReader(strings.NewReader(simpleIni))

	assert.Nil(t, err, "Simple configuration should load without error.")

	assert.Equal(t, config.String("first", ""), "alpha", "Read value of first wrong")
	assert.Equal(t, config.String("second", ""), "beta", "Read value of second wrong")
	assert.Equal(t, config.String("third", ""), "gamma bamma", "Read value of third wrong")
	assert.Equal(t, config.String("fourth", ""), "delta", "Read value of fourth wrong")
	assert.Equal(t, config.Integer("int", 0), int64(32), "Read value of int wrong")
	assert.Equal(t, config.Float("float", 0), 3.14, "Read value of float wrong")
	assert.Equal(t, config.Boolean("true", false), true, "Read true wrong")
	assert.Equal(t, config.Boolean("false", true), false, "Read false wrong")

	assert.Equal(t, len(config.Keys()), 8, "Simple ini contains 8 fields")
}

func TestCaseInsensitive(t *testing.T) {

	simpleIni := `fIrst=alpha
SECOND=beta
Third="gamma bamma"
FourTh = 'delta'`

	config, err := LoadConfigurationFromReader(strings.NewReader(simpleIni))

	assert.Nil(t, err, "Case insensitive configuration should load without error.")

	assert.Equal(t, config.String("first", ""), "alpha", "Read value of first wrong")
	assert.Equal(t, config.String("second", ""), "beta", "Read value of second wrong")
	assert.Equal(t, config.String("THIRD", ""), "gamma bamma", "Read value of third wrong")
	assert.Equal(t, config.String("fourth", ""), "delta", "Read value of fourth wrong")

	assert.Equal(t, len(config.Keys()), 4, "Case ins ini contains 4 fields")
}

func TestArrayOfStrings(t *testing.T) {

	simpleIni := `key[]=one
key[]=two
noarray=three`

	config, err := LoadConfigurationFromReader(strings.NewReader(simpleIni))

	assert.Nil(t, err, "Simple configuration should load without error.")

	val := config.Strings("key")

	assert.Equal(t, len(val), 2, "Array for keys should have 2 values")
	assert.Equal(t, val[0], "one", "Read value of first wrong")
	assert.Equal(t, val[1], "two", "Read value of second wrong")

	val = config.Strings("noarray")
	assert.Equal(t, len(val), 1, "Array for noarray should have 1 value")
	assert.Equal(t, val[0], "three", "Read value of noarray wrong")

	assert.Equal(t, len(config.Keys()), 2, "StringArray test contains 2 fields")
}

func TestArrayOfIntegers(t *testing.T) {

	simpleIni := `key[]=1
key[]=2
noarray=3`

	config, err := LoadConfigurationFromReader(strings.NewReader(simpleIni))

	assert.Nil(t, err, "Simple configuration should load without error.")

	val := config.Integers("key")

	assert.Equal(t, len(val), 2, "Array for keys should have 2 values")
	assert.Equal(t, val[0], int64(1), "Read value of first wrong")
	assert.Equal(t, val[1], int64(2), "Read value of second wrong")

	val = config.Integers("noarray")
	assert.Equal(t, len(val), 1, "Array for noarray should have 1 value")
	assert.Equal(t, val[0], int64(3), "Read value of noarray wrong")

	assert.Equal(t, len(config.Keys()), 2, "IntArray test contains 2 fields")
}

func TestArrayOfFloats(t *testing.T) {

	simpleIni := `key[]=1.1
key[]=2.2
noarray=3.3`

	config, err := LoadConfigurationFromReader(strings.NewReader(simpleIni))

	assert.Nil(t, err, "Simple configuration should load without error.")

	val := config.Floats("key")

	assert.Equal(t, len(val), 2, "Array for keys should have 2 values")
	assert.Equal(t, val[0], 1.1, "Read value of first wrong")
	assert.Equal(t, val[1], 2.2, "Read value of second wrong")

	val = config.Floats("noarray")
	assert.Equal(t, len(val), 1, "Array for noarray should have 1 value")
	assert.Equal(t, val[0], 3.3, "Read value of noarray wrong")

	assert.Equal(t, len(config.Keys()), 2, "FloatArray test contains 2 fields")
}

func TestSectionedIniFile(t *testing.T) {

	simpleIni := `first=alpha
second=beta
third="gamma bamma"
fourth = 'delta'
int=32
float=3.14
true=true
false=false

[section]
first=raz
second=dba
int=124
float=1222.7
true=false
false=true
#comment
; comment`

	config, err := LoadConfigurationFromReader(strings.NewReader(simpleIni))

	assert.Nil(t, err, "Sectioned configuration should load without error.")

	assert.Equal(t, config.String("first", ""), "alpha", "Read value of first wrong")
	assert.Equal(t, config.String("second", ""), "beta", "Read value of second wrong")
	assert.Equal(t, config.String("third", ""), "gamma bamma", "Read value of third wrong")
	assert.Equal(t, config.String("fourth", ""), "delta", "Read value of fourth wrong")
	assert.Equal(t, config.Integer("int", 0), int64(32), "Read value of int wrong")
	assert.Equal(t, config.Float("float", 0), 3.14, "Read value of float wrong")
	assert.Equal(t, config.Boolean("true", false), true, "Read true wrong")
	assert.Equal(t, config.Boolean("false", true), false, "Read false wrong")

	assert.Equal(t, config.StringFromSection("section", "first", ""), "raz", "Read value of first from section wrong")
	assert.Equal(t, config.StringFromSection("section", "second", ""), "dba", "Read value of second from section wrong")
	assert.Equal(t, config.IntegerFromSection("section", "int", 0), int64(124), "Read value of int in section wrong")
	assert.Equal(t, config.FloatFromSection("section", "float", 0), 1222.7, "Read value of float in section wrong")
	assert.Equal(t, config.BooleanFromSection("section", "true", true), false, "Read true in section wrong")
	assert.Equal(t, config.BooleanFromSection("section", "false", false), true, "Read false in section wrong")

	assert.Equal(t, len(config.Keys()), 8, "Section ini contains 6 fields")
	assert.Equal(t, len(config.KeysForSection("section")), 6, "Section in ini contains 4 fields")
}

func TestArrayOfStringsInSection(t *testing.T) {

	simpleIni := `key=nope
noarray=nope
[section]
key[]=one
key[]=two
noarray=three`

	config, err := LoadConfigurationFromReader(strings.NewReader(simpleIni))

	assert.Nil(t, err, "Configuration should load without error.")

	val := config.StringsFromSection("section", "key")

	assert.Equal(t, len(val), 2, "Array for keys should have 2 values")
	assert.Equal(t, val[0], "one", "Read value of first wrong")
	assert.Equal(t, val[1], "two", "Read value of second wrong")

	val = config.StringsFromSection("section", "noarray")
	assert.Equal(t, len(val), 1, "Array for noarray should have 1 value")
	assert.Equal(t, val[0], "three", "Read value of noarray wrong")

	assert.Equal(t, len(config.Keys()), 2, "StringArray section test contains 2 fields")
}

func TestArrayOfIntegersInSection(t *testing.T) {

	simpleIni := `key=nope
noarray=nope
[section]
key[]=1
key[]=2
noarray=3`

	config, err := LoadConfigurationFromReader(strings.NewReader(simpleIni))

	assert.Nil(t, err, "Configuration should load without error.")

	val := config.IntegersFromSection("section", "key")

	assert.Equal(t, len(val), 2, "Array for keys should have 2 values")
	assert.Equal(t, val[0], int64(1), "Read value of first wrong")
	assert.Equal(t, val[1], int64(2), "Read value of second wrong")

	val = config.IntegersFromSection("section", "noarray")
	assert.Equal(t, len(val), 1, "Array for noarray should have 1 value")
	assert.Equal(t, val[0], int64(3), "Read value of noarray wrong")

	assert.Equal(t, len(config.KeysForSection("section")), 2, "IntArray section test contains 2 fields")
}

func TestArrayOfFloatsInSection(t *testing.T) {

	simpleIni := `key=nope
noarray=nope
[section]
key[]=1.1
key[]=2.2
noarray=3.3`

	config, err := LoadConfigurationFromReader(strings.NewReader(simpleIni))

	assert.Nil(t, err, "Configuration should load without error.")

	val := config.FloatsFromSection("section", "key")

	assert.Equal(t, len(val), 2, "Array for keys should have 2 values")
	assert.Equal(t, val[0], 1.1, "Read value of first wrong")
	assert.Equal(t, val[1], 2.2, "Read value of second wrong")

	val = config.FloatsFromSection("section", "noarray")
	assert.Equal(t, len(val), 1, "Array for noarray should have 1 value")
	assert.Equal(t, val[0], 3.3, "Read value of noarray wrong")

	assert.Equal(t, len(config.Keys()), 2, "FloatArray section test contains 2 fields")
}

func TestMultipleSections(t *testing.T) {

	simpleIni := `first=alpha
int=32
float=3.14

[section_one]
first=raz
int=124
float=1222.7

[section_two]
first=one
int=555
float=124.3`

	config, err := LoadConfigurationFromReader(strings.NewReader(simpleIni))

	assert.Nil(t, err, "Sectioned configuration should load without error.")

	assert.Equal(t, config.String("first", ""), "alpha", "Read value of first wrong")
	assert.Equal(t, config.Integer("int", 0), int64(32), "Read value of int wrong")
	assert.Equal(t, config.Float("float", 0), 3.14, "Read value of float wrong")

	assert.Equal(t, config.StringFromSection("", "first", ""), "alpha", "Read value of first wrong")
	assert.Equal(t, config.IntegerFromSection("", "int", 0), int64(32), "Read value of int wrong")
	assert.Equal(t, config.FloatFromSection("", "float", 0), 3.14, "Read value of float wrong")

	config.SetName("section_zero")

	assert.Equal(t, config.StringFromSection("section_zero", "first", ""), "alpha", "Read value of first wrong")
	assert.Equal(t, config.IntegerFromSection("section_zero", "int", 0), int64(32), "Read value of int wrong")
	assert.Equal(t, config.FloatFromSection("section_zero", "float", 0), 3.14, "Read value of float wrong")

	assert.Equal(t, config.StringFromSection("section_one", "first", ""), "raz", "Read value of first from section wrong")
	assert.Equal(t, config.IntegerFromSection("section_one", "int", 0), int64(124), "Read value of int in section wrong")
	assert.Equal(t, config.FloatFromSection("section_one", "float", 0), 1222.7, "Read value of float in section wrong")

	assert.Equal(t, config.StringFromSection("section_two", "first", ""), "one", "Read value of first from section wrong")
	assert.Equal(t, config.IntegerFromSection("section_two", "int", 0), int64(555), "Read value of int in section wrong")
	assert.Equal(t, config.FloatFromSection("section_two", "float", 0), 124.3, "Read value of float in section wrong")

	assert.Equal(t, len(config.Keys()), 3, "Section ini contains 3 fields")
	assert.Equal(t, len(config.KeysForSection("section_one")), 3, "Section in ini contains 3 fields")
	assert.Equal(t, len(config.KeysForSection("section_two")), 3, "Section in ini contains 3 fields")
}

func TestSectionNames(t *testing.T) {

	simpleIni := `first=alpha
int=32
float=3.14

[section_one]
first=raz
int=124
float=1222.7

[section_two]
first=one

[section_three]
int=555
float=124.3`

	config, err := LoadConfigurationFromReader(strings.NewReader(simpleIni))

	assert.Nil(t, err, "Sectioned configuration should load without error.")

	sectionNames := config.SectionNames()

	assert.Equal(t, len(sectionNames), 3, "Read section name array wrong")

	//Section names should be sorted, alphabetically
	assert.Equal(t, sectionNames[0], "section_one", "Read section name wrong")
	assert.Equal(t, sectionNames[1], "section_three", "Read section name wrong")
	assert.Equal(t, sectionNames[2], "section_two", "Read section name wrong")

	config.SetName("section_zero")

	sectionNames = config.SectionNames()

	assert.Equal(t, len(sectionNames), 4, "Read section name array wrong")

	//Section names should be sorted, alphabetically
	assert.Equal(t, sectionNames[0], "section_one", "Read section name wrong")
	assert.Equal(t, sectionNames[1], "section_three", "Read section name wrong")
	assert.Equal(t, sectionNames[2], "section_two", "Read section name wrong")
	assert.Equal(t, sectionNames[3], "section_zero", "Read section name wrong")

}

func TestSplitSection(t *testing.T) {

	simpleIni := `first=alpha
int=32
float=3.14

[section_one]
first=raz

[section_two]
first=one
int=555
float=124.3

[section_one]
int=124
float=1222.7`

	config, err := LoadConfigurationFromReader(strings.NewReader(simpleIni))

	assert.Nil(t, err, "Sectioned configuration should load without error.")

	assert.Equal(t, config.String("first", ""), "alpha", "Read value of first wrong")
	assert.Equal(t, config.Integer("int", 0), int64(32), "Read value of int wrong")
	assert.Equal(t, config.Float("float", 0), 3.14, "Read value of float wrong")

	assert.Equal(t, config.StringFromSection("section_one", "first", ""), "raz", "Read value of first from section wrong")
	assert.Equal(t, config.IntegerFromSection("section_one", "int", 0), int64(124), "Read value of int in section wrong")
	assert.Equal(t, config.FloatFromSection("section_one", "float", 0), 1222.7, "Read value of float in section wrong")

	assert.Equal(t, config.StringFromSection("section_two", "first", ""), "one", "Read value of first from section wrong")
	assert.Equal(t, config.IntegerFromSection("section_two", "int", 0), int64(555), "Read value of int in section wrong")
	assert.Equal(t, config.FloatFromSection("section_two", "float", 0), 124.3, "Read value of float in section wrong")

	assert.Equal(t, len(config.Keys()), 3, "Section ini contains 3 fields")
	assert.Equal(t, len(config.KeysForSection("section_one")), 3, "Section in ini contains 3 fields")
	assert.Equal(t, len(config.KeysForSection("section_two")), 3, "Section in ini contains 3 fields")
}

func TestRepeatedKey(t *testing.T) {

	simpleIni := `first=alpha
first=beta`

	config, err := LoadConfigurationFromReader(strings.NewReader(simpleIni))

	assert.Nil(t, err, "Configuration should load without error.")

	assert.Equal(t, config.String("first", ""), "beta", "Read value of first wrong")

	assert.Equal(t, len(config.Keys()), 1, "ini contains 1 fields")
}

func TestDefaults(t *testing.T) {

	simpleIni := `first=alpha
third=\`

	config, err := LoadConfigurationFromReader(strings.NewReader(simpleIni))

	assert.Nil(t, err, "Configuration should load without error.")

	assert.Equal(t, config.String("second", "beta"), "beta", "Read default value of first wrong")
	assert.Equal(t, config.String("third", "gamma"), "gamma", "Read default value of too short a string")
	assert.Equal(t, config.Integer("int", 32), int64(32), "Default value of int wrong")
	assert.Equal(t, config.Float("float", 3.14), 3.14, "Default value of float wrong")
	assert.Equal(t, config.Boolean("bool", true), true, "Default value of bool wrong")

	assert.Equal(t, config.String("", "test"), "test", "Nil key should result in empty value")
	assert.Equal(t, config.Integer("", 32), int64(32), "Default value of int wrong for empty key")
	assert.Equal(t, config.Float("", 3.14), 3.14, "Default value of float wrong for empty key")
	assert.Equal(t, config.Boolean("", true), true, "Default value of bool wrong for empty key")

	assert.Equal(t, len(config.Keys()), 2, "ini contains 2 fields")
}

func TestDefaultsOnParseError(t *testing.T) {

	simpleIni := `first=alpha
int=yex
float=blap
bool=zipzap
intarray[]=blip
floatarray[]=blap`

	config, err := LoadConfigurationFromReader(strings.NewReader(simpleIni))

	assert.Nil(t, err, "Configuration should load without error.")

	assert.Equal(t, config.String("second", "beta"), "beta", "Read default value of first wrong")
	assert.Equal(t, config.Integer("int", 32), int64(32), "Default value of int wrong")
	assert.Equal(t, config.Float("float", 3.14), 3.14, "Default value of float wrong")
	assert.Equal(t, config.Boolean("bool", true), true, "Default value of bool wrong")

	assert.Nil(t, config.Integers("intarray"), "Default value of ints wrong on parse error")
	assert.Nil(t, config.Floats("floatarray"), "Default value of floats wrong on parse error")

	assert.Equal(t, len(config.Keys()), 6, "ini contains 4 fields")
}

func TestMissingArray(t *testing.T) {

	simpleIni := `first=alpha`

	config, err := LoadConfigurationFromReader(strings.NewReader(simpleIni))

	assert.Nil(t, err, "Configuration should load without error.")

	assert.Nil(t, config.Strings("second"), "Read default value of strings wrong")
	assert.Nil(t, config.Integers("int"), "Default value of ints wrong")
	assert.Nil(t, config.Floats("float"), "Default value of floats wrong")

	assert.Nil(t, config.Strings(""), "Read default value of strings wrong for empty key")
	assert.Nil(t, config.Integers(""), "Default value of ints wrong for empty key")
	assert.Nil(t, config.Floats(""), "Default value of floats wrong for empty key")

	assert.Equal(t, len(config.Keys()), 1, "ini contains 1 fields")
}

func TestDefaultsWithSection(t *testing.T) {

	simpleIni := `[section]
first=alpha`

	config, err := LoadConfigurationFromReader(strings.NewReader(simpleIni))

	assert.Nil(t, err, "Configuration should load without error.")

	assert.Equal(t, config.StringFromSection("section", "second", "beta"), "beta", "Read default value of first wrong")
	assert.Equal(t, config.IntegerFromSection("section", "int", 32), int64(32), "Default value of int wrong")
	assert.Equal(t, config.FloatFromSection("section", "float", 3.14), 3.14, "Default value of float wrong")
	assert.Equal(t, config.BooleanFromSection("section", "bool", true), true, "Default value of bool wrong")

	assert.Equal(t, config.StringFromSection("section-1", "second", "beta"), "beta", "Missing section for first wrong")
	assert.Equal(t, config.IntegerFromSection("section-1", "int", 32), int64(32), "Missing section for int wrong")
	assert.Equal(t, config.FloatFromSection("section-1", "float", 3.14), 3.14, "Missing section for float wrong")
	assert.Equal(t, config.BooleanFromSection("section-1", "bool", true), true, "Missing section for bool wrong")

	assert.Equal(t, len(config.Keys()), 0, "ini contains 0 fields")
	assert.Equal(t, len(config.KeysForSection("section")), 1, "section contains 1 field")
	assert.Nil(t, config.KeysForSection("section-1"), "missing section should have no keys")
}

type testStruct struct {
	First        string
	Second       string
	L            int64
	F64          float64
	Flag         bool
	Strings      []string
	LS           []int64
	F64s         []float64
	Missing      string
	MissingInt   int64
	MissingArray []string
	Flags        []bool
	U            uint64
	private      string
}

func TestLoadStructFile(t *testing.T) {

	simpleIni := `[section]
first=alpha
second=beta
third="gamma bamma"
fourth = 'delta'
l=-32
f64=3.14
flag=true
unflag=false
strings[]=one
strings[]=two
LS[]=1
LS[]=2
F64s[]=11.0
F64s[]=22.0
#comment
; comment`

	config, err := LoadConfigurationFromReader(strings.NewReader(simpleIni))

	assert.Nil(t, err, "Simple configuration should load without error.")

	var data testStruct

	data.MissingInt = 33
	data.Missing = "hello world"

	ok := config.DataFromSection("section", &data)

	assert.Equal(t, ok, true, "load should succeed")

	assert.Equal(t, data.First, "alpha", "Read value of first wrong")
	assert.Equal(t, data.Second, "beta", "Read value of second wrong")
	assert.Equal(t, data.L, int64(-32), "Read value of int wrong")
	assert.Equal(t, data.F64, 3.14, "Read value of float wrong")
	assert.Equal(t, data.Flag, true, "Read true wrong")
	assert.Equal(t, data.Missing, "hello world", "Read value of missing wrong")
	assert.Equal(t, data.MissingInt, int64(33), "Read false wrong")
	assert.Nil(t, data.MissingArray, "Missing array Should be nil")
	assert.Equal(t, data.private, "", "private value in struct should be ignored")

	strings := data.Strings
	assert.NotNil(t, strings, "strings should not be nil")
	assert.Equal(t, len(strings), 2, "Read wrong length of string array")
	assert.Equal(t, strings[0], "one", "Read string array wrong")
	assert.Equal(t, strings[1], "two", "Read string array wrong")

	assert.NotNil(t, data.LS, "ints should not be nil")
	assert.Equal(t, len(data.LS), 2, "Read wrong length of ints array")
	assert.Equal(t, data.LS[0], int64(1), "Read ints array wrong")
	assert.Equal(t, data.LS[1], int64(2), "Read ints array wrong")

	assert.NotNil(t, data.F64s, "floats should not be nil")
	assert.Equal(t, len(data.F64s), 2, "Read wrong length of floats array")
	assert.Equal(t, data.F64s[0], 11.0, "Read floats array wrong")
	assert.Equal(t, data.F64s[1], 22.0, "Read floats array wrong")
}

func TestLoadStructMissingSection(t *testing.T) {

	simpleIni := ``

	config, err := LoadConfigurationFromReader(strings.NewReader(simpleIni))

	assert.Nil(t, err, "Simple configuration should load without error.")

	var data testStruct

	ok := config.DataFromSection("section", &data)

	assert.Equal(t, ok, false, "section is missing so ok should be false")
}

func TestMissingSection(t *testing.T) {
	simpleIni := `[section]
first=alpha`

	config, err := LoadConfigurationFromReader(strings.NewReader(simpleIni))

	assert.Nil(t, err, "Simple configuration should load without error.")

	var data testStruct

	val := config.DataFromSection("missing_section", &data)
	assert.False(t, val)
}

func TestMissingArrayInSection(t *testing.T) {

	simpleIni := `[section]
first=alpha`

	config, err := LoadConfigurationFromReader(strings.NewReader(simpleIni))

	assert.Nil(t, err, "Configuration should load without error.")

	assert.Nil(t, config.StringsFromSection("section", "second"), "Read default value of strings wrong")
	assert.Nil(t, config.IntegersFromSection("section", "int"), "Default value of ints wrong")
	assert.Nil(t, config.FloatsFromSection("section", "float"), "Default value of floats wrong")

	assert.Nil(t, config.StringsFromSection("section-1", "second"), "Missing section for strings wrong")
	assert.Nil(t, config.IntegersFromSection("section-1", "int"), "Missing section for ints wrong")
	assert.Nil(t, config.FloatsFromSection("section-1", "float"), "Missing section for floats wrong")

	assert.Equal(t, len(config.Keys()), 0, "ini contains 0 fields")
	assert.Equal(t, len(config.KeysForSection("section")), 1, "section contains 1 field")
	assert.Nil(t, config.KeysForSection("section-1"), "missing section should have no keys")
}

func TestBadSection(t *testing.T) {

	simpleIni := `key=nope
noarray=nope
[section
key[]=one
key[]=two
noarray=three`

	_, err := LoadConfigurationFromReader(strings.NewReader(simpleIni))

	assert.NotNil(t, err, "Configuration should load with error.")
}

func TestBadKeyValue(t *testing.T) {

	simpleIni := `key=nope
noarray:nope`

	_, err := LoadConfigurationFromReader(strings.NewReader(simpleIni))

	assert.NotNil(t, err, "Configuration should load with error.")
}

func TestBadArrayAsSingle(t *testing.T) {

	simpleIni := `key=nope
noarray=nope
[section]
key[]=one
key[]=two
noarray=three`

	config, err := LoadConfigurationFromReader(strings.NewReader(simpleIni))

	assert.Nil(t, err, "Configuration should load without error.")

	assert.Equal(t, config.StringFromSection("section", "key", "default"), "default", "Read default value of strings wrong")
}

func TestBadFile(t *testing.T) {
	const filepath = "/no.such.dir/xxx.no-such-file.txt"
	config, err := LoadConfiguration(filepath)

	assert.NotNil(t, err, "No valid file is an error.")
	assert.True(t, os.IsNotExist(err), "No valid file errors is of expected type.")
	assert.Nil(t, config, "Configuration should be nil.")

}

func TestNullValuesInGet(t *testing.T) {

	assert.Nil(t, get(nil, "foo"), "Configuration should be nil.")

}

func TestStringEscape(t *testing.T) {

	simpleIni := `first=\n\t\rhello`

	config, err := LoadConfigurationFromReader(strings.NewReader(simpleIni))

	assert.Nil(t, err, "Simple configuration should load without error.")

	assert.Equal(t, config.String("first", ""), "\n\t\rhello", "Read value of first wrong")

	assert.Equal(t, len(config.Keys()), 1, "ini contains 1 fields")
}

func TestBadStringArray(t *testing.T) {

	simpleIni := `first[]=\`

	config, err := LoadConfigurationFromReader(strings.NewReader(simpleIni))

	assert.Nil(t, err, "Simple configuration should load without error.")
	assert.Nil(t, config.Strings("first"), "Read value of first wrong")
}

func BenchmarkLoadConfiguration(b *testing.B) {

	simpleIni := `first=alpha
int=32
float=3.14

[section_one]
first=raz

[section_two]
first=one
int=555
float=124.3

[section_one]
int=124
float=1222.7`

	b.ReportAllocs()
	r := strings.NewReader(simpleIni)
	for i := 0; i < b.N; i++ {
		r.Seek(0, os.SEEK_SET)
		_, err := LoadConfigurationFromReader(r)
		if err != nil {
			b.Fatal(err)
		}
	}
}


text:
"use strict";
/**
 * Compare two given ontologies
 * listing added/missing units etc
 *
 */

// set input
const SOURCE = 'OM',
      TARGET = 'OM2';

// includes
const OntoStore = require( './../util/OntoStore' );

// get a list of types
const TYPES = OntoStore.getSemanticTypes()
                .map( (t) => {
                  return t[0].toUpperCase() + t.slice( 1 );
                });

// process each type
const result = {};
for( let type of TYPES ) {

  // get the respective dataset
  let data = OntoStore.getResult( 'map' + type );

  // init results
  result[ type ] = { added: [], removed: [] };

  // walk through the data
  for( let synSet of data ) {

    // get synonyms
    let syns = synSet.getSynonyms();

    // check, if both source and target are present
    let hasTarget = [],
        hasSource = [];
    for( let syn of syns ) {
      if (syn.getOntology() == TARGET){
        hasTarget.push( syn );
      };
      if (syn.getOntology() == SOURCE){
        hasSource.push( syn );
      }
    }

    // is there a difference?
    if( (hasTarget.length == 0) != (hasSource.length == 0) ) {

      // where to add
      let where = (hasTarget.length != 0)
                    ? result[ type ].added
                    : result[ type ].removed;

      // what to add
      let what  = (hasTarget.length != 0)
                    ? hasTarget
                    : hasSource;

      // add an entry
      where.push({
        label:  synSet.getDisplayLabel(),
        uris:   what.map( (e) => e.getURI() )
      });

    }
  }

}

// sort results
Object.keys( result )
      .forEach( (type) => {

        result[type].added.sort( (a,b) => a.uris[0].localeCompare( b.uris[0] ) );
        result[type].removed.sort( (a,b) => a.uris[0].localeCompare( b.uris[0] ) );

      })

// output result
console.log( JSON.stringify( result, null, 2 ) );

redpajama_set_name: RedPajamaGithub


text:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.debnil</groupId>
    <artifactId>mp3-panda</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>
        <dependency>
            <groupId>org</groupId>
            <artifactId>jaudiotagger</artifactId>
            <version>2.0.3</version>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>18.0</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-asl</artifactId>
            <version>1.9.13</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>Mp3Panda</finalName>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
        </resources>

        <!-- To define the plugin version in your parent POM -->
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>com.zenjava</groupId>
                    <artifactId>javafx-maven-plugin</artifactId>
                    <version>8.1.3</version>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.3</version>
                </plugin>
            </plugins>
        </pluginManagement>

        <!-- To use the plugin goals in your POM or parent POM -->
        <plugins>
            <plugin>
                <groupId>com.zenjava</groupId>
                <artifactId>javafx-maven-plugin</artifactId>
                <version>8.1.3</version>
                <configuration>
                    <mainClass>org.debnil.mp3panda.app.Main</mainClass>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>


text:
const express = require('express');
const app = express();
const path = require('path');
const httpProxy = require('http-proxy');

const bodyparser = require("body-parser");
const cookieparser = require("cookie-parser");

const mongoose = require("mongoose");
mongoose.connect("mongodb://admin:moonstarmagicaardvark@ds019698.mlab.com:19698/pinterest");

var User = require("./src/models/User.js");
var Pin = require("./src/models/Pin.js");

const isProduction = process.env.NODE_ENV === 'production';
const port = isProduction ? process.env.PORT || 4000 : 3000;
const publicPath = isProduction ? path.resolve(__dirname, 'build') : path.resolve(__dirname, 'src');

app.set("view options", {layout: false});
app.use(bodyparser.json());
app.use(bodyparser.urlencoded({extended: true}));
app.use(cookieparser());
app.use(express.static(publicPath));

// We only want to run the workflow when not in production
if (!isProduction) {

    const Webpack = require('webpack');
    const WebpackDevServer = require('webpack-dev-server');
    const webpackConfig = require('./webpack.config.js');
    const proxy = httpProxy.createProxyServer();

    // First we fire up Webpack an pass in the configuration we
    // created
    var bundleStart = null;
    const compiler = Webpack(webpackConfig);

    // We give notice in the terminal when it starts bundling and
    // set the time it started
    compiler.plugin('compile', function() {
        console.log('Bundling...');
        bundleStart = Date.now();
    });

    // We also give notice when it is done compiling, including the
    // time it took. Nice to have
    compiler.plugin('done', function() {
        console.log('Bundled in ' + (Date.now() - bundleStart) + 'ms!');
    });

    const bundler = new WebpackDevServer(compiler, {

        // We need to tell Webpack to serve our bundled application
        // from the build path. When proxying:
        // http://localhost:3000/build -> http://localhost:8080/build
        publicPath: '/build/',

        // Configure hot replacement
        hot: true,

        historyApiFallback: true,

        // The rest is terminal configurations
        quiet: false,
        noInfo: true,
        stats: {
            colors: true
        }
    });

    // We fire up the development server and give notice in the terminal
    // that we are starting the initial bundle
    bundler.listen(8080, 'localhost', function () {
        console.log('Bundling project, please wait...');
    });

    // Any requests to localhost:3000/build is proxied
    // to webpack-dev-server
    app.all('/build/*', function (req, res) {
        proxy.web(req, res, {
            target: 'http://localhost:8080'
        });
    });

    // It is important to catch any errors from the proxy or the
    // server will crash. An example of this is connecting to the
    // server when webpack is bundling
    proxy.on('error', function (e) {
        console.log('Could not connect to proxy, please try again...');
    });
}

app.all('/', function (req, res) {
    res.sendFile(`${publicPath}/index.html`);
});

app.post("/login", function(req, res) {
    var un = req.body.username;
    var pw = req.body.password;

    /*
     * response: 1 = success
     * response: 2 = wrong password
     * response: 3 = username not found
     * */

    User.findOne({
        username: un
    }, function(err, doc) {
        if(err) throw err;
        if(doc) {
            if (doc.password === pw) {
                res.json({response: 1});
            } else {
                res.json({response: 2});
            }
        } else {
            res.json({response: 3});
        }
    });
});

app.post("/signup", function(req, res) {
    var un = req.body.username;
    var pw = req.body.password;

    /*
     * response: 1 = user signed up
     * response: 2 = this account name already used
     */

    User.findOne({
        username: un
    }, function(err, doc) {
        if(err) throw err;
        if(doc) {
            res.json({response: 2});
        } else {
            var user = new User({
                username: un,
                password: pw,
                pins: []
            });
            console.log(user);
            user.save();
            res.json({response: 1});
        }
    })
});

app.get("/logout", function(req, res) {

});

app.get("/recent", function(req, res) {
    Pin.find({}).sort({date: -1}).limit(10).exec(function(err, doc) {
        if(err) throw err;
        res.json(doc);
    })
});

app.get("/user/:username", function(req, res) {
    var pins = [];
    User.findOne({
        username: req.params.username
    }).sort({date: -1}).exec(function (err, doc) {
        if (err) throw err;
        doc.pins.map(function (val) {
            Pin.findOne({
                _id: val
            }, function (err, doc2) {
                if (err) throw err;
                pins.push(doc2);
                if (pins.length === doc.pins.length) {
                    res.json(pins);
                }
            });
        });
    });
});

app.post("/user/:username/new", function(req, res) {
    var un = req.params.username;
    var src = req.body.src;
    var title = req.body.title;

    /*
     * response: 1 = added pin
     * response: 2 = pin already exists for user
     */
    Pin.findOne({
        author: un,
        src: src
    }, function(err, doc2) {
        if(err) throw err;
        if(doc2) {
            res.json({response: 2});
        } else {
            var pin = new Pin({
                title: title,
                author: un,
                src: src
            });

            pin.save(function(err, p) {
                if(err) throw err;
                User.update({
                    username: un
                }, {
                    $push: {
                        pins: p._id
                    }
                }, function(err, doc) {
                    if(err) throw err;
                });
            });
            res.json({response: 1});
        }
    })
});

app.listen(port, function () {
    console.log('Server running on port ' + port);
});


text:
namespace simple_layer_namespace
{

class SimpleLayer : public costmap_2d::Layer
{
public:
  SimpleLayer();

  virtual void onInitialize();
  virtual void updateBounds(double robot_x, double robot_y, double robot_yaw, double* min_x, double* min_y, double* max_x,
                             double* max_y);
  virtual void updateCosts(costmap_2d::Costmap2D& master_grid, int min_i, int min_j, int max_i, int max_j);

private:
  void reconfigureCB(costmap_2d::GenericPluginConfig &config, uint32_t level);

  double mark_x_, mark_y_;
  dynamic_reconfigure::Server<costmap_2d::GenericPluginConfig> *dsrv_;
};
}
#endif


text:
package com.sparrow.service.impl;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import com.sparrow.entity.mongo.User;
import com.sparrow.repository.UserRepository;
import com.sparrow.service.iface.IUserService;
import com.sparrow.vo.UserVo;

/**
 * 用户业务逻辑实现类
 * @author       Jay
 * @time         2015年5月21日
 */
@Service
public class UserServiceImpl implements IUserService {

	@Autowired
	private UserRepository userRepository;

	@Autowired
	private MongoTemplate mongoTemplate;

	@Override
	public String hello() {
		throw new IllegalArgumentException("异常测试");
//		User user = new User("Jay", "1234");
//		userRepository.save(user);
//		return "Hello Jay";
	}

	@Override
	public void addUser(UserVo userVo) {
		User user = new User(userVo.getUsername(), userVo.getPassword());
		userRepository.save(user);
	}

	@Override
	public void updateUser(UserVo userVo) {
		// TODO Auto-generated method stub

	}

	@Override
	public UserVo findUserByUserId(String userId) {
		User user = userRepository.findOne(userId);
		UserVo userVo;
		if(null == user){
			userVo = new UserVo();
		}else{
			userVo = new UserVo(user.getUsername(),user.getPassword());
		}
		return userVo;
	}

	@Override
	public UserVo findUserByUserName(String username) {
		User user = userRepository.findByUsername(username);
		UserVo userVo;
		if(null == user){
			userVo = new UserVo();
		}else{
			userVo = new UserVo(user.getUsername(),user.getPassword());
		}
		return userVo;
	}

	@Override
	public void deleteUser(String userId) {
		userRepository.delete(userId);
	}

	@Override
	public List<UserVo> findUsersOrder() {
		Query query=new Query();
		//query.addCriteria(Criteria.where("mobile").is(mobile));
		query.with(new Sort(Sort.Direction.DESC,"username"));
		List<User> list = mongoTemplate.find(query, User.class);
		//query.skip((page-1)*pageSize);
		//query.limit(pageSize);
		List<UserVo> userList = new ArrayList<UserVo>();
		for(User user : list){
			UserVo userVo = new UserVo();
			userVo.setUsername(user.getUsername());
			userList.add(userVo);
		}
		return userList;
	}

}


text:
using System;

namespace PcapDotNet.Base
{
    /// <summary>
    /// Useful functions for sequences of bits.
    /// </summary>
    public static class BitSequence
    {
        /// <summary>
        /// Casts a bit to a byte.
        /// True becomes 1 and false becomes 0.
        /// </summary>
        /// <param name="value">Bit 7 of the byte.</param>
        /// <returns>1 for true, 0 for false.</returns>
        public static byte ToByte(this bool value)
        {
            return value ? (byte)1 : (byte)0;
        }

        /// <summary>
        /// Merges 2 bits to a byte.
        /// Bits should be arranged from the most significant to the least.
        /// </summary>
        /// <param name="value1">Bit 6 of the byte.</param>
        /// <param name="value2">Bit 7 of the byte.</param>
        /// <returns>A byte with the 2 least significant bits determined by the input.</returns>
        public static byte Merge(bool value1, bool value2)
        {
            return (byte)((value1.ToByte() << 1) | value2.ToByte());
        }

        /// <summary>
        /// Merges 3 bits to a byte.
        /// Bits should be arranged from the most significant to the least.
        /// </summary>
        /// <param name="value1">Bit 5 of the byte.</param>
        /// <param name="value2">Bit 6 of the byte.</param>
        /// <param name="value3">Bit 7 of the byte.</param>
        /// <returns>A byte with the 3 least significant bits determined by the input.</returns>
        public static byte Merge(bool value1, bool value2, bool value3)
        {
            return (byte)((Merge(value1, value2) << 1) | value3.ToByte());
        }

        /// <summary>
        /// Merges 4 bits to a byte.
        /// Bits should be arranged from the most significant to the least.
        /// </summary>
        /// <param name="value1">Bit 4 of the byte.</param>
        /// <param name="value2">Bit 5 of the byte.</param>
        /// <param name="value3">Bit 6 of the byte.</param>
        /// <param name="value4">Bit 7 of the byte.</param>
        /// <returns>A byte with the 4 least significant bits determined by the input.</returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1025:ReplaceRepetitiveArgumentsWithParamsArray")]
        public static byte Merge(bool value1, bool value2, bool value3, bool value4)
        {
            return (byte)((Merge(value1, value2, value3) << 1) | value4.ToByte());
        }

        /// <summary>
        /// Merges 5 bits to a byte.
        /// Bits should be arranged from the most significant to the least.
        /// </summary>
        /// <param name="value1">Bit 3 of the byte.</param>
        /// <param name="value2">Bit 4 of the byte.</param>
        /// <param name="value3">Bit 5 of the byte.</param>
        /// <param name="value4">Bit 6 of the byte.</param>
        /// <param name="value5">Bit 7 of the byte.</param>
        /// <returns>A byte with the 5 least significant bits determined by the input.</returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1025:ReplaceRepetitiveArgumentsWithParamsArray")]
        public static byte Merge(bool value1, bool value2, bool value3, bool value4, bool value5)
        {
            return (byte)((Merge(value1, value2, value3, value4) << 1) | value5.ToByte());
        }

        /// <summary>
        /// Merges 6 bits to a byte.
        /// Bits should be arranged from the most significant to the least.
        /// </summary>
        /// <param name="value1">Bit 2 of the byte.</param>
        /// <param name="value2">Bit 3 of the byte.</param>
        /// <param name="value3">Bit 4 of the byte.</param>
        /// <param name="value4">Bit 5 of the byte.</param>
        /// <param name="value5">Bit 6 of the byte.</param>
        /// <param name="value6">Bit 7 of the byte.</param>
        /// <returns>A byte with the 6 least significant bits determined by the input.</returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1025:ReplaceRepetitiveArgumentsWithParamsArray")]
        public static byte Merge(bool value1, bool value2, bool value3, bool value4, bool value5, bool value6)
        {
            return (byte)((Merge(value1, value2, value3, value4, value5) << 1) | value6.ToByte());
        }

        /// <summary>
        /// Merges 7 bits to a byte.
        /// Bits should be arranged from the most significant to the least.
        /// </summary>
        /// <param name="value1">Bit 1 of the byte.</param>
        /// <param name="value2">Bit 2 of the byte.</param>
        /// <param name="value3">Bit 3 of the byte.</param>
        /// <param name="value4">Bit 4 of the byte.</param>
        /// <param name="value5">Bit 5 of the byte.</param>
        /// <param name="value6">Bit 6 of the byte.</param>
        /// <param name="value7">Bit 7 of the byte.</param>
        /// <returns>A byte with the 7 least significant bits determined by the input.</returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1025:ReplaceRepetitiveArgumentsWithParamsArray")]
        public static byte Merge(bool value1, bool value2, bool value3, bool value4, bool value5, bool value6, bool value7)
        {
            return (byte)((Merge(value1, value2, value3, value4, value5, value6) << 1) | value7.ToByte());
        }

        /// <summary>
        /// Merges 8 bits to a byte.
        /// Bits should be arranged from the most significant to the least.
        /// </summary>
        /// <param name="value1">Bit 0 of the byte.</param>
        /// <param name="value2">Bit 1 of the byte.</param>
        /// <param name="value3">Bit 2 of the byte.</param>
        /// <param name="value4">Bit 3 of the byte.</param>
        /// <param name="value5">Bit 4 of the byte.</param>
        /// <param name="value6">Bit 5 of the byte.</param>
        /// <param name="value7">Bit 6 of the byte.</param>
        /// <param name="value8">Bit 7 of the byte.</param>
        /// <returns>A byte whose bits are determined by the input.</returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1025:ReplaceRepetitiveArgumentsWithParamsArray")]
        public static byte Merge(bool value1, bool value2, bool value3, bool value4, bool value5, bool value6, bool value7, bool value8)
        {
            return (byte)((Merge(value1, value2, value3, value4, value5, value6, value7) << 1) | value8.ToByte());
        }

        /// <summary>
        /// Merges 2 bytes to a ushort.
        /// Bytes should be arranged from the most significant to the least.
        /// </summary>
        /// <param name="value1">Bits 0-7 of the ushort.</param>
        /// <param name="value2">Bits 8-15 of the ushort.</param>
        /// <returns>A ushort whose bits are determined by the input.</returns>
        public static ushort Merge(byte value1, byte value2)
        {
            return (ushort)((value1 << 8) | value2);
        }

        /// <summary>
        /// Merges 3 bytes to a UInt24.
        /// Bytes should be arranged from the most significant to the least.
        /// </summary>
        /// <param name="value1">Bits 0-7 of the UInt24.</param>
        /// <param name="value2">Bits 8-15 of the UInt24.</param>
        /// <param name="value3">Bits 16-23 of the UInt24.</param>
        /// <returns>A UInt24 whose bits are determined by the input.</returns>
        public static UInt24 Merge(byte value1, byte value2, byte value3)
        {
            return (UInt24)Merge(0, value1, value2, value3);
        }

        /// <summary>
        /// Merges 4 bytes to a uint.
        /// Bytes should be arranged from the most significant to the least.
        /// </summary>
        /// <param name="value1">Bits 0-7 of the uint.</param>
        /// <param name="value2">Bits 8-15 of the uint.</param>
        /// <param name="value3">Bits 16-23 of the uint.</param>
        /// <param name="value4">Bits 24-31 of the uint.</param>
        /// <returns>A uint whose bits are determined by the input.</returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1025:ReplaceRepetitiveArgumentsWithParamsArray")]
        public static uint Merge(byte value1, byte value2, byte value3, byte value4)
        {
            return Merge(Merge(value1, value2), Merge(value3, value4));
        }

        /// <summary>
        /// Merges 6 bytes to a UInt48.
        /// Bytes should be arranged from the most significant to the least.
        /// </summary>
        /// <param name="value1">Bits 0-7 of the UInt48.</param>
        /// <param name="value2">Bits 8-15 of the UInt48.</param>
        /// <param name="value3">Bits 16-23 of the UInt48.</param>
        /// <param name="value4">Bits 24-31 of the UInt48.</param>
        /// <param name="value5">Bits 32-39 of the UInt48.</param>
        /// <param name="value6">Bits 40-47 of the UInt48.</param>
        /// <returns>A UInt48 whose bits are determined by the input.</returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1025:ReplaceRepetitiveArgumentsWithParamsArray")]
        public static UInt48 Merge(byte value1, byte value2, byte value3, byte value4, byte value5, byte value6)
        {
            return (UInt48)Merge(0, 0, value1, value2, value3, value4, value5, value6);
        }

        /// <summary>
        /// Merges 8 bytes to a ulong.
        /// Bytes should be arranged from the most significant to the least.
        /// </summary>
        /// <param name="value1">Bits 0-7 of the ulong.</param>
        /// <param name="value2">Bits 8-15 of the ulong.</param>
        /// <param name="value3">Bits 16-23 of the ulong.</param>
        /// <param name="value4">Bits 24-31 of the ulong.</param>
        /// <param name="value5">Bits 32-39 of the ulong.</param>
        /// <param name="value6">Bits 40-47 of the ulong.</param>
        /// <param name="value7">Bits 48-55 of the ulong.</param>
        /// <param name="value8">Bits 56-63 of the ulong.</param>
        /// <returns>A ulong whose bits are determined by the input.</returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1025:ReplaceRepetitiveArgumentsWithParamsArray")]
        public static ulong Merge(byte value1, byte value2, byte value3, byte value4, byte value5, byte value6, byte value7, byte value8)
        {
            return Merge(Merge(value1, value2, value3, value4), Merge(value5, value6, value7, value8));
        }

        /// <summary>
        /// Merges 16 bytes to a UInt128.
        /// Bytes should be arranged from the most significant to the least.
        /// </summary>
        /// <param name="value1">Bits 0-7 of the UInt128.</param>
        /// <param name="value2">Bits 8-15 of the UInt128.</param>
        /// <param name="value3">Bits 16-23 of the UInt128.</param>
        /// <param name="value4">Bits 24-31 of the UInt128.</param>
        /// <param name="value5">Bits 32-39 of the UInt128.</param>
        /// <param name="value6">Bits 40-47 of the UInt128.</param>
        /// <param name="value7">Bits 48-55 of the UInt128.</param>
        /// <param name="value8">Bits 56-63 of the UInt128.</param>
        /// <param name="value9">Bits 64-71 of the UInt128.</param>
        /// <param name="value10">Bits 72-79 of the UInt128.</param>
        /// <param name="value11">Bits 80-87 of the UInt128.</param>
        /// <param name="value12">Bits 88-95 of the UInt128.</param>
        /// <param name="value13">Bits 96-103 of the UInt128.</param>
        /// <param name="value14">Bits 104-111 of the UInt128.</param>
        /// <param name="value15">Bits 112-119 of the UInt128.</param>
        /// <param name="value16">Bits 120-127 of the UInt128.</param>
        /// <returns>A UInt128 whose bits are determined by the input.</returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1025:ReplaceRepetitiveArgumentsWithParamsArray")]
        public static UInt128 Merge(byte value1, byte value2, byte value3, byte value4, byte value5, byte value6, byte value7, byte value8,
                                    byte value9, byte value10, byte value11, byte value12, byte value13, byte value14, byte value15, byte value16)
        {
            return Merge(Merge(value1, value2, value3, value4, value5, value6, value7, value8),
                         Merge(value9, value10, value11, value12, value13, value14, value15, value16));
        }

        /// <summary>
        /// Merges 2 ushort to a uint.
        /// ushorts should be arranged from the most significant to the least.
        /// </summary>
        /// <param name="value1">Bits 0-15 of the uint.</param>
        /// <param name="value2">Bits 16-31 of the uint.</param>
        /// <returns>A uint whose bits are determined by the input.</returns>
        public static uint Merge(ushort value1, ushort value2)
        {
            return (uint)((value1 << 16) | value2);
        }

        /// <summary>
        /// Merges a byte and a ushort to a UInt24.
        /// Values should be arranged from the most significant to the least.
        /// </summary>
        /// <param name="value1">Bits 0-7 of the UInt24.</param>
        /// <param name="value2">Bits 8-23 of the UInt24.</param>
        /// <returns>A UInt24 whose bits are determined by the input.</returns>
        public static UInt24 Merge(byte value1, ushort value2)
        {
            return (UInt24)Merge(0, value1, value2);
        }

        /// <summary>
        /// Merges a ushort and 2 bytes to a uint.
        /// Values should be arranged from the most significant to the least.
        /// </summary>
        /// <param name="value1">Bits 0-15 of the uint.</param>
        /// <param name="value2">Bits 16-23 of the uint.</param>
        /// <param name="value3">Bits 24-31 of the uint.</param>
        /// <returns>A uint whose bits are determined by the input.</returns>
        public static uint Merge(ushort value1, byte value2, byte value3)
        {
            return Merge(value1, Merge(value2, value3));
        }

        /// <summary>
        /// Merges a ushort and 2 bytes to a uint.
        /// Values should be arranged from the most significant to the least.
        /// </summary>
        /// <param name="value1">Bits 0-7 of the uint.</param>
        /// <param name="value2">Bits 8-23 of the uint.</param>
        /// <param name="value3">Bits 24-31 of the uint.</param>
        /// <returns>A uint whose bits are determined by the input.</returns>
        public static uint Merge(byte value1, ushort value2, byte value3)
        {
            return (uint)((value1 << 24) | (value2 << 8) | value3);
        }

        /// <summary>
        /// Merges a ushort and 2 bytes to a uint.
        /// Values should be arranged from the most significant to the least.
        /// </summary>
        /// <param name="value1">Bits 0-7 of the uint.</param>
        /// <param name="value2">Bits 8-15 of the uint.</param>
        /// <param name="value3">Bits 16-31 of the uint.</param>
        /// <returns>A uint whose bits are determined by the input.</returns>
        public static uint Merge(byte value1, byte value2, ushort value3)
        {
            return Merge(Merge(value1, value2), value3);
        }

        /// <summary>
        /// Merges a uint and 2 ushorts to a ulong.
        /// values should be arranged from the most significant to the least.
        /// </summary>
        /// <param name="value1">Bits 0-31 of the ulong.</param>
        /// <param name="value2">Bits 32-47 of the ulong.</param>
        /// <param name="value3">Bits 48-63 of the ulong.</param>
        /// <returns>A ulong whose bits are determined by the input.</returns>
        public static ulong Merge(uint value1, ushort value2, ushort value3)
        {
            return Merge(value1, Merge(value2, value3));
        }

        /// <summary>
        /// Merges 2 uints to a ulong.
        /// uints should be arranged from the most significant to the least.
        /// </summary>
        /// <param name="value1">Bits 0-31 of the ulong.</param>
        /// <param name="value2">Bits 32-63 of the ulong.</param>
        /// <returns>A ulong whose bits are determined by the input.</returns>
        public static ulong Merge(uint value1, uint value2)
        {
            return (((ulong)value1) << 32) | value2;
        }

        /// <summary>
        /// Merges 2 ulongs to a UInt128.
        /// ulongs should be arranged from the most significant to the least.
        /// </summary>
        /// <param name="value1">Bits 0-63 of the UInt128.</param>
        /// <param name="value2">Bits 64-127 of the UInt128.</param>
        /// <returns>A UInt128 whose bits are determined by the input.</returns>
        public static UInt128 Merge(ulong value1, ulong value2)
        {
            return new UInt128(value1, value2);
        }
    }
}


text:
namespace arb {

using arb::util::pprintf;

static std::string msize_string(msize_t x) {
    return x==mnpos? "mnpos": pprintf("{}", x);
}

invalid_mlocation::invalid_mlocation(mlocation loc):
    morphology_error(pprintf("invalid mlocation {}", loc)),
    loc(loc)
{}

no_such_branch::no_such_branch(msize_t bid):
    morphology_error(pprintf("no such branch id {}", msize_string(bid))),
    bid(bid)
{}

no_such_segment::no_such_segment(msize_t id):
    arbor_exception(pprintf("no such segment {}", id)),
    sid(id)
{}

invalid_mcable::invalid_mcable(mcable cable):
    morphology_error(pprintf("invalid mcable {}", cable)),
    cable(cable)
{}

invalid_mcable_list::invalid_mcable_list():
    morphology_error("bad mcable_list")
{}

invalid_segment_parent::invalid_segment_parent(msize_t parent, msize_t tree_size):
    morphology_error(pprintf("invalid segment parent {} for a segment tree of size {}", msize_string(parent), tree_size)),
    parent(parent),
    tree_size(tree_size)
{}

duplicate_stitch_id::duplicate_stitch_id(const std::string& id):
    morphology_error(pprintf("duplicate stitch id {}", id)),
    id(id)
{}

no_such_stitch::no_such_stitch(const std::string& id):
    morphology_error(pprintf("no such stitch id {}", id)),
    id(id)
{}

missing_stitch_start::missing_stitch_start(const std::string& id):
    morphology_error(pprintf("require proximal point for stitch id {}", id)),
    id(id)
{}

invalid_stitch_position::invalid_stitch_position(const std::string& id, double along):
    morphology_error(pprintf("invalid stitch position {} on stitch {}", along, id)),
    id(id),
    along(along)
{}

label_type_mismatch::label_type_mismatch(const std::string& label):
    morphology_error(pprintf("label \"{}\" is already bound to a different type of object", label)),
    label(label)
{}

incomplete_branch::incomplete_branch(msize_t bid):
    morphology_error(pprintf("insufficent samples to define branch id {}", msize_string(bid))),
    bid(bid)
{}

unbound_name::unbound_name(const std::string& name):
    morphology_error(pprintf("no definition for '{}'", name)),
    name(name)
{}

circular_definition::circular_definition(const std::string& name):
    morphology_error(pprintf("definition of '{}' requires a definition for '{}'", name, name)),
    name(name)
{}

} // namespace arb


text:
<?xml version="1.0" encoding="UTF-8"?>

<!-- Statistical Detector Rule Logic... -->
    <!--
            Defines the protocols detection rules.
            Supported names:
            "Transport"                       - Transport type 1 - TCP, 2 - UDP (32-bit unsigned)
            "FirstBytesHistogramUp"           - First packet bytes histogram up (vector, size should be 256)
            "FirstBytesHistogramDown"         - First packet bytes histogram down (vector, size should be 256)
            "DirectionChangeRate"             - Direction changing frequency (float-point)
            "BytesUpDownRatio"                - Bytes up percentage (float-point)
            "PacketsUpDownRatio"              - Packets up percentage (float-point)
            "AvgPacketSize"                   - Average packet size (32-bit unsigned)
            "VarPacketSize"                   - Packet size variance (32-bit unsigned)
            "FirstBytesHash"                  - Hash of the first bytes (32-bit unsigned)
            "HashEqualityRating"              - Rating, calculated on packets with equal first bytes hashes (32-bit unsigned)
            "FirstPacketEntropy"              - First packet entropy (floating-point)
            "AvgInterPacketDelay"             - Average inter-packet delay (floating-point)
            "VarInterPacketDelay"             - Inter-packet delay variance (floating-point)
            "FirstPacketSize"                 - First packet size (32-bit unsigned)

            about histograms                  - can contain full histogram vector (256 semicolon-separated values) or approximation
                                                data vector (3 semicolon-separated values or ranges or groups of ranges)
                                                In case of approximation data vector weight attribute must be vector of
                                                comma-separated values.
            Example of approximation data vector
                <attribute name="FirstBytesHistogramUp" weight="1,0,1">0-0.01;0;0.7-0.8,0.4-0.5</attribute>
                in this example approximation coefficient k will be checked against range 0-0.01 with weight 1
                                                          b will not be checked (weight is 0)
                                                          p will be checked against ranges 0.7-0.8 or 0.4-0.5 with weight 1

            weight                            - sets the weight for the particular attribute. If weight = 0 attribute doesn't affect
                                                the results of the detection. Value of weight < 0 defines the attributes, that must be
                                                checked for exact match
     -->
<stat_detection>
    <protocol_models>
        <protocol_model name="skype">
            <rules>
                <!-- Common rule for UDP-based skype -->
                <rule>
                    <attribute name="Transport" weight="-1">2</attribute>
                    <attribute name="HashEqualityRating">5-50</attribute>
                    <attribute name="FirstPacketEntropy">4-8</attribute>
                    <attribute name="AvgInterPacketDelay">0-1</attribute>
                    <attribute name="VarInterPacketDelay">0-1</attribute>
                    <attribute name="FirstBytesHistogramUp" weight="1,0,1">0.03-0.06;0;0.6-0.9</attribute>
                </rule>
                <!-- Exceptional rule for UDP skype with big entropy and big hash equality, probably it's wrong -->
                <rule>
                    <attribute name="Transport" weight="-1">2</attribute>
                    <attribute name="HashEqualityRating">5-75</attribute>
                    <attribute name="FirstPacketEntropy">6-8</attribute>
                    <attribute name="FirstBytesHistogramUp" weight="1,0,1">0.03-0.06;0;0.6-0.9</attribute>
                </rule>
                <!-- Common rule for TCP-based skype with similar packets up/down ratio -->
                <rule>
                    <attribute name="Transport" weight="-1">1</attribute>
                    <attribute name="HashEqualityRating">0-5</attribute>
                    <attribute name="FirstPacketEntropy">5-8</attribute>
                    <attribute name="PacketsUpDownRatio">40-60</attribute>
                    <attribute name="FirstBytesHistogramUp" weight="1,1,1">0.01-0.04;-0.2--0.21;0.4-0.8</attribute>
                    <attribute name="FirstBytesHistogramDown" weight="1,1,1">0.01-0.04;-0.2--0.21;0.4-0.8</attribute>
                </rule>
                <!-- Common rule for TCP-based skype with similar volumes up/down ratio -->
                <rule>
                    <attribute name="Transport" weight="-1">1</attribute>
                    <attribute name="HashEqualityRating">0-5</attribute>
                    <attribute name="FirstPacketEntropy">5-8</attribute>
                    <attribute name="BytesUpDownRatio">40-60</attribute>
                    <attribute name="FirstBytesHistogramUp" weight="1,1,1">0.01-0.04;-0.2--0.21;0.4-0.8</attribute>
                    <attribute name="FirstBytesHistogramDown" weight="1,1,1">0.01-0.04;-0.2--0.21;0.4-0.8</attribute>
                </rule>
            </rules>
        </protocol_model>
        <protocol_model name="bittorrent">
            <rules>
                <!-- Common rule for UDP-based bittorrent -->
                <rule>
                    <attribute name="Transport" weight="-1">2</attribute>
                    <attribute name="HashEqualityRating">75-100</attribute>
                    <attribute name="FirstPacketEntropy">5-8</attribute>
                    <attribute name="AvgInterPacketDelay">0-0.5</attribute>
                    <attribute name="VarInterPacketDelay">0-0.5</attribute>
                    <attribute name="FirstPacketSize">50-250</attribute>
                    <attribute name="AvgPacketSize">50-250</attribute>
                    <attribute name="VarPacketSize">0-100</attribute>
                    <attribute name="FirstBytesHistogramUp" weight="1,0,1">0.05-0.06;0;0.7-0.8</attribute>
                </rule>
                <!-- Rule for UDP-based bittorrent where clients are exchanging service information using single packet flow -->
                <rule>
                    <attribute name="Transport" weight="-1">2</attribute>
                    <attribute name="HashEqualityRating" weight="-1">0</attribute>
                    <attribute name="FirstPacketEntropy">5-8</attribute>
                    <attribute name="FirstPacketSize">50-250</attribute>
                    <attribute name="FirstBytesHistogramUp" weight="1,0,1">0.05-0.06;0;0.7-0.8</attribute>
                </rule>
            </rules>
        </protocol_model>
    </protocol_models>
</stat_detection>


text:
<?php

namespace Danack\Console\Tests\Tester;

use Danack\Console\Application;
use Danack\Console\Output\Output;
use Danack\Console\Tester\ApplicationTester;
use Auryn\Provider;
use Danack\Console\Command\ParsedCommand;

class ApplicationTesterTest extends \PHPUnit_Framework_TestCase
{
    protected $application;

    /** @var  ApplicationTester */
    protected $tester;

    /** @var  ParsedCommand */
    protected $parsedCommand;

    /** @var  Provider */
    protected $provider;

    protected function setUp()
    {
        $this->application = new Application();
        $this->application->setAutoExit(false);
        $callable = function (Output $output) {
            $output->writeln('foo');
        };
        $this->application->register('foo', $callable)
            ->addArgument('foo');

        $this->tester = new ApplicationTester($this->application);
        $this->provider = new Provider();

        $this->parsedCommand = $this->tester->run(array('command' => 'foo', 'foo' => 'bar'), array('interactive' => false, 'decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE));
    }

    protected function tearDown()
    {
        $this->application = null;
        $this->tester = null;
    }

    public function testRun()
    {
        $this->assertFalse($this->tester->getInput()->isInteractive(), '->execute() takes an interactive option');
        $this->assertFalse($this->tester->getOutput()->isDecorated(), '->execute() takes a decorated option');
        $this->assertEquals(Output::VERBOSITY_VERBOSE, $this->tester->getOutput()->getVerbosity(), '->execute() takes a verbosity option');
    }

    public function testGetInput()
    {
        $this->assertEquals('bar', $this->tester->getInput()->getArgument('foo'), '->getInput() returns the current input instance');
    }

    public function testGetOutput()
    {
        $output = $this->tester->getOutput();
        $this->provider->alias(
            'Danack\Console\Output\Output',
            get_class($output)
        );

        $this->provider->share($output);
        $callable = $this->parsedCommand->getCallable();
        $this->provider->execute($callable, []);

        rewind($this->tester->getOutput()->getStream());
        $contents = stream_get_contents($this->tester->getOutput()->getStream());
        $this->assertEquals('foo'.PHP_EOL, $contents, '->getOutput() returns the current output instance');
    }

    public function testGetDisplay()
    {
        $output = $this->tester->getOutput();
        $this->provider->alias(
            'Danack\Console\Output\Output',
            get_class($output)
        );

        $this->provider->share($output);
        $callable = $this->parsedCommand->getCallable();
        $this->provider->execute($callable, []);

        $this->assertEquals('foo'.PHP_EOL, $this->tester->getDisplay(), '->getDisplay() returns the display of the last execution');
    }
}


text:
namespace flutter {

#if OS_ANDROID
using JavaWeakGlobalRef = fml::jni::JavaObjectWeakGlobalRef;
#else
using JavaWeakGlobalRef = std::nullptr_t;
#endif

//------------------------------------------------------------------------------
/// Allows to call Java code running in the JVM from any thread. However, most
/// methods can only be called from the platform thread as that is where the
/// Java code runs.
///
/// This interface must not depend on the Android toolchain directly, so it can
/// be used in unit tests compiled with the host toolchain.
///
class PlatformViewAndroidJNI {
 public:
  virtual ~PlatformViewAndroidJNI();

  //----------------------------------------------------------------------------
  /// @brief      Sends a platform message. The message may be empty.
  ///
  virtual void FlutterViewHandlePlatformMessage(
      fml::RefPtr<flutter::PlatformMessage> message,
      int responseId) = 0;

  //----------------------------------------------------------------------------
  /// @brief      Responds to a platform message. The data may be a `nullptr`.
  ///
  virtual void FlutterViewHandlePlatformMessageResponse(
      int responseId,
      std::unique_ptr<fml::Mapping> data) = 0;

  //----------------------------------------------------------------------------
  /// @brief      Sends semantics tree updates.
  ///
  /// @note       Must be called from the platform thread.
  ///
  virtual void FlutterViewUpdateSemantics(std::vector<uint8_t> buffer,
                                          std::vector<std::string> strings) = 0;

  //----------------------------------------------------------------------------
  /// @brief      Sends new custom accessibility events.
  ///
  /// @note       Must be called from the platform thread.
  ///
  virtual void FlutterViewUpdateCustomAccessibilityActions(
      std::vector<uint8_t> actions_buffer,
      std::vector<std::string> strings) = 0;

  //----------------------------------------------------------------------------
  /// @brief      Indicates that FlutterView should start painting pixels.
  ///
  /// @note       Must be called from the platform thread.
  ///
  virtual void FlutterViewOnFirstFrame() = 0;

  //----------------------------------------------------------------------------
  /// @brief      Indicates that a hot restart is about to happen.
  ///
  virtual void FlutterViewOnPreEngineRestart() = 0;

  //----------------------------------------------------------------------------
  /// @brief      Attach the SurfaceTexture to the OpenGL ES context that is
  ///             current on the calling thread.
  ///
  virtual void SurfaceTextureAttachToGLContext(
      JavaWeakGlobalRef surface_texture,
      int textureId) = 0;

  //----------------------------------------------------------------------------
  /// @brief      Updates the texture image to the most recent frame from the
  ///             image stream.
  ///
  virtual void SurfaceTextureUpdateTexImage(
      JavaWeakGlobalRef surface_texture) = 0;

  //----------------------------------------------------------------------------
  /// @brief      Gets the transform matrix from the SurfaceTexture.
  ///             Then, it updates the `transform` matrix, so it fill the canvas
  ///             and preserve the aspect ratio.
  ///
  virtual void SurfaceTextureGetTransformMatrix(
      JavaWeakGlobalRef surface_texture,
      SkMatrix& transform) = 0;

  //----------------------------------------------------------------------------
  /// @brief      Detaches a SurfaceTexture from the OpenGL ES context.
  ///
  virtual void SurfaceTextureDetachFromGLContext(
      JavaWeakGlobalRef surface_texture) = 0;

  //----------------------------------------------------------------------------
  /// @brief      Positions and sizes a platform view if using hybrid
  ///             composition.
  ///
  /// @note       Must be called from the platform thread.
  ///
  virtual void FlutterViewOnDisplayPlatformView(
      int view_id,
      int x,
      int y,
      int width,
      int height,
      int viewWidth,
      int viewHeight,
      MutatorsStack mutators_stack) = 0;

  //----------------------------------------------------------------------------
  /// @brief      Positions and sizes an overlay surface in hybrid composition.
  ///
  /// @note       Must be called from the platform thread.
  ///
  virtual void FlutterViewDisplayOverlaySurface(int surface_id,
                                                int x,
                                                int y,
                                                int width,
                                                int height) = 0;

  //----------------------------------------------------------------------------
  /// @brief      Initiates a frame if using hybrid composition.
  ///
  ///
  /// @note       Must be called from the platform thread.
  ///
  virtual void FlutterViewBeginFrame() = 0;

  //----------------------------------------------------------------------------
  /// @brief      Indicates that the current frame ended.
  ///             It's used to clean up state.
  ///
  /// @note       Must be called from the platform thread.
  ///
  virtual void FlutterViewEndFrame() = 0;

  //------------------------------------------------------------------------------
  /// The metadata returned from Java which is converted into an |OverlayLayer|
  /// by |SurfacePool|.
  ///
  struct OverlayMetadata {
    OverlayMetadata(int id, fml::RefPtr<AndroidNativeWindow> window)
        : id(id), window(window){};

    ~OverlayMetadata() = default;

    // A unique id to identify the overlay when it gets recycled.
    const int id;

    // Holds a reference to the native window. That is, an `ANativeWindow`,
    // which is the C counterpart of the `android.view.Surface` object in Java.
    const fml::RefPtr<AndroidNativeWindow> window;
  };

  //----------------------------------------------------------------------------
  /// @brief      Instantiates an overlay surface in hybrid composition and
  ///             provides the necessary metadata to operate the surface in C.
  ///
  /// @note       Must be called from the platform thread.
  ///
  virtual std::unique_ptr<PlatformViewAndroidJNI::OverlayMetadata>
  FlutterViewCreateOverlaySurface() = 0;

  //----------------------------------------------------------------------------
  /// @brief      Destroys the overlay surfaces.
  ///
  /// @note       Must be called from the platform thread.
  ///
  virtual void FlutterViewDestroyOverlaySurfaces() = 0;

  //----------------------------------------------------------------------------
  /// @brief      Computes the locale Android would select.
  ///
  virtual std::unique_ptr<std::vector<std::string>>
  FlutterViewComputePlatformResolvedLocale(
      std::vector<std::string> supported_locales_data) = 0;
};

}  // namespace flutter

#endif  // FLUTTER_SHELL_PLATFORM_ANDROID_JNI_PLATFORM_VIEW_ANDROID_JNI_H_


text:
const Koa = require('koa');
const co = require('co');
const convert = require('koa-convert');
const bodyParser = require('koa-bodyparser');
const path = require('path');

const app = new Koa();
app.use(bodyParser());

/**
 * static serve
 */
const serve = require('koa-static');
app.use(convert(serve(__dirname + '/static')));

/**
 * render config
 */
const render = require('koa-ejs');
render(app, {
  root: path.join(__dirname, 'views'),
  layout: 'layout',
  viewExt: 'html',
  cache: false,
  debug: true
});

/**
 *  logger
 */
app.use(co.wrap(function *(ctx, next){
  const start = new Date;
  yield next();
  const ms = new Date - start;
  console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
}));

/**
 *  router
 */
router = require('./route');
app
  .use(router.routes())
  .use(router.allowedMethods());

app.listen(6900,()=>{
    console.info('listen at 6900');
});


text:
#include "MarkedList.h"
#include "../interface/HeeksObj.h"
#include "../interface/MarkedObject.h"
#include "../interface/PropertyInt.h"
#include "DigitizeMode.h"
#include "SelectMode.h"
#include "PointOrWindow.h"
#include "GripperSelTransform.h"
#include "GraphicsCanvas.h"
#include "HeeksFrame.h"
#include "ConversionTools.h"
#include "SolidTools.h"
#include "MenuSeparator.h"
using namespace std;

MarkedList::MarkedList(){
	gripping = false;
	point_or_window = new PointOrWindow(true);
	gripper_marked_list_changed = false;
	ignore_coords_only = false;
	m_filter = -1;
}

MarkedList::~MarkedList(void){
	delete point_or_window;
	std::list<Gripper*>::iterator It;
	for(It = move_grips.begin(); It != move_grips.end(); It++){
		Gripper* gripper = *It;
		gripper->m_index = 0;
	}
	delete_move_grips(false);
}

void MarkedList::delete_move_grips(bool check_app_grippers){
	std::list<Gripper*>::iterator It;
	for(It = move_grips.begin(); It != move_grips.end(); It++){
		Gripper* gripper = *It;
		if(check_app_grippers){
			if(gripper == wxGetApp().cursor_gripper)wxGetApp().cursor_gripper = NULL;
			if(gripper == wxGetApp().drag_gripper)wxGetApp().drag_gripper = NULL;
		}
		delete gripper;
	}
	move_grips.clear();
}

void MarkedList::create_move_grips(){
	delete_move_grips(true);
	int number_of_grips_made = 0;
	std::list<HeeksObj*>::iterator Iter ;
	for(Iter = m_list.begin(); Iter != m_list.end() && number_of_grips_made<100; Iter++){
		HeeksObj* object = *Iter;
		if(object->GetType() == GripperType)continue;
		std::list<GripData> vl;
		std::list<GripData>::iterator It;
		object->GetGripperPositionsTransformed(&vl, false);
		for(It = vl.begin(); It != vl.end() && number_of_grips_made<100; It++)
		{
			move_grips.push_back(new GripperSelTransform(*It, object));
			number_of_grips_made++;
		}
	}
}

void MarkedList::update_move_grips(){
	if(gripping)return;
	std::list<HeeksObj*>::iterator Iter ;
	std::list<Gripper*>::iterator Iter2;
	Iter2 = move_grips.begin();
	for(Iter = m_list.begin(); Iter != m_list.end(); Iter++){
		if(Iter2 == move_grips.end())break;
		HeeksObj* object = *Iter;
		if(object->GetType() == GripperType)continue;
		std::list<GripData> vl;
		std::list<GripData>::iterator It;
		object->GetGripperPositionsTransformed(&vl, false);
		for(It = vl.begin(); It != vl.end(); It++){
			Gripper* gripper = *Iter2;
			gripper->m_data = *It;
			Iter2++;
			if(Iter2 == move_grips.end())break;
		}
	}
}

void MarkedList::render_move_grips(bool select, bool no_color){
	std::list<Gripper*>::iterator It;
	for(It = move_grips.begin(); It != move_grips.end(); It++){
		if(select)glPushName((*It)->GetIndex());
		(*It)->glCommands(select, false, no_color);
		if(select)glPopName();
	}
}

void MarkedList::create_grippers(){
	if(gripping)return;
	if(gripper_marked_list_changed)create_move_grips();
	else update_move_grips();
	gripper_marked_list_changed = false;
}

void MarkedList::GrippersGLCommands(bool select, bool no_color){
	if(size()>0){
		create_grippers();
		render_move_grips(select, no_color);
	}
}

void MarkedList::ObjectsInWindow( wxRect window, MarkedObject* marked_object, bool single_picking){
	int buffer_length = 16384;
	GLuint *data = (GLuint *)malloc( buffer_length * sizeof(GLuint) );
	if(data == NULL)return;
	int half_window_width = 0;
	wxPoint window_centre;
	if(single_picking){
		half_window_width = (window.width)/2;
		window_centre.x = window.x + window.width/2;
		window_centre.y = window.y + window.height/2;
	}
	int window_mode = 0;
	while(1){
		if(single_picking){
			int window_size = half_window_width;
			if(window_mode == 0)window_size = 0;
			if(window_mode == 1)window_size = half_window_width/2;
			window.x = window_centre.x - window_size;
			window.y = window_centre.y - window_size;
			window.width = window_size * 2;
			window.height = window_size * 2;
		}
	    GLint num_hits = -1;
		while(num_hits < 0){
			glSelectBuffer(buffer_length, data);
			glRenderMode(GL_SELECT);
			glInitNames();
			wxGetApp().m_current_viewport->SetViewport();
			wxGetApp().m_current_viewport->m_view_point.SetPickProjection(window);
			wxGetApp().m_current_viewport->m_view_point.SetModelview();
			wxGetApp().glCommands(true, false, false);
			GrippersGLCommands(true, false);
			glFlush();
			num_hits = glRenderMode(GL_RENDER);
			if(num_hits<0){
				free(data);
				buffer_length *= 10;
				data = (GLuint *)malloc( buffer_length * sizeof(GLuint) );
				if(data == NULL)return;
			}
		}
		int pos = 0;
		bool added = false;
		for(unsigned i=0; i<(unsigned int)num_hits; i++)
		{
			unsigned int names = data[pos];
			if(names == 0)break;
			pos++;
			unsigned int min_depth = data[pos];
			pos+=2;
			MarkedObject* current_found_object = marked_object;
			bool ignore_coords_only_found = false;
			for(unsigned int j=0; j<names; j++, pos++){
				HeeksObj *object = m_name_index.find(data[pos]);
				bool custom_names = object->UsesCustomSubNames();
				if(!ignore_coords_only_found && current_found_object != NULL){

					if(ignore_coords_only && wxGetApp().m_digitizing->OnlyCoords(object)){
						ignore_coords_only_found = true;
					}
					else{
						if((object->GetType() == GripperType) || ((object->GetMarkingMask() & m_filter) && (object->GetMarkingMask() != 0))){
							int window_size = window.width;
							current_found_object = current_found_object->Add(object, min_depth, window_size, custom_names ? (names - 1 - j) : 0, custom_names ? (&data[pos+1]):NULL);
							added = true;
						}
					}

				}
				if(custom_names)
				{
					pos+=(names-j);
					break;
				}
			}
		}
		window_mode++;
		if(!single_picking)break;
		if(window_mode > 2)break;
	}

	free(data);
}

void MarkedList::Add(std::list<HeeksObj *> &list, bool call_OnChanged){
	std::list<HeeksObj *>::iterator It;
	for(It = list.begin(); It != list.end(); It++){
		HeeksObj *object = *It;
		m_list.push_back(object);
		m_set.insert(object);
	}
	if(call_OnChanged)OnChanged(false, &list, NULL);
}

void MarkedList::Remove(HeeksObj *object, bool call_OnChanged){
	if (!object) return;
	std::list<HeeksObj *> list;
	list.push_back(object);
	Remove(list, call_OnChanged);
}

void MarkedList::Add(HeeksObj *object, bool call_OnChanged){
	if (!object) return;
	std::list<HeeksObj *> list;
	list.push_back(object);
	Add(list, call_OnChanged);
}

void MarkedList::Remove(const std::list<HeeksObj *> &obj_list, bool call_OnChanged){
	std::list<HeeksObj *>::const_iterator It;
	for(It = obj_list.begin(); It != obj_list.end(); It++){
		HeeksObj *object = *It;
		if(m_set.find(object) != m_set.end()){
			m_list.remove(object);
		}
		m_set.erase(object);
	}
	if(call_OnChanged)OnChanged(false, NULL, &obj_list);
}

void MarkedList::Clear(bool call_OnChanged){
	m_list.clear();
	m_set.clear();
	if(call_OnChanged)OnChanged(true, NULL, NULL);
}

void MarkedList::FindMarkedObject(const wxPoint &point, MarkedObject* marked_object){
	if(marked_object == NULL)return;
	point_or_window->SetWithPoint(point);
	ObjectsInWindow(point_or_window->box_chosen, marked_object);
}

bool MarkedList::ObjectMarked(HeeksObj *object){
	return m_set.find(object) != m_set.end();
}

void MarkedList::OnChanged(bool selection_cleared, const std::list<HeeksObj *>* added, const std::list<HeeksObj *>* removed){
	gripper_marked_list_changed = true;
	wxGetApp().ObserversMarkedListChanged(selection_cleared, added, removed);
}

void MarkedList::OnChangedAdded(HeeksObj* object)
{
	std::list<HeeksObj *> added;
	added.push_back(object);
	OnChanged(false, &added, NULL);
}

void MarkedList::OnChangedRemoved(HeeksObj* object)
{
	std::list<HeeksObj *> removed;
	removed.push_back(object);
	OnChanged(false, NULL, &removed);
}

void MarkedList::set_ignore_onoff(HeeksObj* object, bool b){
	if(b)m_ignore_set.insert(object);
	else m_ignore_set.erase(object);
}

bool MarkedList::get_ignore(HeeksObj* object){
	if(m_ignore_set.find(object) != m_ignore_set.end())return true;
	return false;
}

void MarkedList::GetProperties(std::list<Property *> *list){
	if(m_list.size() == 1)
	{
		m_list.front()->GetProperties(list);
	}
	else
	{
		// multiple selection
		//list->push_back(new PropertyInt(_("Number of items selected"), m_list.size(), NULL));
		for(std::list<HeeksObj*>::iterator It = m_list.begin(); It != m_list.end(); It++)
		{
			HeeksObj* obj = *It;
			obj->GetProperties(list);
		}
	}
}

class DeleteMarkedListTool : public Tool
{
public:
	const wxChar* GetTitle() {return _("Delete Marked Items");}
	void Run() {wxGetApp().DeleteMarkedItems();}
	wxString BitmapPath(){return _T("delete");}
} delete_marked_list_tool;

class CopyMarkedList: public Tool
{
public:
	void Run();
	const wxChar* GetTitle(){return _("Copy");}
	wxString BitmapPath(){return _T("copy");}
	const wxChar* GetToolTip(){return _("Copies the selected items to the clipboard");}
} copy_marked_list;

void CopyMarkedList::Run()
{
	wxGetApp().m_marked_list->CopySelectedItems();
}

class PasteTool: public Tool
{
public:
	HeeksObj* m_paste_into;

	PasteTool():m_paste_into(NULL){}
	void Run();
	const wxChar* GetTitle(){return m_paste_into ? _("Paste Into") : _("Paste");}
	wxString BitmapPath(){return _T("paste");}
	const wxChar* GetToolTip(){return _("Paste items from the clipboard to the drawing");}
} paste_tool;

void PasteTool::Run()
{
	wxGetApp().Paste(m_paste_into, NULL);
}

void MarkedList::GetTools(MarkedObject* clicked_object, std::list<Tool*>& t_list, const wxPoint* p, bool copy_and_paste_tools){
	if(wxGetApp().m_no_creation_mode)return;

	if (m_list.size() > 0)
	{
		t_list.push_back(&delete_marked_list_tool);
		t_list.push_back(new MenuSeparator);
	}

	wxGetApp().GetExternalMarkedListTools(t_list);
	GetConversionMenuTools(&t_list);
	GetSolidMenuTools(&t_list);

	if(copy_and_paste_tools)
	{
		// cut and copy tools
		for(std::list<HeeksObj*>::iterator It = m_list.begin(); It != m_list.end(); It++)
		{
			HeeksObj* object = *It;
			if(object->CanBeCopied())
			{
				t_list.push_back(&copy_marked_list);
				break;
			}
		}

		// paste
		if (wxGetApp().IsPasteReady())
		{
			paste_tool.m_paste_into = clicked_object->GetObject();
			t_list.push_back(&paste_tool);
		}
	}
}

void MarkedList::CutSelectedItems()
{
	CopySelectedItems();
	wxGetApp().Remove(m_list);
}

void MarkedList::CopySelectedItems()
{
#if wxCHECK_VERSION(3, 0, 0)
	wxStandardPaths& sp = wxStandardPaths::Get();
#else
	wxStandardPaths sp;
#endif
	sp.GetTempDir();
	wxFileName temp_file(sp.GetTempDir().c_str(), _T("temp_Heeks_clipboard_file.xml"));

	wxGetApp().SaveXMLFile(m_list, temp_file.GetFullPath().c_str(), true);

#if wxUSE_UNICODE
	wifstream ifs(Ttc(temp_file.GetFullPath().c_str()));
#else
	ifstream ifs(temp_file.GetFullPath());
#endif
	if(!ifs)return;

	wxString fstr;
	wxChar str[1024];
	while(!(ifs.eof())){
		ifs.getline(str, 1022);
		fstr.append(str);
		fstr.append(_T("\r\n"));
		if(!ifs)break;
	}

	if (wxTheClipboard->Open())
	{
		// This data object is held by the clipboard,
		// so do not delete them in the app.
		wxTheClipboard->SetData( new wxTextDataObject(fstr));
		wxTheClipboard->Close();
	}
}

void MarkedList::Reset()
{
	delete_move_grips(true);
}

unsigned int MarkedList::GetIndex(HeeksObj *object) {
	return m_name_index.insert(object);
}

void MarkedList::ReleaseIndex(unsigned int index) {
	return m_name_index.erase(index);
}