diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 299d7b306..0eae7e597 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -1,18 +1,10 @@ { "ImportPath": "github.com/minio-io/minio", - "GoVersion": "go1.4.2", + "GoVersion": "go1.4", "Packages": [ "./..." ], "Deps": [ - { - "ImportPath": "github.com/clbanning/mxj", - "Rev": "e11b85050263aff26728fb9863bf2ebaf6591279" - }, - { - "ImportPath": "github.com/fatih/structs", - "Rev": "c00d27128bb88e9c1adab1a53cda9c72c6d1ff9b" - }, { "ImportPath": "github.com/gorilla/context", "Rev": "50c25fb3b2b3b3cc724e9b6ac75fb44b3bccd0da" diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/LICENSE b/Godeps/_workspace/src/github.com/clbanning/mxj/LICENSE deleted file mode 100644 index 67563f958..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/LICENSE +++ /dev/null @@ -1,55 +0,0 @@ -Copyright (c) 2012-2014 Charles Banning . All rights reserved. - -The MIT License (MIT) - -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. - -=============================================================================== - -Go Language Copyright & License - - -Copyright 2009 The Go Authors. All rights reserved. -Use of this source code is governed by a BSD-style -license that can be found in the LICENSE file. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/anyxml.go b/Godeps/_workspace/src/github.com/clbanning/mxj/anyxml.go deleted file mode 100644 index 5579e1036..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/anyxml.go +++ /dev/null @@ -1,177 +0,0 @@ -package mxj - -import ( - "encoding/xml" - "reflect" -) - -const ( - DefaultElementTag = "element" -) - -// Encode arbitrary value as XML. -// -// Note: unmarshaling the resultant -// XML may not return the original value, since tag labels may have been injected -// to create the XML representation of the value. -/* - Encode an arbitrary JSON object. - package main - - import ( - "encoding/json" - "fmt" - "github/clbanning/mxj" - ) - - func main() { - jsondata := []byte(`[ - { "somekey":"somevalue" }, - "string", - 3.14159265, - true - ]`) - var i interface{} - err := json.Unmarshal(jsondata, &i) - if err != nil { - // do something - } - x, err := anyxml.XmlIndent(i, "", " ", "mydoc") - if err != nil { - // do something else - } - fmt.Println(string(x)) - } - - output: - - somevalue - string - 3.14159265 - true - -*/ -// Alternative values for DefaultRootTag and DefaultElementTag can be set as: -// AnyXmlIndent( v, myRootTag, myElementTag). -func AnyXml(v interface{}, tags ...string) ([]byte, error) { - if reflect.TypeOf(v).Kind() == reflect.Struct { - return xml.Marshal(v) - } - - var err error - s := new(string) - p := new(pretty) - - var rt, et string - if len(tags) == 1 || len(tags) == 2 { - rt = tags[0] - } else { - rt = DefaultRootTag - } - if len(tags) == 2 { - et = tags[1] - } else { - et = DefaultElementTag - } - - var ss string - var b []byte - switch v.(type) { - case []interface{}: - ss = "<" + rt + ">" - for _, vv := range v.([]interface{}) { - switch vv.(type) { - case map[string]interface{}: - m := vv.(map[string]interface{}) - if len(m) == 1 { - for tag, val := range m { - err = mapToXmlIndent(false, s, tag, val, p) - } - } else { - err = mapToXmlIndent(false, s, et, vv, p) - } - default: - err = mapToXmlIndent(false, s, et, vv, p) - } - if err != nil { - break - } - } - ss += *s + "" - b = []byte(ss) - case map[string]interface{}: - m := Map(v.(map[string]interface{})) - b, err = m.Xml(rt) - default: - err = mapToXmlIndent(false, s, rt, v, p) - b = []byte(*s) - } - - return b, err -} - -// Encode an arbitrary value as a pretty XML string. -// Alternative values for DefaultRootTag and DefaultElementTag can be set as: -// AnyXmlIndent( v, "", " ", myRootTag, myElementTag). -func AnyXmlIndent(v interface{}, prefix, indent string, tags ...string) ([]byte, error) { - if reflect.TypeOf(v).Kind() == reflect.Struct { - return xml.MarshalIndent(v, prefix, indent) - } - - var err error - s := new(string) - p := new(pretty) - p.indent = indent - p.padding = prefix - - var rt, et string - if len(tags) == 1 || len(tags) == 2 { - rt = tags[0] - } else { - rt = DefaultRootTag - } - if len(tags) == 2 { - et = tags[1] - } else { - et = DefaultElementTag - } - - var ss string - var b []byte - switch v.(type) { - case []interface{}: - ss = "<" + rt + ">\n" - p.Indent() - for _, vv := range v.([]interface{}) { - switch vv.(type) { - case map[string]interface{}: - m := vv.(map[string]interface{}) - if len(m) == 1 { - for tag, val := range m { - err = mapToXmlIndent(true, s, tag, val, p) - } - } else { - p.start = 1 // we 1 tag in - err = mapToXmlIndent(true, s, et, vv, p) - *s += "\n" - } - default: - p.start = 0 // in case trailing p.start = 1 - err = mapToXmlIndent(true, s, et, vv, p) - } - if err != nil { - break - } - } - ss += *s + "" - b = []byte(ss) - case map[string]interface{}: - m := Map(v.(map[string]interface{})) - b, err = m.XmlIndent(prefix, indent, rt) - default: - err = mapToXmlIndent(true, s, rt, v, p) - b = []byte(*s) - } - - return b, err -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/anyxml_test.go b/Godeps/_workspace/src/github.com/clbanning/mxj/anyxml_test.go deleted file mode 100644 index df7228286..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/anyxml_test.go +++ /dev/null @@ -1,110 +0,0 @@ -package mxj - -import ( - "encoding/json" - "fmt" - "testing" -) - -func TestAnyXmlHeader(t *testing.T) { - fmt.Println("\n---------------- anyxml_test.go ...\n") -} - -var anydata = []byte(`[ - { - "somekey": "somevalue" - }, - { - "somekey": "somevalue" - }, - { - "somekey": "somevalue", - "someotherkey": "someothervalue" - }, - "string", - 3.14159265, - true -]`) - -type MyStruct struct { - Somekey string `xml:"somekey"` - B float32 `xml:"floatval"` -} - -func TestAnyXml(t *testing.T) { - var i interface{} - err := json.Unmarshal(anydata, &i) - if err != nil { - t.Fatal(err) - } - x, err := AnyXml(i) - if err != nil { - t.Fatal(err) - } - fmt.Println("[]->x:", string(x)) - - a := []interface{}{"try", "this", 3.14159265, true} - x, err = AnyXml(a) - if err != nil { - t.Fatal(err) - } - fmt.Println("a->x:", string(x)) - - x, err = AnyXml(a, "myRootTag", "myElementTag") - if err != nil { - t.Fatal(err) - } - fmt.Println("a->x:", string(x)) - - x, err = AnyXml(3.14159625) - if err != nil { - t.Fatal(err) - } - fmt.Println("f->x:", string(x)) - - s := MyStruct{"somevalue", 3.14159625} - x, err = AnyXml(s) - if err != nil { - t.Fatal(err) - } - fmt.Println("s->x:", string(x)) -} - -func TestAnyXmlIndent(t *testing.T) { - var i interface{} - err := json.Unmarshal(anydata, &i) - if err != nil { - t.Fatal(err) - } - x, err := AnyXmlIndent(i, "", " ") - if err != nil { - t.Fatal(err) - } - fmt.Println("[]->x:\n", string(x)) - - a := []interface{}{"try", "this", 3.14159265, true} - x, err = AnyXmlIndent(a, "", " ") - if err != nil { - t.Fatal(err) - } - fmt.Println("a->x:\n", string(x)) - - x, err = AnyXmlIndent(3.14159625, "", " ") - if err != nil { - t.Fatal(err) - } - fmt.Println("f->x:\n", string(x)) - - x, err = AnyXmlIndent(3.14159625, "", " ", "myRootTag", "myElementTag") - if err != nil { - t.Fatal(err) - } - fmt.Println("f->x:\n", string(x)) - - s := MyStruct{"somevalue", 3.14159625} - x, err = AnyXmlIndent(s, "", " ") - if err != nil { - t.Fatal(err) - } - fmt.Println("s->x:\n", string(x)) -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/bulk_test.go b/Godeps/_workspace/src/github.com/clbanning/mxj/bulk_test.go deleted file mode 100644 index bb64f9c00..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/bulk_test.go +++ /dev/null @@ -1,107 +0,0 @@ -// bulk_test.go - uses Handler and Writer functions to process some streams as a demo. - -package mxj - -import ( - "bytes" - "fmt" - "testing" -) - -func TestBulkHeader(t *testing.T) { - fmt.Println("\n---------------- bulk_test.go ...\n") -} - -var jsonWriter = new(bytes.Buffer) -var xmlWriter = new(bytes.Buffer) - -var jsonErrLog = new(bytes.Buffer) -var xmlErrLog = new(bytes.Buffer) - -func TestXmlReader(t *testing.T) { - // create Reader for xmldata - xmlReader := bytes.NewReader(xmldata) - - // read XML from Readerand pass Map value with the raw XML to handler - err := HandleXmlReader(xmlReader, bxmaphandler, bxerrhandler) - if err != nil { - t.Fatal("err:", err.Error()) - } - - // get the JSON - j := make([]byte, jsonWriter.Len()) - _, _ = jsonWriter.Read(j) - - // get the errors - e := make([]byte, xmlErrLog.Len()) - _, _ = xmlErrLog.Read(e) - - // print the input - fmt.Println("XmlReader, xmldata:\n", string(xmldata)) - // print the result - fmt.Println("XmlReader, result :\n", string(j)) - // print the errors - fmt.Println("XmlReader, errors :\n", string(e)) -} - -func bxmaphandler(m Map) bool { - j, err := m.JsonIndent("", " ", true) - if err != nil { - return false - } - - _, _ = jsonWriter.Write(j) - // put in a NL to pretty up printing the Writer - _, _ = jsonWriter.Write([]byte("\n")) - return true -} - -func bxerrhandler(err error) bool { - // write errors to file - _, _ = xmlErrLog.Write([]byte(err.Error())) - _, _ = xmlErrLog.Write([]byte("\n")) // pretty up - return true -} - -func TestJsonReader(t *testing.T) { - jsonReader := bytes.NewReader(jsondata) - - // read all the JSON - err := HandleJsonReader(jsonReader, bjmaphandler, bjerrhandler) - if err != nil { - t.Fatal("err:", err.Error()) - } - - // get the XML - x := make([]byte, xmlWriter.Len()) - _, _ = xmlWriter.Read(x) - - // get the errors - e := make([]byte, jsonErrLog.Len()) - _, _ = jsonErrLog.Read(e) - - // print the input - fmt.Println("JsonReader, jsondata:\n", string(jsondata)) - // print the result - fmt.Println("JsonReader, result :\n", string(x)) - // print the errors - fmt.Println("JsonReader, errors :\n", string(e)) -} - -func bjmaphandler(m Map) bool { - x, err := m.XmlIndent(" ", " ") - if err != nil { - return false - } - _, _ = xmlWriter.Write(x) - // put in a NL to pretty up printing the Writer - _, _ = xmlWriter.Write([]byte("\n")) - return true -} - -func bjerrhandler(err error) bool { - // write errors to file - _, _ = jsonErrLog.Write([]byte(err.Error())) - _, _ = jsonErrLog.Write([]byte("\n")) // pretty up - return true -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/bulkraw_test.go b/Godeps/_workspace/src/github.com/clbanning/mxj/bulkraw_test.go deleted file mode 100644 index 61c61fd5f..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/bulkraw_test.go +++ /dev/null @@ -1,113 +0,0 @@ -// bulk_test.go - uses Handler and Writer functions to process some streams as a demo. - -package mxj - -import ( - "bytes" - "fmt" - "testing" -) - -func TestBulkRawHeader(t *testing.T) { - fmt.Println("\n---------------- bulkraw_test.go ...\n") -} - -// use data from bulk_test.go - -var jsonWriterRaw = new(bytes.Buffer) -var xmlWriterRaw = new(bytes.Buffer) - -var jsonErrLogRaw = new(bytes.Buffer) -var xmlErrLogRaw = new(bytes.Buffer) - -func TestXmlReaderRaw(t *testing.T) { - // create Reader for xmldata - xmlReader := bytes.NewReader(xmldata) - - // read XML from Reader and pass Map value with the raw XML to handler - err := HandleXmlReaderRaw(xmlReader, bxmaphandlerRaw, bxerrhandlerRaw) - if err != nil { - t.Fatal("err:", err.Error()) - } - - // get the JSON - j := make([]byte, jsonWriterRaw.Len()) - _, _ = jsonWriterRaw.Read(j) - - // get the errors - e := make([]byte, xmlErrLogRaw.Len()) - _, _ = xmlErrLogRaw.Read(e) - - // print the input - fmt.Println("XmlReaderRaw, xmldata:\n", string(xmldata)) - // print the result - fmt.Println("XmlReaderRaw, result :\n", string(j)) - // print the errors - fmt.Println("XmlReaderRaw, errors :\n", string(e)) -} - -func bxmaphandlerRaw(m Map, raw []byte) bool { - j, err := m.JsonIndent("", " ", true) - if err != nil { - return false - } - - _, _ = jsonWriterRaw.Write(j) - // put in a NL to pretty up printing the Writer - _, _ = jsonWriterRaw.Write([]byte("\n")) - return true -} - -func bxerrhandlerRaw(err error, raw []byte) bool { - // write errors to file - _, _ = xmlErrLogRaw.Write([]byte(err.Error())) - _, _ = xmlErrLogRaw.Write([]byte("\n")) // pretty up - _, _ = xmlErrLogRaw.Write(raw) - _, _ = xmlErrLogRaw.Write([]byte("\n")) // pretty up - return true -} - -func TestJsonReaderRaw(t *testing.T) { - jsonReader := bytes.NewReader(jsondata) - - // read all the JSON - err := HandleJsonReaderRaw(jsonReader, bjmaphandlerRaw, bjerrhandlerRaw) - if err != nil { - t.Fatal("err:", err.Error()) - } - - // get the XML - x := make([]byte, xmlWriterRaw.Len()) - _, _ = xmlWriterRaw.Read(x) - - // get the errors - e := make([]byte, jsonErrLogRaw.Len()) - _, _ = jsonErrLogRaw.Read(e) - - // print the input - fmt.Println("JsonReaderRaw, jsondata:\n", string(jsondata)) - // print the result - fmt.Println("JsonReaderRaw, result :\n", string(x)) - // print the errors - fmt.Println("JsonReaderRaw, errors :\n", string(e)) -} - -func bjmaphandlerRaw(m Map, raw []byte) bool { - x, err := m.XmlIndent(" ", " ") - if err != nil { - return false - } - _, _ = xmlWriterRaw.Write(x) - // put in a NL to pretty up printing the Writer - _, _ = xmlWriterRaw.Write([]byte("\n")) - return true -} - -func bjerrhandlerRaw(err error, raw []byte) bool { - // write errors to file - _, _ = jsonErrLogRaw.Write([]byte(err.Error())) - _, _ = jsonErrLogRaw.Write([]byte("\n")) // pretty up, Error() from json.Unmarshal !NL - _, _ = jsonErrLogRaw.Write(raw) - _, _ = jsonErrLogRaw.Write([]byte("\n")) // pretty up - return true -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/data_test.go b/Godeps/_workspace/src/github.com/clbanning/mxj/data_test.go deleted file mode 100644 index 357513f66..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/data_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package mxj - -var xmldata = []byte(` - - William H. Gaddis - The Recognitions - One of the seminal American novels of the 20th century. - - - William H. Gaddis - JR - Won the National Book Award. - - - Austin Tappan Wright - Islandia - An example of earlier 20th century American utopian fiction. - - - John Hawkes - The Beetle Leg - A lyrical novel about the construction of Ft. Peck Dam in Montana. - - - - T.E. - Porter - - King's Day - A magical novella. -`) - -var jsondata = []byte(` - {"book":{"author":"William H. Gaddis","review":"One of the great seminal American novels of the 20th century.","title":"The Recognitions"}} -{"book":{"author":"Austin Tappan Wright","review":"An example of earlier 20th century American utopian fiction.","title":"Islandia"}} -{"book":{"author":"John Hawkes","review":"A lyrical novel about the construction of Ft. Peck Dam in Montana.","title":"The Beetle Leg"}} -{"book":{"author":{"first_name":"T.E.","last_name":"Porter"},"review":"A magical novella.","title":"King's Day"}} -{ "here":"we", "put":"in", "an":error }`) diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/doc.go b/Godeps/_workspace/src/github.com/clbanning/mxj/doc.go deleted file mode 100644 index 4db312c6e..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/doc.go +++ /dev/null @@ -1,84 +0,0 @@ -// mxj - A collection of map[string]interface{} and associated XML and JSON utilities. -// Copyright 2012-2014 Charles Banning. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file - -/* -Marshal/Unmarshal XML to/from JSON and map[string]interface{} values, and extract/modify values from maps by key or key-path, including wildcards. - -mxj supplants the legacy x2j and j2x packages. If you want the old syntax, use mxj/x2j or mxj/j2x packages. - -Note: this library was designed for processing ad hoc anonymous messages. Bulk processing large data sets may be much more efficiently performed using the encoding/xml or encoding/json packages from Go's standard library directly. - -Note: - 2014-08-02: AnyXml() and AnyXmlIndent() will try to marshal arbitrary values to XML. - -SUMMARY - - type Map map[string]interface{} - - Create a Map value, 'm', from any map[string]interface{} value, 'v': - m := Map(v) - - Unmarshal / marshal XML as a Map value, 'm': - m, err := NewMapXml(xmlValue) // unmarshal - xmlValue, err := m.Xml() // marshal - - Unmarshal XML from an io.Reader as a Map value, 'm': - m, err := NewMapReader(xmlReader) // repeated calls, as with an os.File Reader, will process stream - m, raw, err := NewMapReaderRaw(xmlReader) // 'raw' is the raw XML that was decoded - - Marshal Map value, 'm', to an XML Writer (io.Writer): - err := m.XmlWriter(xmlWriter) - raw, err := m.XmlWriterRaw(xmlWriter) // 'raw' is the raw XML that was written on xmlWriter - - Also, for prettified output: - xmlValue, err := m.XmlIndent(prefix, indent, ...) - err := m.XmlIndentWriter(xmlWriter, prefix, indent, ...) - raw, err := m.XmlIndentWriterRaw(xmlWriter, prefix, indent, ...) - - Bulk process XML with error handling (note: handlers must return a boolean value): - err := HandleXmlReader(xmlReader, mapHandler(Map), errHandler(error)) - err := HandleXmlReaderRaw(xmlReader, mapHandler(Map, []byte), errHandler(error, []byte)) - - Converting XML to JSON: see Examples for NewMapXml and HandleXmlReader. - - There are comparable functions and methods for JSON processing. - - Arbitrary structure values can be decoded to / encoded from Map values: - m, err := NewMapStruct(structVal) - err := m.Struct(structPointer) - - To work with XML tag values, JSON or Map key values or structure field values, decode the XML, JSON - or structure to a Map value, 'm', or cast a map[string]interface{} value to a Map value, 'm', then: - paths := m.PathsForKey(key) - path := m.PathForKeyShortest(key) - values, err := m.ValuesForKey(key, subkeys) - values, err := m.ValuesForPath(path, subkeys) // 'path' can be dot-notation with wildcards and indexed arrays. - count, err := m.UpdateValuesForPath(newVal, path, subkeys) - - Get everything at once, irrespective of path depth: - leafnodes := m.LeafNodes() - leafvalues := m.LeafValues() - - A new Map with whatever keys are desired can be created from the current Map and then encoded in XML - or JSON. (Note: keys can use dot-notation. 'oldKey' can also use wildcards and indexed arrays.) - newMap := m.NewMap("oldKey_1:newKey_1", "oldKey_2:newKey_2", ..., "oldKey_N:newKey_N") - newXml := newMap.Xml() // for example - newJson := newMap.Json() // ditto - -XML PARSING CONVENTIONS - - - Attributes are parsed to map[string]interface{} values by prefixing a hyphen, '-', - to the attribute label. (PrependAttrWithHyphen(false) will override this.) - - If the element is a simple element and has attributes, the element value - is given the key '#text' for its map[string]interface{} representation. - -XML ENCODING CONVENTIONS - - - 'nil' Map values, which may represent 'null' JSON values, are encoded as "". - NOTE: the operation is not symmetric as "" elements are decoded as 'tag:""' Map values, - which, then, encode in JSON as '"tag":""' values.. - -*/ -package mxj diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/example_test.go b/Godeps/_workspace/src/github.com/clbanning/mxj/example_test.go deleted file mode 100644 index 81fb28612..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/example_test.go +++ /dev/null @@ -1,344 +0,0 @@ -// note - "// Output:" is a key for "go test" to match function ouput with the lines that follow. -// It is also use by "godoc" to build the Output block of the function / method documentation. -// To skip processing Example* functions, use: go test -run "Test*" -// or make sure example function output matches // Output: documentation EXACTLY. - -package mxj_test - -import ( - "bytes" - "fmt" - "github.com/clbanning/mxj" - "io" -) - -func ExampleHandleXmlReader() { - /* - Bulk processing XML to JSON seems to be a common requirement. - See: bulk_test.go for working example. - Run "go test" in package directory then scroll back to find output. - - The logic is as follows. - - // need somewhere to write the JSON. - var jsonWriter io.Writer - - // probably want to log any errors in reading the XML stream - var xmlErrLogger io.Writer - - // func to handle Map value from XML Reader - func maphandler(m mxj.Map) bool { - // marshal Map as JSON - jsonVal, err := m.Json() - if err != nil { - // log error - return false // stops further processing of XML Reader - } - - // write JSON somewhere - _, err = jsonWriter.Write(jsonVal) - if err != nil { - // log error - return false // stops further processing of XML Reader - } - - // continue - get next XML from Reader - return true - } - - // func to handle error from unmarshaling XML Reader - func errhandler(errVal error) bool { - // log error somewhere - _, err := xmlErrLogger.Write([]byte(errVal.Error())) - if err != nil { - // log error - return false // stops further processing of XML Reader - } - - // continue processing - return true - } - - // func that starts bulk processing of the XML - ... - // set up io.Reader for XML data - perhaps an os.File - ... - err := mxj.HandleXmlReader(xmlReader, maphandler, errhandler) - if err != nil { - // handle error - } - ... - */ -} - -func ExampleHandleXmlReaderRaw() { - /* - See: bulkraw_test.go for working example. - Run "go test" in package directory then scroll back to find output. - - Basic logic for bulk XML to JSON processing is in HandleXmlReader example; - the only major difference is in handler function signatures so they are passed - the raw XML. (Read documentation on NewXmlReader regarding performance.) - */ -} - -func ExampleHandleJsonReader() { - /* - See: bulk_test.go for working example. - Run "go test" in package directory then scroll back to find output. - - Basic logic for bulk JSON to XML processing is similar to that for - bulk XML to JSON processing as outlined in the HandleXmlReader example. - The test case is also a good example. - */ -} - -func ExampleHandleJsonReaderRaw() { - /* - See: bulkraw_test.go for working example. - Run "go test" in package directory then scroll back to find output. - - Basic logic for bulk JSON to XML processing is similar to that for - bulk XML to JSON processing as outlined in the HandleXmlReader example. - The test case is also a good example. - */ -} - -/* -func ExampleNewMapXmlReaderRaw() { - // in an http.Handler - - mapVal, raw, err := mxj.NewMapXmlReader(req.Body) - if err != nil { - // handle error - } - logger.Print(string(*raw)) - // do something with mapVal - -} -*/ - -func ExampleNewMapStruct() { - type str struct { - IntVal int `json:"int"` - StrVal string `json:"str"` - FloatVal float64 `json:"float"` - BoolVal bool `json:"bool"` - private string - } - strVal := str{IntVal: 4, StrVal: "now's the time", FloatVal: 3.14159, BoolVal: true, private: "Skies are blue"} - - mapVal, merr := mxj.NewMapStruct(strVal) - if merr != nil { - // handle error - } - - fmt.Printf("strVal: %#v\n", strVal) - fmt.Printf("mapVal: %#v\n", mapVal) - // Note: example output is conformed to pass "go test". "mxj_test" is example_test.go package name. - - // Output: - // strVal: mxj_test.str{IntVal:4, StrVal:"now's the time", FloatVal:3.14159, BoolVal:true, private:"Skies are blue"} - // mapVal: mxj.Map{"int":4, "str":"now's the time", "float":3.14159, "bool":true} -} - -func ExampleMap_Struct() { - type str struct { - IntVal int `json:"int"` - StrVal string `json:"str"` - FloatVal float64 `json:"float"` - BoolVal bool `json:"bool"` - private string - } - - mapVal := mxj.Map{"int": 4, "str": "now's the time", "float": 3.14159, "bool": true, "private": "Somewhere over the rainbow"} - - var strVal str - mverr := mapVal.Struct(&strVal) - if mverr != nil { - // handle error - } - - fmt.Printf("mapVal: %#v\n", mapVal) - fmt.Printf("strVal: %#v\n", strVal) - // Note: example output is conformed to pass "go test". "mxj_test" is example_test.go package name. - - // Output: - // mapVal: mxj.Map{"int":4, "str":"now's the time", "float":3.14159, "bool":true, "private":"Somewhere over the rainbow"} - // strVal: mxj_test.str{IntVal:4, StrVal:"now's the time", FloatVal:3.14159, BoolVal:true, private:""} -} - -func ExampleMap_ValuesForKeyPath() { - // a snippet from examples/gonuts1.go - // How to compensate for irregular tag labels in data. - // Need to extract from an XML stream the values for "netid" and "idnet". - // Solution: use a wildcard path "data.*" to anonymize the "netid" and "idnet" tags. - - var msg1 = []byte(` - - - - no - default:text - default:word - - -`) - - var msg2 = []byte(` - - - - yes - default:text - default:word - - -`) - - // let's create a message stream - buf := new(bytes.Buffer) - // load a couple of messages into it - _, _ = buf.Write(msg1) - _, _ = buf.Write(msg2) - - n := 0 - for { - n++ - // Read the stream as Map values - quit on io.EOF. - // Get the raw XML as well as the Map value. - m, merr := mxj.NewMapXmlReader(buf) - if merr != nil && merr != io.EOF { - // handle error - for demo we just print it and continue - fmt.Printf("msg: %d - merr: %s\n", n, merr.Error()) - continue - } else if merr == io.EOF { - break - } - - // get the values for "netid" or "idnet" key using path == "data.*" - values, _ := m.ValuesForPath("data.*") - fmt.Println("\nmsg:", n, "> path == data.* - got array of values, len:", len(values)) - for i, val := range values { - fmt.Println("ValuesForPath result array member -", i, ":", val) - fmt.Println(" k:v pairs for array member:", i) - for key, val := range val.(map[string]interface{}) { - // You'd probably want to process the value, as appropriate. - // Here we just print it out. - fmt.Println("\t\t", key, ":", val) - } - } - } - // Output: - // msg: 1 > path == data.* - got array of values, len: 1 - // ValuesForPath result array member - 0 : map[disable:no text1:default:text word1:default:word] - // k:v pairs for array member: 0 - // disable : no - // text1 : default:text - // word1 : default:word - // - // msg: 2 > path == data.* - got array of values, len: 1 - // ValuesForPath result array member - 0 : map[disable:yes text1:default:text word1:default:word] - // k:v pairs for array member: 0 - // disable : yes - // text1 : default:text - // word1 : default:word -} - -func ExampleMap_UpdateValuesForPath() { - /* - - var biblioDoc = []byte(` - - - William Gaddis - - - The Recognitions - 1955 - A novel that changed the face of American literature. - - - JR - 1975 - Winner of National Book Award for Fiction. - - - - `) - - ... - m, merr := mxj.NewMapXml(biblioDoc) - if merr != nil { - // handle error - } - - // change 'review' for a book - count, err := m.UpdateValuesForPath("review:National Book Award winner." "*.*.*.*", "title:JR") - if err != nil { - // handle error - } - ... - - // change 'date' value from string type to float64 type - // Note: the following is equivalent to m, merr := NewMapXml(biblioDoc, mxj.Cast). - path := m.PathForKeyShortest("date") - v, err := m.ValuesForPath(path) - if err != nil { - // handle error - } - var total int - for _, vv := range v { - oldVal := "date:" + vv.(string) - newVal := "date:" + vv.(string) + ":num" - n, err := m.UpdateValuesForPath(newVal, path, oldVal) - if err != nil { - // handle error - } - total += n - } - ... - */ -} - -func ExampleMap_Copy() { - // Hand-crafted Map values that include structures do NOT Copy() as expected, - // since to simulate a deep copy the original Map value is JSON encoded then decoded. - - type str struct { - IntVal int `json:"int"` - StrVal string `json:"str"` - FloatVal float64 `json:"float"` - BoolVal bool `json:"bool"` - private string - } - s := str{IntVal: 4, StrVal: "now's the time", FloatVal: 3.14159, BoolVal: true, private: "Skies are blue"} - m := make(map[string]interface{}, 0) - m["struct"] = interface{}(s) - m["struct_ptr"] = interface{}(&s) - m["misc"] = interface{}(`Now is the time`) - - mv := mxj.Map(m) - cp, _ := mv.Copy() - - fmt.Printf("mv:%s\n", mv.StringIndent(2)) - fmt.Printf("cp:%s\n", cp.StringIndent(2)) - - // Output: - // mv: - // struct :[unknown] mxj_test.str{IntVal:4, StrVal:"now's the time", FloatVal:3.14159, BoolVal:true, private:"Skies are blue"} - // struct_ptr :[unknown] &mxj_test.str{IntVal:4, StrVal:"now's the time", FloatVal:3.14159, BoolVal:true, private:"Skies are blue"} - // misc :[string] Now is the time - // cp: - // misc :[string] Now is the time - // struct : - // int :[float64] 4.00e+00 - // str :[string] now's the time - // float :[float64] 3.14e+00 - // bool :[bool] true - // struct_ptr : - // int :[float64] 4.00e+00 - // str :[string] now's the time - // float :[float64] 3.14e+00 - // bool :[bool] true -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/README b/Godeps/_workspace/src/github.com/clbanning/mxj/examples/README deleted file mode 100644 index e14580f7b..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/README +++ /dev/null @@ -1,124 +0,0 @@ -Examples of using ValuesFromTagPath(). - -A number of interesting examples have shown up in the gonuts discussion group -that could be handled - after a fashion - using the ValuesFromTagPath() function. - -gonuts1.go - - -Here we see that the message stream has a problem with multiple tag spellings, -though the message structure remains constant. In this example we 'anonymize' -the tag for the variant spellings. - values := m.ValuesForPath("data.*) - where '*' is any possible spelling - "netid" or "idnet" - and the result is a list with 1 member of map[string]interface{} type. - -Once we've retrieved the Map, we can parse it using the known keys - "disable", -"text1" and "word1". - - -gonuts1a.go - (03-mar-14) - -Here we just permute the tag labels using m.NewMap() to make all the messages -consistent. Then they can be decoded into a single structure definition. - - -gonuts2.go - - -This is an interesting case where there was a need to handle messages with lists -of "ClaimStatusCodeRecord" entries as well as messages with NONE. (Here we see -some of the vagaries of dealing with mixed messages that are verging on becoming -anonymous.) - - msg1 - the message with two ClaimStatusCodeRecord entries - msg2 - the message with one ClaimStatusCodeRecord entry - msg3 - the message with NO ClaimStatusCodeRecord entries - -ValuesForPath options: - - path == "Envelope.Body.GetClaimStatusCodesResponse.GetClaimStatusCodesResult.ClaimStatusCodeRecord" - for msg == msg1: - returns: a list - []interface{} - with two values of map[string]interface{} type - for msg == msg2: - returns: a list - []interface{} - with one map[string]interface{} type - for msg == msg3: - returns 'nil' - no values - - path == "*.*.*.*.*" - for msg == msg1: - returns: a list - []interface{} - with two values of map[string]interface{} type - - path == "*.*.*.*.*.Description - for msg == msg1: - returns: a list - []interface{} - with two values of string type, the individual - values from parsing the two map[string]interface{} values where key=="Description" - - path == "*.*.*.*.*.*" - for msg == msg1: - returns: a list - []interface{} - with six values of string type, the individual - values from parsing all keys in the two map[string]interface{} values - -Think of the wildcard character "*" as anonymizing the tag in the position of the path where -it occurs. The books.go example has a range of use cases. - - -gonuts3.go - - -Uses the ValuesForKey method to extract a list of image "src" file names that are encoded as -attribute values. - - -gonuts4.go - - -Here we use the ValuesForPath to extract attribute values for country names. The attribute -is included in the 'path' argument by prepending it with a hyphen: ""doc.some_tag.geoInfo.country.-name". - - -gonuts5.go (10-mar-14) - - -Extract a node of values using ValuesForPath based on name="list3-1-1-1". Then get the values -for the 'int' entries based on attribute 'name' values - mv.ValuesForKey("int", "-name:"+n). - -gonuts5a.go (10-mar-14) - - -Extract a node of values using ValuesForPath based on name="list3-1-1-1". Then get the values -for the 'int' entries based on attribute 'name' values - mv.ValuesForKey("*", "-name:"+n). -(Same as gonuts5.go but with wildcarded key value, since we're matching elements on subkey.) - - -EAT YOUR OWN DOG FOOD ... - -I needed to convert a large (14.9 MB) XML data set from an Eclipse metrics report on an -application that had 355,100 lines of code in 211 packages into CSV data sets. The report -included application-, package-, class- and method-level metrics reported in an element, -"Value", with varying attributes. - - - - - -In addition, the metrics were reported with two different "Metric" compound elements: - - - - - ... - - - ... - - - - ... - - -Using the mxj package seemed a more straightforward approach than using Go vernacular -and the standard xml package. I wrote the program getmetrics.go to do this. Here are -three version to illustrate using - getmetrics1.go - pass os.File handle for metrics_data.xml to NewMapXmlReader. - getmetrics2.go - load metrics_data.xml into an in-memory buffer, then pass it to NewMapXml. - getmetrics3.go - demonstrates overhead of extracting the raw XML while decoding with NewMapXmlReaderRaw. - -To run example getmetrics1.go, extract a 120,000+ row data set from metrics_data.zip. Then: - go run getmetrics1.go -file=metrics_data.xml - - diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/books.go b/Godeps/_workspace/src/github.com/clbanning/mxj/examples/books.go deleted file mode 100644 index e703d8395..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/books.go +++ /dev/null @@ -1,71 +0,0 @@ -// Note: this illustrates ValuesForKey() and ValuesForPath() methods - -package main - -import ( - "fmt" - "github.com/clbanning/mxj" - "log" -) - -var xmldata = []byte(` - - - William H. Gaddis - The Recognitions - One of the great seminal American novels of the 20th century. - - - Austin Tappan Wright - Islandia - An example of earlier 20th century American utopian fiction. - - - John Hawkes - The Beetle Leg - A lyrical novel about the construction of Ft. Peck Dam in Montana. - - - T.E. Porter - King's Day - A magical novella. - - -`) - -func main() { - fmt.Println(string(xmldata)) - - m, err := mxj.NewMapXml(xmldata) - if err != nil { - log.Fatal("err:", err.Error()) - } - - v, _ := m.ValuesForKey("books") - fmt.Println("path: books; len(v):", len(v)) - fmt.Printf("\t%+v\n", v) - - v, _ = m.ValuesForPath("books.book") - fmt.Println("path: books.book; len(v):", len(v)) - for _, vv := range v { - fmt.Printf("\t%+v\n", vv) - } - - v, _ = m.ValuesForPath("books.*") - fmt.Println("path: books.*; len(v):", len(v)) - for _, vv := range v { - fmt.Printf("\t%+v\n", vv) - } - - v, _ = m.ValuesForPath("books.*.title") - fmt.Println("path: books.*.title len(v):", len(v)) - for _, vv := range v { - fmt.Printf("\t%+v\n", vv) - } - - v, _ = m.ValuesForPath("books.*.*") - fmt.Println("path: books.*.*; len(v):", len(v)) - for _, vv := range v { - fmt.Printf("\t%+v\n", vv) - } -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/getmetrics1.go b/Godeps/_workspace/src/github.com/clbanning/mxj/examples/getmetrics1.go deleted file mode 100644 index c4e680382..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/getmetrics1.go +++ /dev/null @@ -1,176 +0,0 @@ -// getmetrics1.go - transform Eclipse Metrics (v3) XML report into CSV files for each metric -// Uses NewMapXmlReader on os.File without copying the raw XML into a buffer while decoding.. -// Shows no significant overhead for not first buffering large XML file as in getmetrics2.go. - -/* -I needed to convert a large (14.9 MB) XML data set from an Eclipse metrics report on an -application that had 355,100 lines of code in 211 packages into CSV data sets. The report -included application-, package-, class- and method-level metrics reported in an element, -"Value", with varying attributes. - - - - - -In addition, the metrics were reported with two different "Metric" compound elements: - - - - - ... - - - ... - - - - ... - - -To run this example, extract the metrics_data.xml file from metrics_data.zip, then: - > go run getmetrics1 -file=metrics_data.xml - -The output will be a set of "csv" files. -*/ - -package main - -import ( - "flag" - "fmt" - "github.com/clbanning/mxj" - "log" - "os" - "time" -) - -func main() { - var file string - flag.StringVar(&file, "file", "", "file to process") - flag.Parse() - - fh, fherr := os.Open(file) - if fherr != nil { - fmt.Println("fherr:", fherr.Error()) - return - } - defer fh.Close() - fmt.Println(time.Now().String(), "... File Opened:", file) - - /* - // Get the XML data set from the file. - fs, _ := fh.Stat() - xmldata := make([]byte, fs.Size()) - n, frerr := fh.Read(xmldata) - if frerr != nil { - fmt.Println("frerr:", frerr.Error()) - return - } - if int64(n) != fs.Size() { - fmt.Println("n:", n, "fs.Size():", fs.Size()) - return - } - fmt.Println(time.Now().String(), "... File Read - size:", fs.Size()) - - // load XML into a Map value - m, merr := mxj.NewMapXml(xmldata) - */ - // Consume the file using os.File Reader. - // Note: there is a single record with root tag of "Metrics". - m, merr := mxj.NewMapXmlReader(fh) - if merr != nil { - log.Fatal("merr:", merr.Error()) - } - fmt.Println(time.Now().String(), "... XML Unmarshaled - len:", len(m)) - - // Get just the key values of interest. - // Could also use m.ValuesForKey("Metric"), - // since there's just the one path. - metricVals, err := m.ValuesForPath("Metrics.Metric") - if err != nil { - log.Fatal("err:", err.Error()) - } - fmt.Println(time.Now().String(), "... ValuesFromKeyPath - len:", len(metricVals)) - - // now just manipulate Map entries returned as []interface{} array. - for _, v := range metricVals { - aMetricVal := v.(map[string]interface{}) - - // create file to hold csv data sets - id := aMetricVal["-id"].(string) - desc := aMetricVal["-description"].(string) - mf, mferr := os.OpenFile(id+".csv", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666) - if mferr != nil { - fmt.Println("mferr:", mferr.Error()) - return - } - - fmt.Print(time.Now().String(), " id: ", id, " desc: ", desc) - mf.WriteString(id + "," + desc + "\n") - - // rescan looking for keys with data: Values or Value - for key, val := range aMetricVal { - switch key { - case "Values": - // extract the list of "Value" from map - values := val.(map[string]interface{})["Value"].([]interface{}) - fmt.Println(" len(Values):", len(values)) - - // first line in file is the metric label values (keys) - var gotKeys bool - for _, vval := range values { - valueEntry := vval.(map[string]interface{}) - - // no guarantee that range on map will follow any sequence - lv := len(valueEntry) - type ev [2]string - list := make([]ev, lv) - var i int - for k, v := range valueEntry { - list[i][0] = k - list[i][1] = v.(string) - i++ - } - - // extract keys as column header on first pass - if !gotKeys { - // print out the keys - var gotFirstKey bool - // for kk, _ := range valueEntry { - for i := 0; i < lv; i++ { - if gotFirstKey { - mf.WriteString(",") - } else { - gotFirstKey = true - } - // strip prepended hyphen - mf.WriteString((list[i][0])[1:]) - } - mf.WriteString("\n") - gotKeys = true - } - - // print out values - var gotFirstVal bool - // for _, vv := range valueEntry { - for i := 0; i < lv; i++ { - if gotFirstVal { - mf.WriteString(",") - } else { - gotFirstVal = true - } - mf.WriteString(list[i][1]) - } - - // terminate row of data - mf.WriteString("\n") - } - case "Value": - vv := val.(map[string]interface{}) - fmt.Println(" len(Value):", len(vv)) - mf.WriteString("value\n" + vv["-value"].(string) + "\n") - } - } - mf.Close() - } -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/getmetrics2.go b/Godeps/_workspace/src/github.com/clbanning/mxj/examples/getmetrics2.go deleted file mode 100644 index 65d6c9513..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/getmetrics2.go +++ /dev/null @@ -1,173 +0,0 @@ -// getmetrics2.go - transform Eclipse Metrics (v3) XML report into CSV files for each metric -// Uses an in-memory buffer for the XML data and direct XML decoding of the buffer into a Map. -// Not significantly faster than getmetrics1.go that uses an io.Reader (os.File) to directly -// decode the XML from the file. - -/* -I needed to convert a large (14.9 MB) XML data set from an Eclipse metrics report on an -application that had 355,100 lines of code in 211 packages into CSV data sets. The report -included application-, package-, class- and method-level metrics reported in an element, -"Value", with varying attributes. - - - - - -In addition, the metrics were reported with two different "Metric" compound elements: - - - - - ... - - - ... - - - - ... - - -To run this example, extract the metrics_data.xml file from metrics_data.zip, then: - > go run getmetrics -file=metrics_data.xml - -The output will be a set of "csv" files. -*/ - -package main - -import ( - "flag" - "fmt" - "github.com/clbanning/mxj" - "log" - "os" - "time" -) - -func main() { - var file string - flag.StringVar(&file, "file", "", "file to process") - flag.Parse() - - fh, fherr := os.Open(file) - if fherr != nil { - fmt.Println("fherr:", fherr.Error()) - return - } - defer fh.Close() - fmt.Println(time.Now().String(), "... File Opened:", file) - - // Get the XML data set from the file. - fs, _ := fh.Stat() - xmldata := make([]byte, fs.Size()) - n, frerr := fh.Read(xmldata) - if frerr != nil { - fmt.Println("frerr:", frerr.Error()) - return - } - if int64(n) != fs.Size() { - fmt.Println("n:", n, "fs.Size():", fs.Size()) - return - } - fmt.Println(time.Now().String(), "... File Read - size:", fs.Size()) - - // load XML into a Map value - // Note: there is a single record with root tag of "Metrics". - m, merr := mxj.NewMapXml(xmldata) - if merr != nil { - log.Fatal("merr:", merr.Error()) - } - fmt.Println(time.Now().String(), "... XML Unmarshaled - len:", len(m)) - - // Get just the key values of interest. - // Could also use m.ValuesForKey("Metric"), - // since there's just the one path. - metricVals, err := m.ValuesForPath("Metrics.Metric") - if err != nil { - log.Fatal("err:", err.Error()) - } - fmt.Println(time.Now().String(), "... ValuesFromKeyPath - len:", len(metricVals)) - - // now just manipulate Map entries returned as []interface{} array. - for _, v := range metricVals { - aMetricVal := v.(map[string]interface{}) - - // create file to hold csv data sets - id := aMetricVal["-id"].(string) - desc := aMetricVal["-description"].(string) - mf, mferr := os.OpenFile(id+".csv", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666) - if mferr != nil { - fmt.Println("mferr:", mferr.Error()) - return - } - - fmt.Print(time.Now().String(), " id: ", id, " desc: ", desc) - mf.WriteString(id + "," + desc + "\n") - - // rescan looking for keys with data: Values or Value - for key, val := range aMetricVal { - switch key { - case "Values": - // extract the list of "Value" from map - values := val.(map[string]interface{})["Value"].([]interface{}) - fmt.Println(" len(Values):", len(values)) - - // first line in file is the metric label values (keys) - var gotKeys bool - for _, vval := range values { - valueEntry := vval.(map[string]interface{}) - - // no guarantee that range on map will follow any sequence - lv := len(valueEntry) - type ev [2]string - list := make([]ev, lv) - var i int - for k, v := range valueEntry { - list[i][0] = k - list[i][1] = v.(string) - i++ - } - - // extract keys as column header on first pass - if !gotKeys { - // print out the keys - var gotFirstKey bool - // for kk, _ := range valueEntry { - for i := 0; i < lv; i++ { - if gotFirstKey { - mf.WriteString(",") - } else { - gotFirstKey = true - } - // strip prepended hyphen - mf.WriteString((list[i][0])[1:]) - } - mf.WriteString("\n") - gotKeys = true - } - - // print out values - var gotFirstVal bool - // for _, vv := range valueEntry { - for i := 0; i < lv; i++ { - if gotFirstVal { - mf.WriteString(",") - } else { - gotFirstVal = true - } - mf.WriteString(list[i][1]) - } - - // terminate row of data - mf.WriteString("\n") - } - case "Value": - vv := val.(map[string]interface{}) - fmt.Println(" len(Value):", len(vv)) - mf.WriteString("value\n" + vv["-value"].(string) + "\n") - } - } - mf.Close() - } -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/getmetrics3.go b/Godeps/_workspace/src/github.com/clbanning/mxj/examples/getmetrics3.go deleted file mode 100644 index a914d5491..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/getmetrics3.go +++ /dev/null @@ -1,180 +0,0 @@ -// getmetrics3.go - transform Eclipse Metrics (v3) XML report into CSV files for each metric -// Uses NewMapXmlReaderRaw that requires loading raw XML into a []byte buffer using a ByteReader. -// Show's performance impact of copying the raw XML while simultaneously decoding it from on os.File -// Reader. (vs. getmetrics1.go) If you're processing a file and need a copy of the raw XML and SPEED, -// should buffer the file in memory and decode using mxj.NewMapXmlReaderRaw as in getmetrics4.go. - -/* -I needed to convert a large (14.9 MB) XML data set from an Eclipse metrics report on an -application that had 355,100 lines of code in 211 packages into CSV data sets. The report -included application-, package-, class- and method-level metrics reported in an element, -"Value", with varying attributes. - - - - - -In addition, the metrics were reported with two different "Metric" compound elements: - - - - - ... - - - ... - - - - ... - - -To run this example, extract the metrics_data.xml file from metrics_data.zip, then: - > go run getmetrics3 -file=metrics_data.xml - -The output will be a set of "csv" files. -*/ - -package main - -import ( - "flag" - "fmt" - "github.com/clbanning/mxj" - "log" - "os" - "time" -) - -func main() { - var file string - flag.StringVar(&file, "file", "", "file to process") - flag.Parse() - - fh, fherr := os.Open(file) - if fherr != nil { - fmt.Println("fherr:", fherr.Error()) - return - } - defer fh.Close() - fmt.Println(time.Now().String(), "... File Opened:", file) - - /* - // Get the XML data set from the file. - fs, _ := fh.Stat() - xmldata := make([]byte, fs.Size()) - n, frerr := fh.Read(xmldata) - if frerr != nil { - fmt.Println("frerr:", frerr.Error()) - return - } - if int64(n) != fs.Size() { - fmt.Println("n:", n, "fs.Size():", fs.Size()) - return - } - fmt.Println(time.Now().String(), "... File Read - size:", fs.Size()) - - // load XML into a Map value - m, merr := mxj.NewMapXml(xmldata) - */ - // Consume the file using os.File Reader. - // Note: there is a single record with root tag of "Metrics". - // Also: this is MUCH slower than using buffer or not loading raw XML. - m, raw, merr := mxj.NewMapXmlReaderRaw(fh) - if merr != nil { - log.Fatal("merr:", merr.Error()) - } - fmt.Println(time.Now().String(), "... XML Unmarshaled - len:", len(m)) - fmt.Println("raw XML buffer size (should be same as File size):", len(*raw)) - - // Get just the key values of interest. - // Could also use m.ValuesForKey("Metric"), - // since there's just the one path. - metricVals, err := m.ValuesForPath("Metrics.Metric") - if err != nil { - log.Fatal("err:", err.Error()) - } - fmt.Println(time.Now().String(), "... ValuesFromKeyPath - len:", len(metricVals)) - - // now just manipulate Map entries returned as []interface{} array. - for _, v := range metricVals { - aMetricVal := v.(map[string]interface{}) - - // create file to hold csv data sets - id := aMetricVal["-id"].(string) - desc := aMetricVal["-description"].(string) - mf, mferr := os.OpenFile(id+".csv", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666) - if mferr != nil { - fmt.Println("mferr:", mferr.Error()) - return - } - - fmt.Print(time.Now().String(), " id: ", id, " desc: ", desc) - mf.WriteString(id + "," + desc + "\n") - - // rescan looking for keys with data: Values or Value - for key, val := range aMetricVal { - switch key { - case "Values": - // extract the list of "Value" from map - values := val.(map[string]interface{})["Value"].([]interface{}) - fmt.Println(" len(Values):", len(values)) - - // first line in file is the metric label values (keys) - var gotKeys bool - for _, vval := range values { - valueEntry := vval.(map[string]interface{}) - - // no guarantee that range on map will follow any sequence - lv := len(valueEntry) - type ev [2]string - list := make([]ev, lv) - var i int - for k, v := range valueEntry { - list[i][0] = k - list[i][1] = v.(string) - i++ - } - - // extract keys as column header on first pass - if !gotKeys { - // print out the keys - var gotFirstKey bool - // for kk, _ := range valueEntry { - for i := 0; i < lv; i++ { - if gotFirstKey { - mf.WriteString(",") - } else { - gotFirstKey = true - } - // strip prepended hyphen - mf.WriteString((list[i][0])[1:]) - } - mf.WriteString("\n") - gotKeys = true - } - - // print out values - var gotFirstVal bool - // for _, vv := range valueEntry { - for i := 0; i < lv; i++ { - if gotFirstVal { - mf.WriteString(",") - } else { - gotFirstVal = true - } - mf.WriteString(list[i][1]) - } - - // terminate row of data - mf.WriteString("\n") - } - case "Value": - vv := val.(map[string]interface{}) - fmt.Println(" len(Value):", len(vv)) - mf.WriteString("value\n" + vv["-value"].(string) + "\n") - } - } - mf.Close() - } -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/getmetrics4.go b/Godeps/_workspace/src/github.com/clbanning/mxj/examples/getmetrics4.go deleted file mode 100644 index 2cf663817..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/getmetrics4.go +++ /dev/null @@ -1,179 +0,0 @@ -// getmetrics2.go - transform Eclipse Metrics (v3) XML report into CSV files for each metric -// Uses an in-memory buffer for the XML data and direct XML decoding of the buffer into a Map. -// Then XML buffer is decoded into a Map while the raw XML is copied using NewMapXmlReaderRaw() -// to illustrate processing overhead relative to getmetrics2.go. Not a practical example, -// but confirms the getmetrics1.go vs. getmetrics3.go use case. - -/* -I needed to convert a large (14.9 MB) XML data set from an Eclipse metrics report on an -application that had 355,100 lines of code in 211 packages into CSV data sets. The report -included application-, package-, class- and method-level metrics reported in an element, -"Value", with varying attributes. - - - - - -In addition, the metrics were reported with two different "Metric" compound elements: - - - - - ... - - - ... - - - - ... - - -To run this example, extract the metrics_data.xml file from metrics_data.zip, then: - > go run getmetrics -file=metrics_data.xml - -The output will be a set of "csv" files. -*/ - -package main - -import ( - "bytes" - "flag" - "fmt" - "github.com/clbanning/mxj" - "log" - "os" - "time" -) - -func main() { - var file string - flag.StringVar(&file, "file", "", "file to process") - flag.Parse() - - fh, fherr := os.Open(file) - if fherr != nil { - fmt.Println("fherr:", fherr.Error()) - return - } - defer fh.Close() - fmt.Println(time.Now().String(), "... File Opened:", file) - - // Get the XML data set from the file. - fs, _ := fh.Stat() - xmldata := make([]byte, fs.Size()) - n, frerr := fh.Read(xmldata) - if frerr != nil { - fmt.Println("frerr:", frerr.Error()) - return - } - if int64(n) != fs.Size() { - fmt.Println("n:", n, "fs.Size():", fs.Size()) - return - } - fmt.Println(time.Now().String(), "... File Read - size:", fs.Size()) - - // wrap the buffer in an io.Reader - xmlReader := bytes.NewBuffer(xmldata) - - // load XML into a Map value - // Note: there is a single record with root tag of "Metrics". - m, raw, merr := mxj.NewMapXmlReaderRaw(xmlReader) // don't catch the pointer to raw XML - if merr != nil { - log.Fatal("merr:", merr.Error()) - } - fmt.Println(time.Now().String(), "... XML Unmarshaled - len:", len(m)) - fmt.Println("raw XML buffer size (should be same as File size):", len(*raw)) - - // Get just the key values of interest. - // Could also use m.ValuesForKey("Metric"), - // since there's just the one path. - metricVals, err := m.ValuesForPath("Metrics.Metric") - if err != nil { - log.Fatal("err:", err.Error()) - } - fmt.Println(time.Now().String(), "... ValuesFromKeyPath - len:", len(metricVals)) - - // now just manipulate Map entries returned as []interface{} array. - for _, v := range metricVals { - aMetricVal := v.(map[string]interface{}) - - // create file to hold csv data sets - id := aMetricVal["-id"].(string) - desc := aMetricVal["-description"].(string) - mf, mferr := os.OpenFile(id+".csv", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666) - if mferr != nil { - fmt.Println("mferr:", mferr.Error()) - return - } - - fmt.Print(time.Now().String(), " id: ", id, " desc: ", desc) - mf.WriteString(id + "," + desc + "\n") - - // rescan looking for keys with data: Values or Value - for key, val := range aMetricVal { - switch key { - case "Values": - // extract the list of "Value" from map - values := val.(map[string]interface{})["Value"].([]interface{}) - fmt.Println(" len(Values):", len(values)) - - // first line in file is the metric label values (keys) - var gotKeys bool - for _, vval := range values { - valueEntry := vval.(map[string]interface{}) - - // no guarantee that range on map will follow any sequence - lv := len(valueEntry) - type ev [2]string - list := make([]ev, lv) - var i int - for k, v := range valueEntry { - list[i][0] = k - list[i][1] = v.(string) - i++ - } - - // extract keys as column header on first pass - if !gotKeys { - // print out the keys - var gotFirstKey bool - // for kk, _ := range valueEntry { - for i := 0; i < lv; i++ { - if gotFirstKey { - mf.WriteString(",") - } else { - gotFirstKey = true - } - // strip prepended hyphen - mf.WriteString((list[i][0])[1:]) - } - mf.WriteString("\n") - gotKeys = true - } - - // print out values - var gotFirstVal bool - // for _, vv := range valueEntry { - for i := 0; i < lv; i++ { - if gotFirstVal { - mf.WriteString(",") - } else { - gotFirstVal = true - } - mf.WriteString(list[i][1]) - } - - // terminate row of data - mf.WriteString("\n") - } - case "Value": - vv := val.(map[string]interface{}) - fmt.Println(" len(Value):", len(vv)) - mf.WriteString("value\n" + vv["-value"].(string) + "\n") - } - } - mf.Close() - } -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/gonuts1.go b/Godeps/_workspace/src/github.com/clbanning/mxj/examples/gonuts1.go deleted file mode 100644 index a0c5d6fce..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/gonuts1.go +++ /dev/null @@ -1,82 +0,0 @@ -// https://groups.google.com/forum/#!searchin/golang-nuts/idnet$20netid/golang-nuts/guM3ZHHqSF0/K1pBpMqQSSwJ -// http://play.golang.org/p/BFFDxphKYK - -package main - -import ( - "bytes" - "fmt" - "github.com/clbanning/mxj" - "io" -) - -// Demo how to compensate for irregular tag labels in data. -// Need to extract from an XML stream the values for "netid" and "idnet". -// Solution: use a wildcard path "data.*" to anonymize the "netid" and "idnet" tags. - -var msg1 = []byte(` - - - - no - default:text - default:word - - -`) - -var msg2 = []byte(` - - - - yes - default:text - default:word - - -`) - -func main() { - // let's create a message stream - buf := new(bytes.Buffer) - // load a couple of messages into it - _, _ = buf.Write(msg1) - _, _ = buf.Write(msg2) - - n := 0 - for { - n++ - // read the stream as Map values - quit on io.EOF - m, raw, merr := mxj.NewMapXmlReaderRaw(buf) - if merr != nil && merr != io.EOF { - // handle error - for demo we just print it and continue - fmt.Printf("msg: %d - merr: %s\n", n, merr.Error()) - continue - } else if merr == io.EOF { - break - } - fmt.Println("\nMessage to parse:", string(*raw)) - fmt.Println("Map value for XML message:", m.StringIndent()) - - // get the values for "netid" or "idnet" key using path == "data.*" - values, _ := m.ValuesForPath("data.*") - fmt.Println("\nmsg:", n, "> path == data.* - got array of values, len:", len(values)) - for i, val := range values { - fmt.Println("ValuesForPath result array member -", i, ":", val) - fmt.Println(" k:v pairs for array member:", i) - for key, val := range val.(map[string]interface{}) { - // You'd probably want to process the value, as appropriate. - // Here we just print it out. - fmt.Println("\t\t", key, ":", val) - } - } - - // This shows what happens if you wildcard the value keys for "idnet" and "netid" - values, _ = m.ValuesForPath("data.*.*") - fmt.Println("\npath == data.*.* - got an array of values, len(v):", len(values)) - fmt.Println("(Note: values returned by ValuesForPath are at maximum depth of the tree. So just have values.)") - for i, val := range values { - fmt.Println("ValuesForPath array member -", i, ":", val) - } - } -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/gonuts1a.go b/Godeps/_workspace/src/github.com/clbanning/mxj/examples/gonuts1a.go deleted file mode 100644 index fbe58ffad..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/gonuts1a.go +++ /dev/null @@ -1,68 +0,0 @@ -// https://groups.google.com/forum/#!searchin/golang-nuts/idnet$20netid/golang-nuts/guM3ZHHqSF0/K1pBpMqQSSwJ -// http://play.golang.org/p/BFFDxphKYK - -package main - -import ( - "bytes" - "fmt" - "github.com/clbanning/mxj" - "io" -) - -// Demo how to re-label a key using mv.NewMap(). -// Need to normalize from an XML stream the tags "netid" and "idnet". -// Solution: make everything "netid". - -var msg1 = []byte(` - - - - no - default:text - default:word - - -`) - -var msg2 = []byte(` - - - - yes - default:text - default:word - - -`) - -func main() { - // let's create a message stream - buf := new(bytes.Buffer) - // load a couple of messages into it - _, _ = buf.Write(msg1) - _, _ = buf.Write(msg2) - - n := 0 - for { - n++ - // read the stream as Map values - quit on io.EOF - m, raw, merr := mxj.NewMapXmlReaderRaw(buf) - if merr != nil && merr != io.EOF { - // handle error - for demo we just print it and continue - fmt.Printf("msg: %d - merr: %s\n", n, merr.Error()) - continue - } else if merr == io.EOF { - break - } - - // the first keypair retains values if data correct - // the second keypair relabels "idnet" to "netid" - n, _ := m.NewMap("data.netid", "data.idnet:data.netid") - x, _ := n.XmlIndent("", " ") - - fmt.Println("original value:", string(raw)) - fmt.Println("new value:") - fmt.Println(string(x)) - } -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/gonuts2.go b/Godeps/_workspace/src/github.com/clbanning/mxj/examples/gonuts2.go deleted file mode 100644 index 6bd0bab73..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/gonuts2.go +++ /dev/null @@ -1,240 +0,0 @@ -// https://groups.google.com/forum/#!topic/golang-nuts/V83jUKluLnM -// http://play.golang.org/p/alWGk4MDBc - -// Here messsages come in one of three forms: -// ... list of ClaimStatusCodeRecord ... -// ... one instance of ClaimStatusCodeRecord ... -// ... empty element ... -// ValueForPath - -package main - -import ( - "fmt" - "github.com/clbanning/mxj" -) - -var xmlmsg1 = []byte(` - - - - -true -A -Initial Claim Review/Screening - - -true -B -Initial Contact Made w/ Provider - - - - - -`) - -var xmlmsg2 = []byte(` - - - - -true -A -Initial Claim Review/Screening - - - - - -`) - -var xmlmsg3 = []byte(` - - - - - - - -`) - -func main() { - xmldata := [][]byte{xmlmsg1, xmlmsg2, xmlmsg3} - fullPath(xmldata) - partPath1(xmlmsg1) - partPath2(xmlmsg1) - partPath3(xmlmsg1) - partPath4(xmlmsg1) - partPath5(xmlmsg1) - partPath6(xmlmsg1) -} - -func fullPath(xmldata [][]byte) { - for i, msg := range xmldata { - fmt.Println("\ndoc:", i) - fmt.Println(string(msg)) - // decode the XML - m, _ := mxj.NewMapXml(msg) - - // get the value for the key path of interest - path := "Envelope.Body.GetClaimStatusCodesResponse.GetClaimStatusCodesResult.ClaimStatusCodeRecord" - values, err := m.ValueForPath(path) - if err != nil { - fmt.Println("err:", err.Error()) - return - } - if values == nil { - fmt.Println("path:", path) - fmt.Println("No ClaimStatusCodesResult code records.") - continue - } - fmt.Println("\nPath:", path) - fmt.Println("Number of code records:", len(values)) - fmt.Println("values:", values, "\n") - for _, v := range values { - switch v.(type) { - case map[string]interface{}: - fmt.Println("map[string]interface{}:", v.(map[string]interface{})) - case []map[string]interface{}: - fmt.Println("[]map[string]interface{}:", v.([]map[string]interface{})) - case []interface{}: - fmt.Println("[]interface{}:", v.([]interface{})) - case interface{}: - fmt.Println("interface{}:", v.(interface{})) - } - } - } -} - -func partPath1(msg []byte) { - fmt.Println("\nmsg:", string(msg)) - m, _ := mxj.NewMapXml(msg) - fmt.Println("m:", m.StringIndent()) - path := "Envelope.Body.*.*.ClaimStatusCodeRecord" - values, err := m.ValueForPath(path) - if err != nil { - fmt.Println("err:", err.Error()) - return - } - if values == nil { - fmt.Println("path:", path) - fmt.Println("No ClaimStatusCodesResult code records.") - return - } - fmt.Println("\nPath:", path) - fmt.Println("Number of code records:", len(values)) - for n, v := range values { - fmt.Printf("\t#%d: %v\n", n, v) - } -} - -func partPath2(msg []byte) { - fmt.Println("\nmsg:", string(msg)) - m, _ := mxj.NewMapXml(msg) - fmt.Println("m:", m.StringIndent()) - path := "Envelope.Body.*.*.*" - values, err := m.ValueForPath(path) - if err != nil { - fmt.Println("err:", err.Error()) - return - } - if values == nil { - fmt.Println("path:", path) - fmt.Println("No ClaimStatusCodesResult code records.") - return - } - fmt.Println("\nPath:", path) - fmt.Println("Number of code records:", len(values)) - for n, v := range values { - fmt.Printf("\t#%d: %v\n", n, v) - } -} - -func partPath3(msg []byte) { - fmt.Println("\nmsg:", string(msg)) - m, _ := mxj.NewMapXml(msg) - fmt.Println("m:", m.StringIndent()) - path := "*.*.*.*.*" - values, err := m.ValueForPath(path) - if err != nil { - fmt.Println("err:", err.Error()) - return - } - if values == nil { - fmt.Println("path:", path) - fmt.Println("No ClaimStatusCodesResult code records.") - return - } - fmt.Println("\nPath:", path) - fmt.Println("Number of code records:", len(values)) - for n, v := range values { - fmt.Printf("\t#%d: %v\n", n, v) - } -} - -func partPath4(msg []byte) { - fmt.Println("\nmsg:", string(msg)) - m, _ := mxj.NewMapXml(msg) - fmt.Println("m:", m.StringIndent()) - path := "*.*.*.*.*.Description" - values, err := m.ValueForPath(path) - if err != nil { - fmt.Println("err:", err.Error()) - return - } - if values == nil { - fmt.Println("path:", path) - fmt.Println("No ClaimStatusCodesResult code records.") - return - } - fmt.Println("\nPath:", path) - fmt.Println("Number of code records:", len(values)) - for n, v := range values { - fmt.Printf("\t#%d: %v\n", n, v) - } -} - -func partPath5(msg []byte) { - fmt.Println("\nmsg:", string(msg)) - m, _ := mxj.NewMapXml(msg) - fmt.Println("m:", m.StringIndent()) - path := "*.*.*.*.*.*" - values, err := m.ValueForPath(path) - if err != nil { - fmt.Println("err:", err.Error()) - return - } - if values == nil { - fmt.Println("path:", path) - fmt.Println("No ClaimStatusCodesResult code records.") - return - } - fmt.Println("\nPath:", path) - fmt.Println("Number of code records:", len(values)) - for n, v := range values { - fmt.Printf("\t#%d: %v\n", n, v) - } -} - -func partPath6(msg []byte) { - fmt.Println("\nmsg:", string(msg)) - m, _ := mxj.NewMapXml(msg) - fmt.Println("m:", m.StringIndent()) - path := "*.*.*.*.*.*.*" - values, err := m.ValueForPath(path) - if err != nil { - fmt.Println("err:", err.Error()) - return - } - if values == nil { - fmt.Println("path:", path) - fmt.Println("No ClaimStatusCodesResult code records.") - return - } - fmt.Println("\nPath:", path) - fmt.Println("Number of code records:", len(values)) - for n, v := range values { - fmt.Printf("\t#%d: %v\n", n, v) - } -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/gonuts3.go b/Godeps/_workspace/src/github.com/clbanning/mxj/examples/gonuts3.go deleted file mode 100644 index 5bfe0628c..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/gonuts3.go +++ /dev/null @@ -1,47 +0,0 @@ -// https://groups.google.com/forum/#!topic/golang-nuts/cok6xasvI3w -// retrieve 'src' values from 'image' tags - -package main - -import ( - "fmt" - "github.com/clbanning/mxj" -) - -var xmldata = []byte(` - - - - - something else - - - - - - - -`) - -func main() { - fmt.Println("xmldata:", string(xmldata)) - - // get all image tag values - []interface{} - m, merr := mxj.NewMapXml(xmldata) - if merr != nil { - fmt.Println("merr:", merr.Error()) - return - } - - // grab all values for attribute "src" - // Note: attributes are prepended with a hyphen, '-'. - sources, err := m.ValuesForKey("-src") - if err != nil { - fmt.Println("err:", err.Error()) - return - } - - for _, src := range sources { - fmt.Println(src) - } -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/gonuts4.go b/Godeps/_workspace/src/github.com/clbanning/mxj/examples/gonuts4.go deleted file mode 100644 index 5ad4f9df3..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/gonuts4.go +++ /dev/null @@ -1,50 +0,0 @@ -// https://groups.google.com/forum/#!topic/golang-nuts/-N9Toa6qlu8 -// shows that you can extract attribute values directly from tag/key path. -// NOTE: attribute values are encoded by prepending a hyphen, '-'. - -package main - -import ( - "fmt" - "github.com/clbanning/mxj" -) - -var xmldata = []byte(` - - - - - - - - - - - - - - - - - - `) - -func main() { - fmt.Println("xmldata:", string(xmldata)) - - m, merr := mxj.NewMapXml(xmldata) - if merr != nil { - fmt.Println("merr:", merr) - return - } - - // Attributes are keys with prepended hyphen, '-'. - values, err := m.ValuesForPath("doc.some_tag.geoInfo.country.-name") - if err != nil { - fmt.Println("err:", err.Error()) - } - - for _, v := range values { - fmt.Println("v:", v) - } -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/gonuts5.go b/Godeps/_workspace/src/github.com/clbanning/mxj/examples/gonuts5.go deleted file mode 100644 index a1b8d16a5..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/gonuts5.go +++ /dev/null @@ -1,75 +0,0 @@ -// gonuts5.go - from https://groups.google.com/forum/#!topic/golang-nuts/MWoYY19of3o -// problem is to extract entries from by "int name=" - -package main - -import ( - "fmt" - "github.com/clbanning/mxj" -) - -var xmlData = []byte(` - - - - - - - 1 - - - - 1 - 2 - 3 - 4 - 5 - - - - - 1 - 2 - 3 - 4 - 5 - - - - -`) - -func main() { - // parse XML into a Map - m, merr := mxj.NewMapXml(xmlData) - if merr != nil { - fmt.Println("merr:", merr.Error()) - return - } - - // extract the 'list3-1-1-1' node - there'll be just 1? - // NOTE: attribute keys are prepended with '-' - lstVal, lerr := m.ValuesForPath("*.*.*.*.*", "-name:list3-1-1-1") - if lerr != nil { - fmt.Println("ierr:", lerr.Error()) - return - } - - // assuming just one value returned - create a new Map - mv := mxj.Map(lstVal[0].(map[string]interface{})) - - // extract the 'int' values by 'name' attribute: "-name" - // interate over list of 'name' values of interest - var names = []string{"field1", "field2", "field3", "field4", "field5"} - for _, n := range names { - vals, verr := mv.ValuesForKey("int", "-name:"+n) - if verr != nil { - fmt.Println("verr:", verr.Error(), len(vals)) - return - } - - // values for simple elements have key '#text' - // NOTE: there can be only one value for key '#text' - fmt.Println(n, ":", vals[0].(map[string]interface{})["#text"]) - } -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/gonuts5a.go b/Godeps/_workspace/src/github.com/clbanning/mxj/examples/gonuts5a.go deleted file mode 100644 index de60688fa..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/gonuts5a.go +++ /dev/null @@ -1,75 +0,0 @@ -// gonuts5.go - from https://groups.google.com/forum/#!topic/golang-nuts/MWoYY19of3o -// problem is to extract entries from by "int name=" - -package main - -import ( - "fmt" - "github.com/clbanning/mxj" -) - -var xmlData = []byte(` - - - - - - - 1 - - - - 1 - 2 - 3 - 4 - 5 - - - - - 1 - 2 - 3 - 4 - 5 - - - - -`) - -func main() { - // parse XML into a Map - m, merr := mxj.NewMapXml(xmlData) - if merr != nil { - fmt.Println("merr:", merr.Error()) - return - } - - // extract the 'list3-1-1-1' node - there'll be just 1? - // NOTE: attribute keys are prepended with '-' - lstVal, lerr := m.ValuesForPath("*.*.*.*.*", "-name:list3-1-1-1") - if lerr != nil { - fmt.Println("ierr:", lerr.Error()) - return - } - - // assuming just one value returned - create a new Map - mv := mxj.Map(lstVal[0].(map[string]interface{})) - - // extract the 'int' values by 'name' attribute: "-name" - // interate over list of 'name' values of interest - var names = []string{"field1", "field2", "field3", "field4", "field5"} - for _, n := range names { - vals, verr := mv.ValuesForKey("*", "-name:"+n) - if verr != nil { - fmt.Println("verr:", verr.Error(), len(vals)) - return - } - - // values for simple elements have key '#text' - // NOTE: there can be only one value for key '#text' - fmt.Println(n, ":", vals[0].(map[string]interface{})["#text"]) - } -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/gonuts6.go b/Godeps/_workspace/src/github.com/clbanning/mxj/examples/gonuts6.go deleted file mode 100644 index 56b3d29e2..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/gonuts6.go +++ /dev/null @@ -1,43 +0,0 @@ -/* https://groups.google.com/forum/#!topic/golang-nuts/EMXHB1nJoBA - -package main - -import "fmt" -import "encoding/json" - -func main() { - var v struct { - DBInstances []struct { - Endpoint struct { - Address string - } - } - } - json.Unmarshal(s, &v) - fmt.Println(v.DBInstances[0].Endpoint.Address) -} -*/ - -package main - -import "fmt" -import "github.com/clbanning/mxj" - -func main() { - m, err := mxj.NewMapJson(s) - if err != nil { - fmt.Println("err:", err.Error()) - } - v, err := m.ValuesForKey("Address") - // v, err := m.ValuesForPath("DBInstances[0].Endpoint.Address") - if err != nil { - fmt.Println("err:", err.Error()) - } - if len(v) > 0 { - fmt.Println(v[0].(string)) - } else { - fmt.Println("No value.") - } -} - -var s = []byte(`{ "DBInstances": [ { "PubliclyAccessible": true, "MasterUsername": "postgres", "LicenseModel": "postgresql-license", "VpcSecurityGroups": [ { "Status": "active", "VpcSecurityGroupId": "sg-e72a4282" } ], "InstanceCreateTime": "2014-06-29T03:52:59.268Z", "OptionGroupMemberships": [ { "Status": "in-sync", "OptionGroupName": "default:postgres-9-3" } ], "PendingModifiedValues": {}, "Engine": "postgres", "MultiAZ": true, "LatestRestorableTime": "2014-06-29T12:00:34Z", "DBSecurityGroups": [ { "Status": "active", "DBSecurityGroupName": "production-dbsecuritygroup-q4f0ugxpjck8" } ], "DBParameterGroups": [ { "DBParameterGroupName": "default.postgres9.3", "ParameterApplyStatus": "in-sync" } ], "AutoMinorVersionUpgrade": true, "PreferredBackupWindow": "06:59-07:29", "DBSubnetGroup": { "Subnets": [ { "SubnetStatus": "Active", "SubnetIdentifier": "subnet-34e5d01c", "SubnetAvailabilityZone": { "Name": "us-east-1b", "ProvisionedIopsCapable": false } }, { "SubnetStatus": "Active", "SubnetIdentifier": "subnet-50759d27", "SubnetAvailabilityZone": { "Name": "us-east-1c", "ProvisionedIopsCapable": false } }, { "SubnetStatus": "Active", "SubnetIdentifier": "subnet-450a1f03", "SubnetAvailabilityZone": { "Name": "us-east-1d", "ProvisionedIopsCapable": false } } ], "DBSubnetGroupName": "default", "VpcId": "vpc-acb86cc9", "DBSubnetGroupDescription": "default", "SubnetGroupStatus": "Complete" }, "SecondaryAvailabilityZone": "us-east-1b", "ReadReplicaDBInstanceIdentifiers": [], "AllocatedStorage": 15, "BackupRetentionPeriod": 1, "DBName": "deis", "PreferredMaintenanceWindow": "fri:05:52-fri:06:22", "Endpoint": { "Port": 5432, "Address": "production.cfk8mskkbkeu.us-east-1.rds.amazonaws.com" }, "DBInstanceStatus": "available", "EngineVersion": "9.3.3", "AvailabilityZone": "us-east-1c", "DBInstanceClass": "db.m1.small", "DBInstanceIdentifier": "production" } ] }`) diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/metrics_data.zip b/Godeps/_workspace/src/github.com/clbanning/mxj/examples/metrics_data.zip deleted file mode 100644 index 386837491..000000000 Binary files a/Godeps/_workspace/src/github.com/clbanning/mxj/examples/metrics_data.zip and /dev/null differ diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/files.go b/Godeps/_workspace/src/github.com/clbanning/mxj/files.go deleted file mode 100644 index 589711874..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/files.go +++ /dev/null @@ -1,299 +0,0 @@ -package mxj - -import ( - "fmt" - "io" - "os" -) - -type Maps []Map - -func NewMaps() Maps { - return make(Maps, 0) -} - -type MapRaw struct { - M Map - R []byte -} - -// NewMapsFromXmlFile - creates an array from a file of JSON values. -func NewMapsFromJsonFile(name string) (Maps, error) { - fi, err := os.Stat(name) - if err != nil { - return nil, err - } - if !fi.Mode().IsRegular() { - return nil, fmt.Errorf("file %s is not a regular file", name) - } - - fh, err := os.Open(name) - if err != nil { - return nil, err - } - defer fh.Close() - - am := make([]Map, 0) - for { - m, raw, err := NewMapJsonReaderRaw(fh) - if err != nil && err != io.EOF { - return am, fmt.Errorf("error: %s - reading: %s", err.Error(), string(raw)) - } - if len(m) > 0 { - am = append(am, m) - } - if err == io.EOF { - break - } - } - return am, nil -} - -// ReadMapsFromJsonFileRaw - creates an array of MapRaw from a file of JSON values. -func NewMapsFromJsonFileRaw(name string) ([]MapRaw, error) { - fi, err := os.Stat(name) - if err != nil { - return nil, err - } - if !fi.Mode().IsRegular() { - return nil, fmt.Errorf("file %s is not a regular file", name) - } - - fh, err := os.Open(name) - if err != nil { - return nil, err - } - defer fh.Close() - - am := make([]MapRaw, 0) - for { - mr := new(MapRaw) - mr.M, mr.R, err = NewMapJsonReaderRaw(fh) - if err != nil && err != io.EOF { - return am, fmt.Errorf("error: %s - reading: %s", err.Error(), string(mr.R)) - } - if len(mr.M) > 0 { - am = append(am, *mr) - } - if err == io.EOF { - break - } - } - return am, nil -} - -// NewMapsFromXmlFile - creates an array from a file of XML values. -func NewMapsFromXmlFile(name string) (Maps, error) { - x := XmlWriterBufSize - XmlWriterBufSize = 0 - defer func() { - XmlWriterBufSize = x - }() - - fi, err := os.Stat(name) - if err != nil { - return nil, err - } - if !fi.Mode().IsRegular() { - return nil, fmt.Errorf("file %s is not a regular file", name) - } - - fh, err := os.Open(name) - if err != nil { - return nil, err - } - defer fh.Close() - - am := make([]Map, 0) - for { - m, raw, err := NewMapXmlReaderRaw(fh) - if err != nil && err != io.EOF { - return am, fmt.Errorf("error: %s - reading: %s", err.Error(), string(raw)) - } - if len(m) > 0 { - am = append(am, m) - } - if err == io.EOF { - break - } - } - return am, nil -} - -// NewMapsFromXmlFileRaw - creates an array of MapRaw from a file of XML values. -// NOTE: the slice with the raw XML is clean with no extra capacity - unlike NewMapXmlReaderRaw(). -// It is slow at parsing a file from disk and is intended for relatively small utility files. -func NewMapsFromXmlFileRaw(name string) ([]MapRaw, error) { - x := XmlWriterBufSize - XmlWriterBufSize = 0 - defer func() { - XmlWriterBufSize = x - }() - - fi, err := os.Stat(name) - if err != nil { - return nil, err - } - if !fi.Mode().IsRegular() { - return nil, fmt.Errorf("file %s is not a regular file", name) - } - - fh, err := os.Open(name) - if err != nil { - return nil, err - } - defer fh.Close() - - am := make([]MapRaw, 0) - for { - mr := new(MapRaw) - mr.M, mr.R, err = NewMapXmlReaderRaw(fh) - if err != nil && err != io.EOF { - return am, fmt.Errorf("error: %s - reading: %s", err.Error(), string(mr.R)) - } - if len(mr.M) > 0 { - am = append(am, *mr) - } - if err == io.EOF { - break - } - } - return am, nil -} - -// ------------------------ Maps writing ------------------------- -// These are handy-dandy methods for dumping configuration data, etc. - -// JsonString - analogous to mv.Json() -func (mvs Maps) JsonString(safeEncoding ...bool) (string, error) { - var s string - for _, v := range mvs { - j, err := v.Json() - if err != nil { - return s, err - } - s += string(j) - } - return s, nil -} - -// JsonStringIndent - analogous to mv.JsonIndent() -func (mvs Maps) JsonStringIndent(prefix, indent string, safeEncoding ...bool) (string, error) { - var s string - var haveFirst bool - for _, v := range mvs { - j, err := v.JsonIndent(prefix, indent) - if err != nil { - return s, err - } - if haveFirst { - s += "\n" - } else { - haveFirst = true - } - s += string(j) - } - return s, nil -} - -// XmlString - analogous to mv.Xml() -func (mvs Maps) XmlString() (string, error) { - var s string - for _, v := range mvs { - x, err := v.Xml() - if err != nil { - return s, err - } - s += string(x) - } - return s, nil -} - -// XmlStringIndent - analogous to mv.XmlIndent() -func (mvs Maps) XmlStringIndent(prefix, indent string) (string, error) { - var s string - for _, v := range mvs { - x, err := v.XmlIndent(prefix, indent) - if err != nil { - return s, err - } - s += string(x) - } - return s, nil -} - -// JsonFile - write Maps to named file as JSON -// Note: the file will be created, if necessary; if it exists it will be truncated. -// If you need to append to a file, open it and use JsonWriter method. -func (mvs Maps) JsonFile(file string, safeEncoding ...bool) error { - var encoding bool - if len(safeEncoding) == 1 { - encoding = safeEncoding[0] - } - s, err := mvs.JsonString(encoding) - if err != nil { - return err - } - fh, err := os.Create(file) - if err != nil { - return err - } - defer fh.Close() - fh.WriteString(s) - return nil -} - -// JsonFileIndent - write Maps to named file as pretty JSON -// Note: the file will be created, if necessary; if it exists it will be truncated. -// If you need to append to a file, open it and use JsonIndentWriter method. -func (mvs Maps) JsonFileIndent(file, prefix, indent string, safeEncoding ...bool) error { - var encoding bool - if len(safeEncoding) == 1 { - encoding = safeEncoding[0] - } - s, err := mvs.JsonStringIndent(prefix, indent, encoding) - if err != nil { - return err - } - fh, err := os.Create(file) - if err != nil { - return err - } - defer fh.Close() - fh.WriteString(s) - return nil -} - -// XmlFile - write Maps to named file as XML -// Note: the file will be created, if necessary; if it exists it will be truncated. -// If you need to append to a file, open it and use XmlWriter method. -func (mvs Maps) XmlFile(file string) error { - s, err := mvs.XmlString() - if err != nil { - return err - } - fh, err := os.Create(file) - if err != nil { - return err - } - defer fh.Close() - fh.WriteString(s) - return nil -} - -// XmlFileIndent - write Maps to named file as pretty XML -// Note: the file will be created,if necessary; if it exists it will be truncated. -// If you need to append to a file, open it and use XmlIndentWriter method. -func (mvs Maps) XmlFileIndent(file, prefix, indent string) error { - s, err := mvs.XmlStringIndent(prefix, indent) - if err != nil { - return err - } - fh, err := os.Create(file) - if err != nil { - return err - } - defer fh.Close() - fh.WriteString(s) - return nil -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/files_test.badjson b/Godeps/_workspace/src/github.com/clbanning/mxj/files_test.badjson deleted file mode 100644 index d18720044..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/files_test.badjson +++ /dev/null @@ -1,2 +0,0 @@ -{ "this":"is", "a":"test", "file":"for", "files_test.go":"case" } -{ "with":"some", "bad":JSON, "in":"it" } diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/files_test.badxml b/Godeps/_workspace/src/github.com/clbanning/mxj/files_test.badxml deleted file mode 100644 index 4736ef973..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/files_test.badxml +++ /dev/null @@ -1,9 +0,0 @@ - - test - for files.go - - - some - doc - test case - diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/files_test.go b/Godeps/_workspace/src/github.com/clbanning/mxj/files_test.go deleted file mode 100644 index 52778aef6..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/files_test.go +++ /dev/null @@ -1,168 +0,0 @@ -package mxj - -import ( - "fmt" - "testing" -) - -func TestFilesHeader(t *testing.T) { - fmt.Println("\n---------------- files_test.go ...\n") -} - -func TestNewJsonFile(t *testing.T) { - fmt.Println("NewMapsFromJsonFile()") - am, err := NewMapsFromJsonFile("files_test.json") - if err != nil { - t.Fatal(err.Error()) - } - for _, v := range am { - fmt.Printf("%v\n", v) - } - - am, err = NewMapsFromJsonFile("nil") - if err == nil { - t.Fatal("no error returned for read of nil file") - } - fmt.Println("caught error: ", err.Error()) - - am, err = NewMapsFromJsonFile("files_test.badjson") - if err == nil { - t.Fatal("no error returned for read of badjson file") - } - fmt.Println("caught error: ", err.Error()) -} - -func TestNewJsonFileRaw(t *testing.T) { - fmt.Println("NewMapsFromJsonFileRaw()") - mr, err := NewMapsFromJsonFileRaw("files_test.json") - if err != nil { - t.Fatal(err.Error()) - } - for _, v := range mr { - fmt.Printf("%v\n", v) - } - - mr, err = NewMapsFromJsonFileRaw("nil") - if err == nil { - t.Fatal("no error returned for read of nil file") - } - fmt.Println("caught error: ", err.Error()) - - mr, err = NewMapsFromJsonFileRaw("files_test.badjson") - if err == nil { - t.Fatal("no error returned for read of badjson file") - } - fmt.Println("caught error: ", err.Error()) -} - -func TestNewXmFile(t *testing.T) { - fmt.Println("NewMapsFromXmlFile()") - am, err := NewMapsFromXmlFile("files_test.xml") - if err != nil { - t.Fatal(err.Error()) - } - for _, v := range am { - fmt.Printf("%v\n", v) - } - - am, err = NewMapsFromXmlFile("nil") - if err == nil { - t.Fatal("no error returned for read of nil file") - } - fmt.Println("caught error: ", err.Error()) - - am, err = NewMapsFromXmlFile("files_test.badxml") - if err == nil { - t.Fatal("no error returned for read of badjson file") - } - fmt.Println("caught error: ", err.Error()) -} - -func TestNewXmFileRaw(t *testing.T) { - fmt.Println("NewMapsFromXmlFileRaw()") - mr, err := NewMapsFromXmlFileRaw("files_test.xml") - if err != nil { - t.Fatal(err.Error()) - } - for _, v := range mr { - fmt.Printf("%v\n", v) - } - - mr, err = NewMapsFromXmlFileRaw("nil") - if err == nil { - t.Fatal("no error returned for read of nil file") - } - fmt.Println("caught error: ", err.Error()) - - mr, err = NewMapsFromXmlFileRaw("files_test.badxml") - if err == nil { - t.Fatal("no error returned for read of badjson file") - } - fmt.Println("caught error: ", err.Error()) -} - -func TestMaps(t *testing.T) { - fmt.Println("TestMaps()") - mvs := NewMaps() - for i := 0; i < 2; i++ { - m, _ := NewMapJson([]byte(`{ "this":"is", "a":"test" }`)) - mvs = append(mvs, m) - } - fmt.Println("mvs:", mvs) - - s, _ := mvs.JsonString() - fmt.Println("JsonString():", s) - - s, _ = mvs.JsonStringIndent("", " ") - fmt.Println("JsonStringIndent():", s) - - s, _ = mvs.XmlString() - fmt.Println("XmlString():", s) - - s, _ = mvs.XmlStringIndent("", " ") - fmt.Println("XmlStringIndent():", s) -} - -func TestJsonFile(t *testing.T) { - am, err := NewMapsFromJsonFile("files_test.json") - if err != nil { - t.Fatal(err.Error()) - } - for _, v := range am { - fmt.Printf("%v\n", v) - } - - err = am.JsonFile("files_test_dup.json") - if err != nil { - t.Fatal(err.Error()) - } - fmt.Println("files_test_dup.json written") - - err = am.JsonFileIndent("files_test_indent.json", "", " ") - if err != nil { - t.Fatal(err.Error()) - } - fmt.Println("files_test_indent.json written") -} - -func TestXmlFile(t *testing.T) { - am, err := NewMapsFromXmlFile("files_test.xml") - if err != nil { - t.Fatal(err.Error()) - } - for _, v := range am { - fmt.Printf("%v\n", v) - } - - err = am.XmlFile("files_test_dup.xml") - if err != nil { - t.Fatal(err.Error()) - } - fmt.Println("files_test_dup.xml written") - - err = am.XmlFileIndent("files_test_indent.xml", "", " ") - if err != nil { - t.Fatal(err.Error()) - } - fmt.Println("files_test_indent.xml written") -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/files_test.json b/Godeps/_workspace/src/github.com/clbanning/mxj/files_test.json deleted file mode 100644 index e9a3ddf40..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/files_test.json +++ /dev/null @@ -1,2 +0,0 @@ -{ "this":"is", "a":"test", "file":"for", "files_test.go":"case" } -{ "with":"just", "two":2, "JSON":"values", "true":true } diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/files_test.xml b/Godeps/_workspace/src/github.com/clbanning/mxj/files_test.xml deleted file mode 100644 index 65cf021fb..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/files_test.xml +++ /dev/null @@ -1,9 +0,0 @@ - - test - for files.go - - - some - doc - test case - diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/files_test_dup.json b/Godeps/_workspace/src/github.com/clbanning/mxj/files_test_dup.json deleted file mode 100644 index 2becb6a45..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/files_test_dup.json +++ /dev/null @@ -1 +0,0 @@ -{"a":"test","file":"for","files_test.go":"case","this":"is"}{"JSON":"values","true":true,"two":2,"with":"just"} \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/files_test_dup.xml b/Godeps/_workspace/src/github.com/clbanning/mxj/files_test_dup.xml deleted file mode 100644 index aa63dda77..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/files_test_dup.xml +++ /dev/null @@ -1 +0,0 @@ -testfor files.gosomedoctest case \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/files_test_indent.json b/Godeps/_workspace/src/github.com/clbanning/mxj/files_test_indent.json deleted file mode 100644 index 6fde15634..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/files_test_indent.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "a": "test", - "file": "for", - "files_test.go": "case", - "this": "is" -} -{ - "JSON": "values", - "true": true, - "two": 2, - "with": "just" -} \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/files_test_indent.xml b/Godeps/_workspace/src/github.com/clbanning/mxj/files_test_indent.xml deleted file mode 100644 index febee213c..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/files_test_indent.xml +++ /dev/null @@ -1,8 +0,0 @@ - - test - for files.go - - some - doc - test case - \ No newline at end of file diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/j2x/j2x.go b/Godeps/_workspace/src/github.com/clbanning/mxj/j2x/j2x.go deleted file mode 100644 index 868c55a5b..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/j2x/j2x.go +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright 2012-2014 Charles Banning. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file - -// j2x.go - For (mostly) backwards compatibility with legacy j2x package. -// Wrappers for end-to-end JSON to XML transformation and value manipulation. -package j2x - -import ( - . "github.com/clbanning/mxj" - "io" -) - -// FromJson() --> map[string]interface{} -func JsonToMap(jsonVal []byte) (map[string]interface{}, error) { - return NewMapJson(jsonVal) -} - -// interface{} --> ToJson (w/o safe encoding, default) { -func MapToJson(m map[string]interface{}, safeEncoding ...bool) ([]byte, error) { - return Map(m).Json() -} - -// FromJson() --> ToXml(). -func JsonToXml(jsonVal []byte) ([]byte, error) { - m, err := NewMapJson(jsonVal) - if err != nil { - return nil, err - } - return m.Xml() -} - -// FromJson() --> ToXmlWriter(). -func JsonToXmlWriter(jsonVal []byte, xmlWriter io.Writer) ([]byte, error) { - m, err := NewMapJson(jsonVal) - if err != nil { - return nil, err - } - return m.XmlWriterRaw(xmlWriter) -} - -// FromJsonReader() --> ToXml(). -func JsonReaderToXml(jsonReader io.Reader) ([]byte, []byte, error) { - m, jraw, err := NewMapJsonReaderRaw(jsonReader) - if err != nil { - return jraw, nil, err - } - x, xerr := m.Xml() - return jraw, x, xerr -} - -// FromJsonReader() --> ToXmlWriter(). Handy for transforming bulk message sets. -func JsonReaderToXmlWriter(jsonReader io.Reader, xmlWriter io.Writer) ([]byte, []byte, error) { - m, jraw, err := NewMapJsonReaderRaw(jsonReader) - if err != nil { - return jraw, nil, err - } - xraw, xerr := m.XmlWriterRaw(xmlWriter) - return jraw, xraw, xerr -} - -// JSON wrappers for Map methods implementing key path and value functions. - -// Wrap PathsForKey for JSON. -func JsonPathsForKey(jsonVal []byte, key string) ([]string, error) { - m, err := NewMapJson(jsonVal) - if err != nil { - return nil, err - } - paths := m.PathsForKey(key) - return paths, nil -} - -// Wrap PathForKeyShortest for JSON. -func JsonPathForKeyShortest(jsonVal []byte, key string) (string, error) { - m, err := NewMapJson(jsonVal) - if err != nil { - return "", err - } - path := m.PathForKeyShortest(key) - return path, nil -} - -// Wrap ValuesForKey for JSON. -func JsonValuesForKey(jsonVal []byte, key string, subkeys ...string) ([]interface{}, error) { - m, err := NewMapJson(jsonVal) - if err != nil { - return nil, err - } - return m.ValuesForKey(key, subkeys...) -} - -// Wrap ValuesForKeyPath for JSON. -func JsonValuesForKeyPath(jsonVal []byte, path string, subkeys ...string) ([]interface{}, error) { - m, err := NewMapJson(jsonVal) - if err != nil { - return nil, err - } - return m.ValuesForPath(path, subkeys...) -} - -// Wrap UpdateValuesForPath for JSON -// 'jsonVal' is XML value -// 'newKeyValue' is the value to replace an existing value at the end of 'path' -// 'path' is the dot-notation path with the key whose value is to be replaced at the end -// (can include wildcard character, '*') -// 'subkeys' are key:value pairs of key:values that must match for the key -func JsonUpdateValsForPath(jsonVal []byte, newKeyValue interface{}, path string, subkeys ...string) ([]byte, error) { - m, err := NewMapJson(jsonVal) - if err != nil { - return nil, err - } - _, err = m.UpdateValuesForPath(newKeyValue, path, subkeys...) - if err != nil { - return nil, err - } - return m.Json() -} - -// Wrap NewMap for JSON and return as JSON -// 'jsonVal' is an JSON value -// 'keypairs' are "oldKey:newKey" values that conform to 'keypairs' in (Map)NewMap. -func JsonNewJson(jsonVal []byte, keypairs ...string) ([]byte, error) { - m, err := NewMapJson(jsonVal) - if err != nil { - return nil, err - } - n, err := m.NewMap(keypairs...) - if err != nil { - return nil, err - } - return n.Json() -} - -// Wrap NewMap for JSON and return as XML -// 'jsonVal' is an JSON value -// 'keypairs' are "oldKey:newKey" values that conform to 'keypairs' in (Map)NewMap. -func JsonNewXml(jsonVal []byte, keypairs ...string) ([]byte, error) { - m, err := NewMapJson(jsonVal) - if err != nil { - return nil, err - } - n, err := m.NewMap(keypairs...) - if err != nil { - return nil, err - } - return n.Xml() -} - -// Wrap LeafNodes for JSON. -// 'jsonVal' is an JSON value -func JsonLeafNodes(jsonVal []byte) ([]LeafNode, error) { - m, err := NewMapJson(jsonVal) - if err != nil { - return nil, err - } - return m.LeafNodes(), nil -} - -// Wrap LeafValues for JSON. -// 'jsonVal' is an JSON value -func JsonLeafValues(jsonVal []byte) ([]interface{}, error) { - m, err := NewMapJson(jsonVal) - if err != nil { - return nil, err - } - return m.LeafValues(), nil -} - -// Wrap LeafPath for JSON. -// 'xmlVal' is an JSON value -func JsonLeafPath(jsonVal []byte) ([]string, error) { - m, err := NewMapJson(jsonVal) - if err != nil { - return nil, err - } - return m.LeafPaths(), nil -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/j2x/j2x_test.go b/Godeps/_workspace/src/github.com/clbanning/mxj/j2x/j2x_test.go deleted file mode 100644 index 4a25605cb..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/j2x/j2x_test.go +++ /dev/null @@ -1,67 +0,0 @@ -// thanks to Chris Malek (chris.r.malek@gmail.com) for suggestion to handle JSON list docs. - -package j2x - -import ( - "bytes" - "fmt" - "io/ioutil" - "testing" -) - -func TestJsonToXml_1(t *testing.T) { - // mimic a io.Reader - // Body := bytes.NewReader([]byte(`{"some-null-value":"", "a-non-null-value":"bar"}`)) - Body := bytes.NewReader([]byte(`[{"some-null-value":"", "a-non-null-value":"bar"}]`)) - - //body, err := ioutil.ReadAll(req.Body) - body, err := ioutil.ReadAll(Body) - if err != nil { - t.Fatal(err) - } - fmt.Println(string(body)) - //if err != nil { - // t.Fatal(err) - //} - - var xmloutput []byte - //xmloutput, err = j2x.JsonToXml(body) - xmloutput, err = JsonToXml(body) - - //log.Println(string(xmloutput)) - - if err != nil { - t.Fatal(err) - // log.Println(err) - // http.Error(rw, "Could not convert to xml", 400) - } - fmt.Println("xmloutput:", string(xmloutput)) -} - -func TestJsonToXml_2(t *testing.T) { - // mimic a io.Reader - Body := bytes.NewReader([]byte(`{"somekey":[{"value":"1st"},{"value":"2nd"}]}`)) - - //body, err := ioutil.ReadAll(req.Body) - body, err := ioutil.ReadAll(Body) - if err != nil { - t.Fatal(err) - } - fmt.Println(string(body)) - //if err != nil { - // t.Fatal(err) - //} - - var xmloutput []byte - //xmloutput, err = j2x.JsonToXml(body) - xmloutput, err = JsonToXml(body) - - //log.Println(string(xmloutput)) - - if err != nil { - t.Fatal(err) - // log.Println(err) - // http.Error(rw, "Could not convert to xml", 400) - } - fmt.Println("xmloutput:", string(xmloutput)) -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/j2x_test.go b/Godeps/_workspace/src/github.com/clbanning/mxj/j2x_test.go deleted file mode 100644 index b88a64d57..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/j2x_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package mxj - -import ( - "fmt" - "testing" -) - -var jjdata = []byte(`{ "key1":"string", "key2":34, "key3":true, "key4":"unsafe: <>&", "key5":null }`) - -func TestJ2XHeader(t *testing.T) { - fmt.Println("\n---------------- j2x_test .go ...\n") -} - -func TestJ2X(t *testing.T) { - - m, err := NewMapJson(jjdata) - if err != nil { - t.Fatal("NewMapJson, err:", err) - } - - x, err := m.Xml() - if err != nil { - t.Fatal("m.Xml(), err:", err) - } - - fmt.Println("j2x, jdata:", string(jjdata)) - fmt.Println("j2x, m :", m) - fmt.Println("j2x, xml :", string(x)) -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/json.go b/Godeps/_workspace/src/github.com/clbanning/mxj/json.go deleted file mode 100644 index 34c1c0b33..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/json.go +++ /dev/null @@ -1,319 +0,0 @@ -// Copyright 2012-2014 Charles Banning. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file - -package mxj - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "time" -) - -// ------------------------------ write JSON ----------------------- - -// Just a wrapper on json.Marshal. -// If option safeEncoding is'true' then safe encoding of '<', '>' and '&' -// is preserved. (see encoding/json#Marshal, encoding/json#Encode) -func (mv Map) Json(safeEncoding ...bool) ([]byte, error) { - var s bool - if len(safeEncoding) == 1 { - s = safeEncoding[0] - } - - b, err := json.Marshal(mv) - - if !s { - b = bytes.Replace(b, []byte("\\u003c"), []byte("<"), -1) - b = bytes.Replace(b, []byte("\\u003e"), []byte(">"), -1) - b = bytes.Replace(b, []byte("\\u0026"), []byte("&"), -1) - } - return b, err -} - -// Just a wrapper on json.MarshalIndent. -// If option safeEncoding is'true' then safe encoding of '<' , '>' and '&' -// is preserved. (see encoding/json#Marshal, encoding/json#Encode) -func (mv Map) JsonIndent(prefix, indent string, safeEncoding ...bool) ([]byte, error) { - var s bool - if len(safeEncoding) == 1 { - s = safeEncoding[0] - } - - b, err := json.MarshalIndent(mv, prefix, indent) - if !s { - b = bytes.Replace(b, []byte("\\u003c"), []byte("<"), -1) - b = bytes.Replace(b, []byte("\\u003e"), []byte(">"), -1) - b = bytes.Replace(b, []byte("\\u0026"), []byte("&"), -1) - } - return b, err -} - -// The following implementation is provided for symmetry with NewMapJsonReader[Raw] -// The names will also provide a key for the number of return arguments. - -// Writes the Map as JSON on the Writer. -// If 'safeEncoding' is 'true', then "safe" encoding of '<', '>' and '&' is preserved. -func (mv Map) JsonWriter(jsonWriter io.Writer, safeEncoding ...bool) error { - b, err := mv.Json(safeEncoding...) - if err != nil { - return err - } - - _, err = jsonWriter.Write(b) - return err -} - -// Writes the Map as JSON on the Writer. []byte is the raw JSON that was written. -// If 'safeEncoding' is 'true', then "safe" encoding of '<', '>' and '&' is preserved. -func (mv Map) JsonWriterRaw(jsonWriter io.Writer, safeEncoding ...bool) ([]byte, error) { - b, err := mv.Json(safeEncoding...) - if err != nil { - return b, err - } - - _, err = jsonWriter.Write(b) - return b, err -} - -// Writes the Map as pretty JSON on the Writer. -// If 'safeEncoding' is 'true', then "safe" encoding of '<', '>' and '&' is preserved. -func (mv Map) JsonIndentWriter(jsonWriter io.Writer, prefix, indent string, safeEncoding ...bool) error { - b, err := mv.JsonIndent(prefix, indent, safeEncoding...) - if err != nil { - return err - } - - _, err = jsonWriter.Write(b) - return err -} - -// Writes the Map as pretty JSON on the Writer. []byte is the raw JSON that was written. -// If 'safeEncoding' is 'true', then "safe" encoding of '<', '>' and '&' is preserved. -func (mv Map) JsonIndentWriterRaw(jsonWriter io.Writer, prefix, indent string, safeEncoding ...bool) ([]byte, error) { - b, err := mv.JsonIndent(prefix, indent, safeEncoding...) - if err != nil { - return b, err - } - - _, err = jsonWriter.Write(b) - return b, err -} - -// --------------------------- read JSON ----------------------------- - -// Parse numeric values as json.Number types - see encoding/json#Number -var JsonUseNumber bool - -// Just a wrapper on json.Unmarshal -// Converting JSON to XML is a simple as: -// ... -// mapVal, merr := mxj.NewMapJson(jsonVal) -// if merr != nil { -// // handle error -// } -// xmlVal, xerr := mapVal.Xml() -// if xerr != nil { -// // handle error -// } -// NOTE: as a special case, passing a list, e.g., [{"some-null-value":"", "a-non-null-value":"bar"}], -// will be interpreted as having the root key 'object' prepended - {"object":[ ... ]} - to unmarshal to a Map. -// See mxj/j2x/j2x_test.go. -func NewMapJson(jsonVal []byte) (Map, error) { - // empty or nil begets empty - if len(jsonVal) == 0 { - m := make(map[string]interface{}, 0) - return m, nil - } - // handle a goofy case ... - if jsonVal[0] == '[' { - jsonVal = []byte(`{"object":` + string(jsonVal) + `}`) - } - m := make(map[string]interface{}) - // err := json.Unmarshal(jsonVal, &m) - buf := bytes.NewReader(jsonVal) - dec := json.NewDecoder(buf) - if JsonUseNumber { - dec.UseNumber() - } - err := dec.Decode(&m) - return m, err -} - -// Retrieve a Map value from an io.Reader. -// NOTE: The raw JSON off the reader is buffered to []byte using a ByteReader. If the io.Reader is an -// os.File, there may be significant performance impact. If the io.Reader is wrapping a []byte -// value in-memory, however, such as http.Request.Body you CAN use it to efficiently unmarshal -// a JSON object. -func NewMapJsonReader(jsonReader io.Reader) (Map, error) { - jb, err := getJson(jsonReader) - if err != nil || len(*jb) == 0 { - return nil, err - } - - // Unmarshal the 'presumed' JSON string - return NewMapJson(*jb) -} - -// Retrieve a Map value and raw JSON - []byte - from an io.Reader. -// NOTE: The raw JSON off the reader is buffered to []byte using a ByteReader. If the io.Reader is an -// os.File, there may be significant performance impact. If the io.Reader is wrapping a []byte -// value in-memory, however, such as http.Request.Body you CAN use it to efficiently unmarshal -// a JSON object and retrieve the raw JSON in a single call. -func NewMapJsonReaderRaw(jsonReader io.Reader) (Map, []byte, error) { - jb, err := getJson(jsonReader) - if err != nil || len(*jb) == 0 { - return nil, *jb, err - } - - // Unmarshal the 'presumed' JSON string - m, merr := NewMapJson(*jb) - return m, *jb, merr -} - -// Pull the next JSON string off the stream: just read from first '{' to its closing '}'. -// Returning a pointer to the slice saves 16 bytes - maybe unnecessary, but internal to package. -func getJson(rdr io.Reader) (*[]byte, error) { - bval := make([]byte, 1) - jb := make([]byte, 0) - var inQuote, inJson bool - var parenCnt int - var previous byte - - // scan the input for a matched set of {...} - // json.Unmarshal will handle syntax checking. - for { - _, err := rdr.Read(bval) - if err != nil { - if err == io.EOF && inJson && parenCnt > 0 { - return &jb, fmt.Errorf("no closing } for JSON string: %s", string(jb)) - } - return &jb, err - } - switch bval[0] { - case '{': - if !inQuote { - parenCnt++ - inJson = true - } - case '}': - if !inQuote { - parenCnt-- - } - if parenCnt < 0 { - return nil, fmt.Errorf("closing } without opening {: %s", string(jb)) - } - case '"': - if inQuote { - if previous == '\\' { - break - } - inQuote = false - } else { - inQuote = true - } - case '\n', '\r', '\t', ' ': - if !inQuote { - continue - } - } - if inJson { - jb = append(jb, bval[0]) - if parenCnt == 0 { - break - } - } - previous = bval[0] - } - - return &jb, nil -} - -// ------------------------------- JSON Reader handler via Map values ----------------------- - -// Default poll delay to keep Handler from spinning on an open stream -// like sitting on os.Stdin waiting for imput. -var jhandlerPollInterval = time.Duration(1e6) - -// While unnecessary, we make HandleJsonReader() have the same signature as HandleXmlReader(). -// This avoids treating one or other as a special case and discussing the underlying stdlib logic. - -// Bulk process JSON using handlers that process a Map value. -// 'rdr' is an io.Reader for the JSON (stream). -// 'mapHandler' is the Map processing handler. Return of 'false' stops io.Reader processing. -// 'errHandler' is the error processor. Return of 'false' stops io.Reader processing and returns the error. -// Note: mapHandler() and errHandler() calls are blocking, so reading and processing of messages is serialized. -// This means that you can stop reading the file on error or after processing a particular message. -// To have reading and handling run concurrently, pass argument to a go routine in handler and return 'true'. -func HandleJsonReader(jsonReader io.Reader, mapHandler func(Map) bool, errHandler func(error) bool) error { - var n int - for { - m, merr := NewMapJsonReader(jsonReader) - n++ - - // handle error condition with errhandler - if merr != nil && merr != io.EOF { - merr = fmt.Errorf("[jsonReader: %d] %s", n, merr.Error()) - if ok := errHandler(merr); !ok { - // caused reader termination - return merr - } - continue - } - - // pass to maphandler - if len(m) != 0 { - if ok := mapHandler(m); !ok { - break - } - } else if merr != io.EOF { - <-time.After(jhandlerPollInterval) - } - - if merr == io.EOF { - break - } - } - return nil -} - -// Bulk process JSON using handlers that process a Map value and the raw JSON. -// 'rdr' is an io.Reader for the JSON (stream). -// 'mapHandler' is the Map and raw JSON - []byte - processor. Return of 'false' stops io.Reader processing. -// 'errHandler' is the error and raw JSON processor. Return of 'false' stops io.Reader processing and returns the error. -// Note: mapHandler() and errHandler() calls are blocking, so reading and processing of messages is serialized. -// This means that you can stop reading the file on error or after processing a particular message. -// To have reading and handling run concurrently, pass argument(s) to a go routine in handler and return 'true'. -func HandleJsonReaderRaw(jsonReader io.Reader, mapHandler func(Map, []byte) bool, errHandler func(error, []byte) bool) error { - var n int - for { - m, raw, merr := NewMapJsonReaderRaw(jsonReader) - n++ - - // handle error condition with errhandler - if merr != nil && merr != io.EOF { - merr = fmt.Errorf("[jsonReader: %d] %s", n, merr.Error()) - if ok := errHandler(merr, raw); !ok { - // caused reader termination - return merr - } - continue - } - - // pass to maphandler - if len(m) != 0 { - if ok := mapHandler(m, raw); !ok { - break - } - } else if merr != io.EOF { - <-time.After(jhandlerPollInterval) - } - - if merr == io.EOF { - break - } - } - return nil -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/json_test.go b/Godeps/_workspace/src/github.com/clbanning/mxj/json_test.go deleted file mode 100644 index 7c97d2f79..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/json_test.go +++ /dev/null @@ -1,137 +0,0 @@ -package mxj - -import ( - "bytes" - "fmt" - "io" - "testing" -) - -var jdata = []byte(`{ "key1":"string", "key2":34, "key3":true, "key4":"unsafe: <>&", "key5":null }`) -var jdata2 = []byte(`{ "key1":"string", "key2":34, "key3":true, "key4":"unsafe: <>&" }, - { "key":"value in new JSON string" }`) - -func TestJsonHeader(t *testing.T) { - fmt.Println("\n---------------- json_test.go ...\n") -} - -func TestNewMapJson(t *testing.T) { - - m, merr := NewMapJson(jdata) - if merr != nil { - t.Fatal("NewMapJson, merr:", merr.Error()) - } - - fmt.Println("NewMapJson, jdata:", string(jdata)) - fmt.Printf("NewMapJson, m : %#v\n", m) -} - -func TestNewMapJsonNumber(t *testing.T) { - - JsonUseNumber = true - - m, merr := NewMapJson(jdata) - if merr != nil { - t.Fatal("NewMapJson, merr:", merr.Error()) - } - - fmt.Println("NewMapJson, jdata:", string(jdata)) - fmt.Printf("NewMapJson, m : %#v\n", m) - - JsonUseNumber = false -} - -func TestNewMapJsonError(t *testing.T) { - - m, merr := NewMapJson(jdata[:len(jdata)-2]) - if merr == nil { - t.Fatal("NewMapJsonError, m:", m) - } - - fmt.Println("NewMapJsonError, jdata :", string(jdata[:len(jdata)-2])) - fmt.Println("NewMapJsonError, merror:", merr.Error()) - - newData := []byte(`{ "this":"is", "in":error }`) - m, merr = NewMapJson(newData) - if merr == nil { - t.Fatal("NewMapJsonError, m:", m) - } - - fmt.Println("NewMapJsonError, newData :", string(newData)) - fmt.Println("NewMapJsonError, merror :", merr.Error()) -} - -func TestNewMapJsonReader(t *testing.T) { - - rdr := bytes.NewBuffer(jdata2) - - for { - m, jb, merr := NewMapJsonReaderRaw(rdr) - if merr != nil && merr != io.EOF { - t.Fatal("NewMapJsonReader, merr:", merr.Error()) - } - if merr == io.EOF { - break - } - - fmt.Println("NewMapJsonReader, jb:", string(jb)) - fmt.Printf("NewMapJsonReader, m : %#v\n", m) - } -} - -func TestNewMapJsonReaderNumber(t *testing.T) { - - JsonUseNumber = true - - rdr := bytes.NewBuffer(jdata2) - - for { - m, jb, merr := NewMapJsonReaderRaw(rdr) - if merr != nil && merr != io.EOF { - t.Fatal("NewMapJsonReader, merr:", merr.Error()) - } - if merr == io.EOF { - break - } - - fmt.Println("NewMapJsonReader, jb:", string(jb)) - fmt.Printf("NewMapJsonReader, m : %#v\n", m) - } - - JsonUseNumber = false -} - -func TestJson(t *testing.T) { - - m, _ := NewMapJson(jdata) - - j, jerr := m.Json() - if jerr != nil { - t.Fatal("Json, jerr:", jerr.Error()) - } - - fmt.Println("Json, jdata:", string(jdata)) - fmt.Println("Json, j :", string(j)) - - j, _ = m.Json(true) - fmt.Println("Json, j safe:", string(j)) -} - -func TestJsonWriter(t *testing.T) { - mv := Map(map[string]interface{}{"this": "is a", "float": 3.14159, "and": "a", "bool": true}) - - w := new(bytes.Buffer) - raw, err := mv.JsonWriterRaw(w) - if err != nil { - t.Fatal("err:", err.Error()) - } - - b := make([]byte, w.Len()) - _, err = w.Read(b) - if err != nil { - t.Fatal("err:", err.Error()) - } - - fmt.Println("JsonWriter, raw:", string(raw)) - fmt.Println("JsonWriter, b :", string(b)) -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/keyvalues.go b/Godeps/_workspace/src/github.com/clbanning/mxj/keyvalues.go deleted file mode 100644 index 4fc951853..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/keyvalues.go +++ /dev/null @@ -1,620 +0,0 @@ -// Copyright 2012-2014 Charles Banning. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file - -// keyvalues.go: Extract values from an arbitrary XML doc. Tag path can include wildcard characters. - -package mxj - -import ( - "fmt" - "strconv" - "strings" -) - -// ----------------------------- get everything FOR a single key ------------------------- - -const ( - minArraySize = 32 -) - -var defaultArraySize int = minArraySize - -// Adjust the buffers for expected number of values to return from ValuesForKey() and ValuesForPath(). -// This can have the effect of significantly reducing memory allocation-copy functions for large data sets. -// Returns the initial buffer size. -func SetArraySize(size int) int { - if size > minArraySize { - defaultArraySize = size - } else { - defaultArraySize = minArraySize - } - return defaultArraySize -} - -// Return all values in Map, 'mv', associated with a 'key'. If len(returned_values) == 0, then no match. -// On error, the returned array is 'nil'. NOTE: 'key' can be wildcard, "*". -// 'subkeys' (optional) are "key:val[:type]" strings representing attributes or elements in a list. -// - By default 'val' is of type string. "key:val:bool" and "key:val:float" to coerce them. -// - For attributes prefix the label with a hyphen, '-', e.g., "-seq:3". -// - If the 'key' refers to a list, then "key:value" could select a list member of the list. -// - The subkey can be wildcarded - "key:*" - to require that it's there with some value. -// - If a subkey is preceeded with the '!' character, the key:value[:type] entry is treated as an -// exclusion critera - e.g., "!author:William T. Gaddis". -func (mv Map) ValuesForKey(key string, subkeys ...string) ([]interface{}, error) { - m := map[string]interface{}(mv) - var subKeyMap map[string]interface{} - if len(subkeys) > 0 { - var err error - subKeyMap, err = getSubKeyMap(subkeys...) - if err != nil { - return nil, err - } - } - - ret := make([]interface{}, 0, defaultArraySize) - var cnt int - hasKey(m, key, &ret, &cnt, subKeyMap) - return ret[:cnt], nil - // ret := make([]interface{}, 0) - // hasKey(m, key, &ret, subKeyMap) - // return ret, nil -} - -// hasKey - if the map 'key' exists append it to array -// if it doesn't do nothing except scan array and map values -func hasKey(iv interface{}, key string, ret *[]interface{}, cnt *int, subkeys map[string]interface{}) { - // func hasKey(iv interface{}, key string, ret *[]interface{}, subkeys map[string]interface{}) { - switch iv.(type) { - case map[string]interface{}: - vv := iv.(map[string]interface{}) - // see if the current value is of interest - if v, ok := vv[key]; ok { - switch v.(type) { - case map[string]interface{}: - if hasSubKeys(v, subkeys) { - *ret = append(*ret, v) - *cnt++ - } - case []interface{}: - for _, av := range v.([]interface{}) { - if hasSubKeys(av, subkeys) { - *ret = append(*ret, av) - *cnt++ - } - } - default: - if len(subkeys) == 0 { - *ret = append(*ret, v) - *cnt++ - } - } - } - - // wildcard case - if key == "*" { - for _, v := range vv { - switch v.(type) { - case map[string]interface{}: - if hasSubKeys(v, subkeys) { - *ret = append(*ret, v) - *cnt++ - } - case []interface{}: - for _, av := range v.([]interface{}) { - if hasSubKeys(av, subkeys) { - *ret = append(*ret, av) - *cnt++ - } - } - default: - if len(subkeys) == 0 { - *ret = append(*ret, v) - *cnt++ - } - } - } - } - - // scan the rest - for _, v := range vv { - hasKey(v, key, ret, cnt, subkeys) - // hasKey(v, key, ret, subkeys) - } - case []interface{}: - for _, v := range iv.([]interface{}) { - hasKey(v, key, ret, cnt, subkeys) - // hasKey(v, key, ret, subkeys) - } - } -} - -// ----------------------- get everything for a node in the Map --------------------------- - -// Allow indexed arrays in "path" specification. (Request from Abhijit Kadam - abhijitk100@gmail.com.) -// 2014.04.28 - implementation note. -// Implemented as a wrapper of (old)ValuesForPath() because we need look-ahead logic to handle expansion -// of wildcards and unindexed arrays. Embedding such logic into valuesForKeyPath() would have made the -// code much more complicated; this wrapper is straightforward, easy to debug, and doesn't add significant overhead. - -// Retrieve all values for a path from the Map. If len(returned_values) == 0, then no match. -// On error, the returned array is 'nil'. -// 'path' is a dot-separated path of key values. -// - If a node in the path is '*', then everything beyond is walked. -// - 'path' can contain indexed array references, such as, "*.data[1]" and "msgs[2].data[0].field" - -// even "*[2].*[0].field". -// 'subkeys' (optional) are "key:val[:type]" strings representing attributes or elements in a list. -// - By default 'val' is of type string. "key:val:bool" and "key:val:float" to coerce them. -// - For attributes prefix the label with a hyphen, '-', e.g., "-seq:3". -// - If the 'path' refers to a list, then "tag:value" would return member of the list. -// - The subkey can be wildcarded - "key:*" - to require that it's there with some value. -// - If a subkey is preceeded with the '!' character, the key:value[:type] entry is treated as an -// exclusion critera - e.g., "!author:William T. Gaddis". -func (mv Map) ValuesForPath(path string, subkeys ...string) ([]interface{}, error) { - // If there are no array indexes in path, use legacy ValuesForPath() logic. - if strings.Index(path, "[") < 0 { - return mv.oldValuesForPath(path, subkeys...) - } - - var subKeyMap map[string]interface{} - if len(subkeys) > 0 { - var err error - subKeyMap, err = getSubKeyMap(subkeys...) - if err != nil { - return nil, err - } - } - - keys, kerr := parsePath(path) - if kerr != nil { - return nil, kerr - } - - vals, verr := valuesForArray(keys, mv) - if verr != nil { - return nil, verr // Vals may be nil, but return empty array. - } - - // Need to handle subkeys ... only return members of vals that satisfy conditions. - retvals := make([]interface{}, 0) - for _, v := range vals { - if hasSubKeys(v, subKeyMap) { - retvals = append(retvals, v) - } - } - return retvals, nil -} - -func valuesForArray(keys []*key, m Map) ([]interface{}, error) { - var tmppath string - var haveFirst bool - var vals []interface{} - var verr error - - lastkey := len(keys) - 1 - for i := 0; i <= lastkey; i++ { - if !haveFirst { - tmppath = keys[i].name - haveFirst = true - } else { - tmppath += "." + keys[i].name - } - - // Look-ahead: explode wildcards and unindexed arrays. - // Need to handle un-indexed list recursively: - // e.g., path is "stuff.data[0]" rather than "stuff[0].data[0]". - // Need to treat it as "stuff[0].data[0]", "stuff[1].data[0]", ... - if !keys[i].isArray && i < lastkey && keys[i+1].isArray { - // Can't pass subkeys because we may not be at literal end of path. - vv, vverr := m.oldValuesForPath(tmppath) - if vverr != nil { - return nil, vverr - } - for _, v := range vv { - // See if we can walk the value. - am, ok := v.(map[string]interface{}) - if !ok { - continue - } - // Work the backend. - nvals, nvalserr := valuesForArray(keys[i+1:], Map(am)) - if nvalserr != nil { - return nil, nvalserr - } - vals = append(vals, nvals...) - } - break // have recursed the whole path - return - } - - if keys[i].isArray || i == lastkey { - // Don't pass subkeys because may not be at literal end of path. - vals, verr = m.oldValuesForPath(tmppath) - } else { - continue - } - if verr != nil { - return nil, verr - } - - if i == lastkey && !keys[i].isArray { - break - } - - // Now we're looking at an array - supposedly. - // Is index in range of vals? - if len(vals) <= keys[i].position { - vals = nil - break - } - - // Return the array member of interest, if at end of path. - if i == lastkey { - vals = vals[keys[i].position:(keys[i].position + 1)] - break - } - - // Extract the array member of interest. - am := vals[keys[i].position:(keys[i].position + 1)] - - // must be a map[string]interface{} value so we can keep walking the path - amm, ok := am[0].(map[string]interface{}) - if !ok { - vals = nil - break - } - - m = Map(amm) - haveFirst = false - } - - return vals, nil -} - -type key struct { - name string - isArray bool - position int -} - -func parsePath(s string) ([]*key, error) { - keys := strings.Split(s, ".") - - ret := make([]*key, 0) - - for i := 0; i < len(keys); i++ { - if keys[i] == "" { - continue - } - - newkey := new(key) - if strings.Index(keys[i], "[") < 0 { - newkey.name = keys[i] - ret = append(ret, newkey) - continue - } - - p := strings.Split(keys[i], "[") - newkey.name = p[0] - p = strings.Split(p[1], "]") - if p[0] == "" { // no right bracket - return nil, fmt.Errorf("no right bracket on key index: %s", keys[i]) - } - // convert p[0] to a int value - pos, nerr := strconv.ParseInt(p[0], 10, 32) - if nerr != nil { - return nil, fmt.Errorf("cannot convert index to int value: %s", p[0]) - } - newkey.position = int(pos) - newkey.isArray = true - ret = append(ret, newkey) - } - - return ret, nil -} - -// legacy ValuesForPath() - now wrapped to handle special case of indexed arrays in 'path'. -func (mv Map) oldValuesForPath(path string, subkeys ...string) ([]interface{}, error) { - m := map[string]interface{}(mv) - var subKeyMap map[string]interface{} - if len(subkeys) > 0 { - var err error - subKeyMap, err = getSubKeyMap(subkeys...) - if err != nil { - return nil, err - } - } - - keys := strings.Split(path, ".") - if keys[len(keys)-1] == "" { - keys = keys[:len(keys)-1] - } - // ivals := make([]interface{}, 0) - // valuesForKeyPath(&ivals, m, keys, subKeyMap) - // return ivals, nil - ivals := make([]interface{}, 0, defaultArraySize) - var cnt int - valuesForKeyPath(&ivals, &cnt, m, keys, subKeyMap) - return ivals[:cnt], nil -} - -func valuesForKeyPath(ret *[]interface{}, cnt *int, m interface{}, keys []string, subkeys map[string]interface{}) { - lenKeys := len(keys) - - // load 'm' values into 'ret' - // expand any lists - if lenKeys == 0 { - switch m.(type) { - case map[string]interface{}: - if subkeys != nil { - if ok := hasSubKeys(m, subkeys); !ok { - return - } - } - *ret = append(*ret, m) - *cnt++ - case []interface{}: - for i, v := range m.([]interface{}) { - if subkeys != nil { - if ok := hasSubKeys(v, subkeys); !ok { - continue // only load list members with subkeys - } - } - *ret = append(*ret, (m.([]interface{}))[i]) - *cnt++ - } - default: - if subkeys != nil { - return // must be map[string]interface{} if there are subkeys - } - *ret = append(*ret, m) - *cnt++ - } - return - } - - // key of interest - key := keys[0] - switch key { - case "*": // wildcard - scan all values - switch m.(type) { - case map[string]interface{}: - for _, v := range m.(map[string]interface{}) { - // valuesForKeyPath(ret, v, keys[1:], subkeys) - valuesForKeyPath(ret, cnt, v, keys[1:], subkeys) - } - case []interface{}: - for _, v := range m.([]interface{}) { - switch v.(type) { - // flatten out a list of maps - keys are processed - case map[string]interface{}: - for _, vv := range v.(map[string]interface{}) { - // valuesForKeyPath(ret, vv, keys[1:], subkeys) - valuesForKeyPath(ret, cnt, vv, keys[1:], subkeys) - } - default: - // valuesForKeyPath(ret, v, keys[1:], subkeys) - valuesForKeyPath(ret, cnt, v, keys[1:], subkeys) - } - } - } - default: // key - must be map[string]interface{} - switch m.(type) { - case map[string]interface{}: - if v, ok := m.(map[string]interface{})[key]; ok { - // valuesForKeyPath(ret, v, keys[1:], subkeys) - valuesForKeyPath(ret, cnt, v, keys[1:], subkeys) - } - case []interface{}: // may be buried in list - for _, v := range m.([]interface{}) { - switch v.(type) { - case map[string]interface{}: - if vv, ok := v.(map[string]interface{})[key]; ok { - // valuesForKeyPath(ret, vv, keys[1:], subkeys) - valuesForKeyPath(ret, cnt, vv, keys[1:], subkeys) - } - } - } - } - } -} - -// hasSubKeys() - interface{} equality works for string, float64, bool -// 'v' must be a map[string]interface{} value to have subkeys -// 'a' can have k:v pairs with v.(string) == "*", which is treated like a wildcard. -func hasSubKeys(v interface{}, subkeys map[string]interface{}) bool { - if len(subkeys) == 0 { - return true - } - - switch v.(type) { - case map[string]interface{}: - // do all subKey name:value pairs match? - mv := v.(map[string]interface{}) - for skey, sval := range subkeys { - isNotKey := false - if skey[:1] == "!" { // a NOT-key - skey = skey[1:] - isNotKey = true - } - vv, ok := mv[skey] - if !ok { // key doesn't exist - if isNotKey { // key not there, but that's what we want - if kv, ok := sval.(string); ok && kv == "*" { - continue - } - } - return false - } - // wildcard check - if kv, ok := sval.(string); ok && kv == "*" { - if isNotKey { // key is there, and we don't want it - return false - } - continue - } - switch sval.(type) { - case string: - if s, ok := vv.(string); ok && s == sval.(string) { - if isNotKey { - return false - } - continue - } - case bool: - if b, ok := vv.(bool); ok && b == sval.(bool) { - if isNotKey { - return false - } - continue - } - case float64: - if f, ok := vv.(float64); ok && f == sval.(float64) { - if isNotKey { - return false - } - continue - } - } - // key there but didn't match subkey value - if isNotKey { // that's what we want - continue - } - return false - } - // all subkeys matched - return true - } - - // not a map[string]interface{} value, can't have subkeys - return false -} - -// Generate map of key:value entries as map[string]string. -// 'kv' arguments are "name:value" pairs: attribute keys are designated with prepended hyphen, '-'. -// If len(kv) == 0, the return is (nil, nil). -func getSubKeyMap(kv ...string) (map[string]interface{}, error) { - if len(kv) == 0 { - return nil, nil - } - m := make(map[string]interface{}, 0) - for _, v := range kv { - vv := strings.Split(v, ":") - switch len(vv) { - case 2: - m[vv[0]] = interface{}(vv[1]) - case 3: - switch vv[3] { - case "string", "char", "text": - m[vv[0]] = interface{}(vv[1]) - case "bool", "boolean": - // ParseBool treats "1"==true & "0"==false - b, err := strconv.ParseBool(vv[1]) - if err != nil { - return nil, fmt.Errorf("can't convert subkey value to bool: %s", vv[1]) - } - m[vv[0]] = interface{}(b) - case "float", "float64", "num", "number", "numeric": - f, err := strconv.ParseFloat(vv[1], 64) - if err != nil { - return nil, fmt.Errorf("can't convert subkey value to float: %s", vv[1]) - } - m[vv[0]] = interface{}(f) - default: - return nil, fmt.Errorf("unknown subkey conversion spec: %s", v) - } - default: - return nil, fmt.Errorf("unknown subkey spec: %s", v) - } - } - return m, nil -} - -// ------------------------------- END of valuesFor ... ---------------------------- - -// ----------------------- locate where a key value is in the tree ------------------- - -//----------------------------- find all paths to a key -------------------------------- - -// Get all paths through Map, 'mv', (in dot-notation) that terminate with the specified key. -// Results can be used with ValuesForPath. -func (mv Map) PathsForKey(key string) []string { - m := map[string]interface{}(mv) - breadbasket := make(map[string]bool, 0) - breadcrumbs := "" - - hasKeyPath(breadcrumbs, m, key, breadbasket) - if len(breadbasket) == 0 { - return nil - } - - // unpack map keys to return - res := make([]string, len(breadbasket)) - var i int - for k, _ := range breadbasket { - res[i] = k - i++ - } - - return res -} - -// Extract the shortest path from all possible paths - from PathsForKey() - in Map, 'mv'.. -// Paths are strings using dot-notation. -func (mv Map) PathForKeyShortest(key string) string { - paths := mv.PathsForKey(key) - - lp := len(paths) - if lp == 0 { - return "" - } - if lp == 1 { - return paths[0] - } - - shortest := paths[0] - shortestLen := len(strings.Split(shortest, ".")) - - for i := 1; i < len(paths); i++ { - vlen := len(strings.Split(paths[i], ".")) - if vlen < shortestLen { - shortest = paths[i] - shortestLen = vlen - } - } - - return shortest -} - -// hasKeyPath - if the map 'key' exists append it to KeyPath.path and increment KeyPath.depth -// This is really just a breadcrumber that saves all trails that hit the prescribed 'key'. -func hasKeyPath(crumbs string, iv interface{}, key string, basket map[string]bool) { - switch iv.(type) { - case map[string]interface{}: - vv := iv.(map[string]interface{}) - if _, ok := vv[key]; ok { - if crumbs == "" { - crumbs = key - } else { - crumbs += "." + key - } - // *basket = append(*basket, crumb) - basket[crumbs] = true - } - // walk on down the path, key could occur again at deeper node - for k, v := range vv { - // create a new breadcrumb, intialized with the one we have - var nbc string - if crumbs == "" { - nbc = k - } else { - nbc = crumbs + "." + k - } - hasKeyPath(nbc, v, key, basket) - } - case []interface{}: - // crumb-trail doesn't change, pass it on - for _, v := range iv.([]interface{}) { - hasKeyPath(crumbs, v, key, basket) - } - } -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/keyvalues_test.go b/Godeps/_workspace/src/github.com/clbanning/mxj/keyvalues_test.go deleted file mode 100644 index ad42a77c9..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/keyvalues_test.go +++ /dev/null @@ -1,412 +0,0 @@ -// keyvalues_test.go - test keyvalues.go methods - -package mxj - -import ( - // "bytes" - "fmt" - // "io" - "testing" -) - -func TestKVHeader(t *testing.T) { - fmt.Println("\n---------------- keyvalues_test.go ...\n") -} - -var doc1 = []byte(` - - - - William T. Gaddis - The Recognitions - One of the great seminal American novels of the 20th century. - - - Austin Tappan Wright - Islandia - An example of earlier 20th century American utopian fiction. - - - John Hawkes - The Beetle Leg - A lyrical novel about the construction of Ft. Peck Dam in Montana. - - - - T.E. - Porter - - King's Day - A magical novella. - - - -`) - -var doc2 = []byte(` - - - - William T. Gaddis - The Recognitions - One of the great seminal American novels of the 20th century. - - - Something else. - -`) - -// the basic demo/test case - a small bibliography with mixed element types -func TestPathsForKey(t *testing.T) { - fmt.Println("PathsForKey, doc1 ...") - m, merr := NewMapXml(doc1) - if merr != nil { - t.Fatal("merr:", merr.Error()) - } - fmt.Println("PathsForKey, doc1#author") - ss := m.PathsForKey("author") - fmt.Println("... ss:", ss) - - fmt.Println("PathsForKey, doc1#books") - ss = m.PathsForKey("books") - fmt.Println("... ss:", ss) - - fmt.Println("PathsForKey, doc2 ...") - m, merr = NewMapXml(doc2) - if merr != nil { - t.Fatal("merr:", merr.Error()) - } - fmt.Println("PathForKey, doc2#book") - ss = m.PathsForKey("book") - fmt.Println("... ss:", ss) - - fmt.Println("PathForKeyShortest, doc2#book") - s := m.PathForKeyShortest("book") - fmt.Println("... s :", s) -} - -func TestValuesForKey(t *testing.T) { - fmt.Println("ValuesForKey ...") - m, merr := NewMapXml(doc1) - if merr != nil { - t.Fatal("merr:", merr.Error()) - } - fmt.Println("ValuesForKey, doc1#author") - ss, sserr := m.ValuesForKey("author") - if sserr != nil { - t.Fatal("sserr:", sserr.Error()) - } - for _, v := range ss { - fmt.Println("... ss.v:", v) - } - - fmt.Println("ValuesForKey, doc1#book") - ss, sserr = m.ValuesForKey("book") - if sserr != nil { - t.Fatal("sserr:", sserr.Error()) - } - for _, v := range ss { - fmt.Println("... ss.v:", v) - } - - fmt.Println("ValuesForKey, doc1#book,-seq:3") - ss, sserr = m.ValuesForKey("book", "-seq:3") - if sserr != nil { - t.Fatal("sserr:", sserr.Error()) - } - for _, v := range ss { - fmt.Println("... ss.v:", v) - } - - fmt.Println("ValuesForKey, doc1#book, author:William T. Gaddis") - ss, sserr = m.ValuesForKey("book", "author:William T. Gaddis") - if sserr != nil { - t.Fatal("sserr:", sserr.Error()) - } - for _, v := range ss { - fmt.Println("... ss.v:", v) - } - - fmt.Println("ValuesForKey, doc1#author, -seq:1") - ss, sserr = m.ValuesForKey("author", "-seq:1") - if sserr != nil { - t.Fatal("sserr:", sserr.Error()) - } - for _, v := range ss { // should be len(ss) == 0 - fmt.Println("... ss.v:", v) - } -} - -func TestValuesForPath(t *testing.T) { - fmt.Println("ValuesForPath ...") - m, merr := NewMapXml(doc1) - if merr != nil { - t.Fatal("merr:", merr.Error()) - } - fmt.Println("ValuesForPath, doc.books.book.author") - ss, sserr := m.ValuesForPath("doc.books.book.author") - if sserr != nil { - t.Fatal("sserr:", sserr.Error()) - } - for _, v := range ss { - fmt.Println("... ss.v:", v) - } - - fmt.Println("ValuesForPath, doc.books.book") - ss, sserr = m.ValuesForPath("doc.books.book") - if sserr != nil { - t.Fatal("sserr:", sserr.Error()) - } - for _, v := range ss { - fmt.Println("... ss.v:", v) - } - - fmt.Println("ValuesForPath, doc.books.book -seq=3") - ss, sserr = m.ValuesForPath("doc.books.book", "-seq:3") - if sserr != nil { - t.Fatal("sserr:", sserr.Error()) - } - for _, v := range ss { - fmt.Println("... ss.v:", v) - } - - fmt.Println("ValuesForPath, doc.books.* -seq=3") - ss, sserr = m.ValuesForPath("doc.books.*", "-seq:3") - if sserr != nil { - t.Fatal("sserr:", sserr.Error()) - } - for _, v := range ss { - fmt.Println("... ss.v:", v) - } - - fmt.Println("ValuesForPath, doc.*.* -seq=3") - ss, sserr = m.ValuesForPath("doc.*.*", "-seq:3") - if sserr != nil { - t.Fatal("sserr:", sserr.Error()) - } - for _, v := range ss { - fmt.Println("... ss.v:", v) - } -} - -func TestValuesForNotKey(t *testing.T) { - fmt.Println("ValuesForNotKey ...") - m, merr := NewMapXml(doc1) - if merr != nil { - t.Fatal("merr:", merr.Error()) - } - fmt.Println("ValuesForPath, doc.books.book !author:William T. Gaddis") - ss, sserr := m.ValuesForPath("doc.books.book", "!author:William T. Gaddis") - if sserr != nil { - t.Fatal("sserr:", sserr.Error()) - } - for _, v := range ss { - fmt.Println("... ss.v:", v) - } - - fmt.Println("ValuesForPath, doc.books.book !author:*") - ss, sserr = m.ValuesForPath("doc.books.book", "!author:*") - if sserr != nil { - t.Fatal("sserr:", sserr.Error()) - } - for _, v := range ss { // expect len(ss) == 0 - fmt.Println("... ss.v:", v) - } - - fmt.Println("ValuesForPath, doc.books.book !unknown:*") - ss, sserr = m.ValuesForPath("doc.books.book", "!unknown:*") - if sserr != nil { - t.Fatal("sserr:", sserr.Error()) - } - for _, v := range ss { - fmt.Println("... ss.v:", v) - } -} - -func TestIAHeader(t *testing.T) { - fmt.Println("\n---------------- indexedarray_test.go ...\n") -} - -var ak_data = []byte(`{ "section1":{"data" : [{"F1" : "F1 data","F2" : "F2 data"},{"F1" : "demo 123","F2" : "abc xyz"}]}}`) -var j_data = []byte(`{ "stuff":[ { "data":[ { "F":1 }, { "F":2 }, { "F":3 } ] }, { "data":[ 4, 5, 6 ] } ] }`) -var x_data = []byte(` - - - - 1 - - - 2 - - - 3 - - - - - 4 - - - 5 - - - 6 - - -`) - -func TestValuesForIndexedArray(t *testing.T) { - j_main(t) - x_main(t) - ak_main(t) -} - -func ak_main(t *testing.T) { - fmt.Println("\nak_data:", string(ak_data)) - m, merr := NewMapJson(ak_data) - if merr != nil { - t.Fatal("merr:", merr.Error()) - return - } - fmt.Println("m:", m) - - v, verr := m.ValuesForPath("section1.data[0].F1") - if verr != nil { - t.Fatal("verr:", verr.Error()) - } - fmt.Println("section1.data[0].F1:", v) -} - -func j_main(t *testing.T) { - fmt.Println("j_data:", string(j_data)) - m, merr := NewMapJson(j_data) - if merr != nil { - t.Fatal("merr:", merr.Error()) - return - } - fmt.Println("m:", m) - - v, verr := m.ValuesForPath("stuff[0]") - if verr != nil { - t.Fatal("verr:", verr.Error()) - } - fmt.Println("stuff[0]:", v) - - v, verr = m.ValuesForPath("stuff.data") - if verr != nil { - t.Fatal("verr:", verr.Error()) - } - fmt.Println("stuff.data:", v) - - v, verr = m.ValuesForPath("stuff[0].data") - if verr != nil { - t.Fatal("verr:", verr.Error()) - } - fmt.Println("stuff[0].data:", v) - - v, verr = m.ValuesForPath("stuff.data[0]") - if verr != nil { - t.Fatal("verr:", verr.Error()) - } - fmt.Println("stuff.data[0]:", v) - - v, verr = m.ValuesForPath("stuff.*[2]") - if verr != nil { - t.Fatal("verr:", verr.Error()) - } - fmt.Println("stuff.*[2]:", v) - - v, verr = m.ValuesForPath("stuff.data.F") - if verr != nil { - t.Fatal("verr:", verr.Error()) - } - fmt.Println("stuff.data.F:", v) - - v, verr = m.ValuesForPath("*.*.F") - if verr != nil { - t.Fatal("verr:", verr.Error()) - } - fmt.Println("*.*.F:", v) - - v, verr = m.ValuesForPath("stuff.data[0].F") - if verr != nil { - t.Fatal("verr:", verr.Error()) - } - fmt.Println("stuff.data[0].F:", v) - - v, verr = m.ValuesForPath("stuff.data[1].F") - if verr != nil { - t.Fatal("verr:", verr.Error()) - } - fmt.Println("stuff.data[1].F:", v) - - v, verr = m.ValuesForPath("stuff[0].data[2]") - if verr != nil { - t.Fatal("verr:", verr.Error()) - } - fmt.Println("stuff[0].data[2]:", v) - - v, verr = m.ValuesForPath("stuff[1].data[1]") - if verr != nil { - t.Fatal("verr:", verr.Error()) - } - fmt.Println("stuff[1].data[1]:", v) - - v, verr = m.ValuesForPath("stuff[1].data[1].F") - if verr != nil { - t.Fatal("verr:", verr.Error()) - } - fmt.Println("stuff[1].data[1].F", v) - - v, verr = m.ValuesForPath("stuff[1].data.F") - if verr != nil { - t.Fatal("verr:", verr.Error()) - } - fmt.Println("stuff[1].data.F:", v) -} - -func x_main(t *testing.T) { - fmt.Println("\nx_data:", string(x_data)) - m, merr := NewMapXml(x_data) - if merr != nil { - t.Fatal("merr:", merr.Error()) - return - } - fmt.Println("m:", m) - - v, verr := m.ValuesForPath("doc.stuff[0]") - if verr != nil { - t.Fatal("verr:", verr.Error()) - } - fmt.Println("doc.stuff[0]:", v) - - v, verr = m.ValuesForPath("doc.stuff.data[0]") - if verr != nil { - t.Fatal("verr:", verr.Error()) - } - fmt.Println("doc.stuff.data[0]:", v) - - v, verr = m.ValuesForPath("doc.stuff.data[0]", "-seq:2.1") - if verr != nil { - t.Fatal("verr:", verr.Error()) - } - fmt.Println("doc.stuff.data[0] -seq:2.1:", v) - - v, verr = m.ValuesForPath("doc.stuff.data[0].F") - if verr != nil { - t.Fatal("verr:", verr.Error()) - } - fmt.Println("doc.stuff.data[0].F:", v) - - v, verr = m.ValuesForPath("doc.stuff[0].data[2]") - if verr != nil { - t.Fatal("verr:", verr.Error()) - } - fmt.Println("doc.stuff[0].data[2]:", v) - - v, verr = m.ValuesForPath("doc.stuff[1].data[1].F") - if verr != nil { - t.Fatal("verr:", verr.Error()) - } - fmt.Println("doc.stuff[1].data[1].F:", v) -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/leafnode.go b/Godeps/_workspace/src/github.com/clbanning/mxj/leafnode.go deleted file mode 100644 index 99f271656..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/leafnode.go +++ /dev/null @@ -1,82 +0,0 @@ -package mxj - -// leafnode.go - return leaf nodes with paths and values for the Map -// inspired by: https://groups.google.com/forum/#!topic/golang-nuts/3JhuVKRuBbw - -import ( - "strconv" -) - -const ( - NoAttributes = true // suppress LeafNode values that are attributes -) - -// LeafNode - a terminal path value in a Map. -// For XML Map values it represents an attribute or simple element value - of type -// string unless Map was created using Cast flag. For JSON Map values it represents -// a string, numeric, boolean, or null value. -type LeafNode struct { - Path string // a dot-notation representation of the path with array subscripting - Value interface{} // the value at the path termination -} - -// LeafNodes - returns an array of all LeafNode values for the Map. -// The option no_attr argument suppresses attribute values (keys with prepended hyphen, '-') -// as well as the "#text" key for the associated simple element value. -func (mv Map) LeafNodes(no_attr ...bool) []LeafNode { - var a bool - if len(no_attr) == 1 { - a = no_attr[0] - } - - l := make([]LeafNode, 0) - getLeafNodes("", "", map[string]interface{}(mv), &l, a) - return l -} - -func getLeafNodes(path, node string, mv interface{}, l *[]LeafNode, noattr bool) { - // if stripping attributes, then also strip "#text" key - if !noattr || node != "#text" { - if path != "" && node[:1] != "[" { - path += "." - } - path += node - } - switch mv.(type) { - case map[string]interface{}: - for k, v := range mv.(map[string]interface{}) { - if noattr && k[:1] == "-" { - continue - } - getLeafNodes(path, k, v, l, noattr) - } - case []interface{}: - for i, v := range mv.([]interface{}) { - getLeafNodes(path, "["+strconv.Itoa(i)+"]", v, l, noattr) - } - default: - // can't walk any further, so create leaf - n := LeafNode{path, mv} - *l = append(*l, n) - } -} - -// LeafPaths - all paths that terminate in LeafNode values. -func (mv Map) LeafPaths(no_attr ...bool) []string { - ln := mv.LeafNodes() - ss := make([]string, len(ln)) - for i := 0; i < len(ln); i++ { - ss[i] = ln[i].Path - } - return ss -} - -// LeafValues - all terminal values in the Map. -func (mv Map) LeafValues(no_attr ...bool) []interface{} { - ln := mv.LeafNodes() - vv := make([]interface{}, len(ln)) - for i := 0; i < len(ln); i++ { - vv[i] = ln[i].Value - } - return vv -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/leafnode_test.go b/Godeps/_workspace/src/github.com/clbanning/mxj/leafnode_test.go deleted file mode 100644 index 9cb9dd716..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/leafnode_test.go +++ /dev/null @@ -1,97 +0,0 @@ -package mxj - -import ( - "fmt" - "testing" -) - -func TestLNHeader(t *testing.T) { - fmt.Println("\n---------------- leafnode_test.go ...") -} - -func TestLeafNodes(t *testing.T) { - json1 := []byte(`{ - "friends": [ - { - "skills": [ - 44, 12 - ] - } - ] - }`) - - json2 := []byte(`{ - "friends": - { - "skills": [ - 44, 12 - ] - } - - }`) - - m, _ := NewMapJson(json1) - ln := m.LeafNodes() - fmt.Println("\njson1-LeafNodes:") - for _, v := range ln { - fmt.Printf("%#v\n", v) - } - p := m.LeafPaths() - fmt.Println("\njson1-LeafPaths:") - for _, v := range p { - fmt.Printf("%#v\n", v) - } - - m, _ = NewMapJson(json2) - ln = m.LeafNodes() - fmt.Println("\njson2-LeafNodes:") - for _, v := range ln { - fmt.Printf("%#v\n", v) - } - v := m.LeafValues() - fmt.Println("\njson1-LeafValues:") - for _, v := range v { - fmt.Printf("%#v\n", v) - } - - json3 := []byte(`{ "a":"list", "of":["data", "of", 3, "types", true]}`) - m, _ = NewMapJson(json3) - ln = m.LeafNodes() - fmt.Println("\njson3-LeafNodes:") - for _, v := range ln { - fmt.Printf("%#v\n", v) - } - v = m.LeafValues() - fmt.Println("\njson3-LeafValues:") - for _, v := range v { - fmt.Printf("%#v\n", v) - } - p = m.LeafPaths() - fmt.Println("\njson3-LeafPaths:") - for _, v := range p { - fmt.Printf("%#v\n", v) - } - - xmldata2 := []byte(` - - Item 2 is blue - - - - - `) - m, err := NewMapXml(xmldata2) - if err != nil { - t.Fatal(err.Error()) - } - fmt.Println("\nxml2data2-LeafValues:") - ln = m.LeafNodes() - for _, v := range ln { - fmt.Printf("%#v\n", v) - } - fmt.Println("\nxml2data2-LeafValues(NoAttributes):") - ln = m.LeafNodes(NoAttributes) - for _, v := range ln { - fmt.Printf("%#v\n", v) - } -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/mxj.go b/Godeps/_workspace/src/github.com/clbanning/mxj/mxj.go deleted file mode 100644 index 8e90c32b3..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/mxj.go +++ /dev/null @@ -1,107 +0,0 @@ -// mxj - A collection of map[string]interface{} and associated XML and JSON utilities. -// Copyright 2012-2014 Charles Banning. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file - -package mxj - -import ( - "fmt" - "strconv" -) - -const ( - Cast = true // for clarity - e.g., mxj.NewMapXml(doc, mxj.Cast) - SafeEncoding = true // ditto - e.g., mv.Json(mxj.SafeEncoding) -) - -type Map map[string]interface{} - -// Allocate a Map. -func New() Map { - m := make(map[string]interface{}, 0) - return m -} - -// Cast a Map to map[string]interface{} -func (mv Map) Old() map[string]interface{} { - return mv -} - -// Return a copy of mv as a newly allocated Map. If the Map only contains string, -// numeric, map[string]interface{}, and []interface{} values, then it can be thought -// of as a "deep copy." Copying a structure (or structure reference) value is subject -// to the noted restrictions. -// NOTE: If 'mv' includes structure values with, possibly, JSON encoding tags -// then only public fields of the structure are in the new Map - and with -// keys that conform to any encoding tag instructions. The structure itself will -// be represented as a map[string]interface{} value. -func (mv Map) Copy() (Map, error) { - // this is the poor-man's deep copy - // not efficient, but it works - j, jerr := mv.Json() - // must handle, we don't know how mv got built - if jerr != nil { - return nil, jerr - } - return NewMapJson(j) -} - -// --------------- StringIndent ... from x2j.WriteMap ------------- - -// Pretty print a Map. -func (mv Map) StringIndent(offset ...int) string { - return writeMap(map[string]interface{}(mv), offset...) -} - -// writeMap - dumps the map[string]interface{} for examination. -// 'offset' is initial indentation count; typically: Write(m). -func writeMap(m interface{}, offset ...int) string { - var indent int - if len(offset) == 1 { - indent = offset[0] - } - - var s string - switch m.(type) { - case nil: - return "[nil] nil" - case string: - return "[string] " + m.(string) - case float64: - return "[float64] " + strconv.FormatFloat(m.(float64), 'e', 2, 64) - case bool: - return "[bool] " + strconv.FormatBool(m.(bool)) - case []interface{}: - s += "[[]interface{}]" - for i, v := range m.([]interface{}) { - s += "\n" - for i := 0; i < indent; i++ { - s += " " - } - s += "[item: " + strconv.FormatInt(int64(i), 10) + "]" - switch v.(type) { - case string, float64, bool: - s += "\n" - default: - // noop - } - for i := 0; i < indent; i++ { - s += " " - } - s += writeMap(v, indent+1) - } - case map[string]interface{}: - for k, v := range m.(map[string]interface{}) { - s += "\n" - for i := 0; i < indent; i++ { - s += " " - } - s += k + " :" + writeMap(v, indent+1) - } - default: - // shouldn't ever be here ... - s += fmt.Sprintf("[unknown] %#v", m) - } - return s -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/mxj_test.go b/Godeps/_workspace/src/github.com/clbanning/mxj/mxj_test.go deleted file mode 100644 index 319e09e54..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/mxj_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package mxj - -import ( - "fmt" - "testing" -) - -func TestMxjHeader(t *testing.T) { - fmt.Println("\n---------------- mxj_test.go ...\n") -} - -func TestMap(t *testing.T) { - m := New() - - m["key"] = interface{}("value") - v := map[string]interface{}{"bool": true, "float": 3.14159, "string": "Now is the time"} - vv := []interface{}{3.1415962535, false, "for all good men"} - v["listkey"] = interface{}(vv) - m["newkey"] = interface{}(v) - - fmt.Println("TestMap, m:", m) - fmt.Println("TestMap, StringIndent:", m.StringIndent()) - - o := interface{}(m.Old()) - switch o.(type) { - case map[string]interface{}: - // do nothing - default: - t.Fatal("invalid type for m.Old()") - } - - m, _ = NewMapXml([]byte(`HelloWorld`)) - fmt.Println("TestMap, m_fromXML:", m) - fmt.Println("TestMap, StringIndent:", m.StringIndent()) - - mm, _ := m.Copy() - fmt.Println("TestMap, m.Copy():", mm) -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/newmap.go b/Godeps/_workspace/src/github.com/clbanning/mxj/newmap.go deleted file mode 100644 index fc1320c00..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/newmap.go +++ /dev/null @@ -1,183 +0,0 @@ -// mxj - A collection of map[string]interface{} and associated XML and JSON utilities. -// Copyright 2012-2014 Charles Banning. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file - -// remap.go - build a new Map from the current Map based on keyOld:keyNew mapppings -// keys can use dot-notation, keyOld can use wildcard, '*' -// -// Computational strategy - -// Using the key path - []string - traverse a new map[string]interface{} and -// insert the oldVal as the newVal when we arrive at the end of the path. -// If the type at the end is nil, then that is newVal -// If the type at the end is a singleton (string, float64, bool) an array is created. -// If the type at the end is an array, newVal is just appended. -// If the type at the end is a map, it is inserted if possible or the map value -// is converted into an array if necessary. - -package mxj - -import ( - "errors" - "strings" -) - -// (Map)NewMap - create a new Map from data in the current Map. -// 'keypairs' are key mappings "oldKey:newKey" and specify that the current value of 'oldKey' -// should be the value for 'newKey' in the returned Map. -// - 'oldKey' supports dot-notation as described for (Map)ValuesForPath() -// - 'newKey' supports dot-notation but with no wildcards, '*', or indexed arrays -// - "oldKey" is shorthand for for the keypair value "oldKey:oldKey" -// - "oldKey:" and ":newKey" are invalid keypair values -// - if 'oldKey' does not exist in the current Map, it is not written to the new Map. -// "null" is not supported unless it is the current Map. -// - see newmap_test.go for several syntax examples -// -// NOTE: mv.NewMap() == mxj.New(). -func (mv Map) NewMap(keypairs ...string) (Map, error) { - n := make(map[string]interface{}, 0) - if len(keypairs) == 0 { - return n, nil - } - - // loop through the pairs - var oldKey, newKey string - var path []string - for _, v := range keypairs { - if len(v) == 0 { - continue // just skip over empty keypair arguments - } - - // initialize oldKey, newKey and check - vv := strings.Split(v, ":") - if len(vv) > 2 { - return n, errors.New("oldKey:newKey keypair value not valid - " + v) - } - if len(vv) == 1 { - oldKey, newKey = vv[0], vv[0] - } else { - oldKey, newKey = vv[0], vv[1] - } - strings.TrimSpace(oldKey) - strings.TrimSpace(newKey) - if i := strings.Index(newKey, "*"); i > -1 { - return n, errors.New("newKey value cannot contain wildcard character - " + v) - } - if i := strings.Index(newKey, "["); i > -1 { - return n, errors.New("newKey value cannot contain indexed arrays - " + v) - } - if oldKey == "" || newKey == "" { - return n, errors.New("oldKey or newKey is not specified - " + v) - } - - // get oldKey value - oldVal, err := mv.ValuesForPath(oldKey) - if err != nil { - return n, err - } - if len(oldVal) == 0 { - continue // oldKey has no value, may not exist in mv - } - - // break down path - path = strings.Split(newKey, ".") - if path[len(path)-1] == "" { // ignore a trailing dot in newKey spec - path = path[:len(path)-1] - } - - addNewVal(&n, path, oldVal) - } - - return n, nil -} - -// navigate 'n' to end of path and add val -func addNewVal(n *map[string]interface{}, path []string, val []interface{}) { - // newVal - either singleton or array - var newVal interface{} - if len(val) == 1 { - newVal = val[0] // is type interface{} - } else { - newVal = interface{}(val) - } - - // walk to the position of interest, create it if necessary - m := (*n) // initialize map walker - var k string // key for m - lp := len(path) - 1 // when to stop looking - for i := 0; i < len(path); i++ { - k = path[i] - if i == lp { - break - } - var nm map[string]interface{} // holds position of next-map - switch m[k].(type) { - case nil: // need a map for next node in path, so go there - nm = make(map[string]interface{}, 0) - m[k] = interface{}(nm) - m = m[k].(map[string]interface{}) - case map[string]interface{}: - // OK - got somewhere to walk to, go there - m = m[k].(map[string]interface{}) - case []interface{}: - // add a map and nm points to new map unless there's already - // a map in the array, then nm points there - // The placement of the next value in the array is dependent - // on the sequence of members - could land on a map or a nil - // value first. TODO: how to test this. - a := make([]interface{}, 0) - var foundmap bool - for _, vv := range m[k].([]interface{}) { - switch vv.(type) { - case nil: // doesn't appear that this occurs, need a test case - if foundmap { // use the first one in array - a = append(a, vv) - continue - } - nm = make(map[string]interface{}, 0) - a = append(a, interface{}(nm)) - foundmap = true - case map[string]interface{}: - if foundmap { // use the first one in array - a = append(a, vv) - continue - } - nm = vv.(map[string]interface{}) - a = append(a, vv) - foundmap = true - default: - a = append(a, vv) - } - } - // no map found in array - if !foundmap { - nm = make(map[string]interface{}, 0) - a = append(a, interface{}(nm)) - } - m[k] = interface{}(a) // must insert in map - m = nm - default: // it's a string, float, bool, etc. - aa := make([]interface{}, 0) - nm = make(map[string]interface{}, 0) - aa = append(aa, m[k], nm) - m[k] = interface{}(aa) - m = nm - } - } - - // value is nil, array or a singleton of some kind - // initially m.(type) == map[string]interface{} - v := m[k] - switch v.(type) { - case nil: // initialized - m[k] = newVal - case []interface{}: - a := m[k].([]interface{}) - a = append(a, newVal) - m[k] = interface{}(a) - default: // v exists:string, float64, bool, map[string]interface, etc. - a := make([]interface{}, 0) - a = append(a, v, newVal) - m[k] = interface{}(a) - } -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/newmap_test.go b/Godeps/_workspace/src/github.com/clbanning/mxj/newmap_test.go deleted file mode 100644 index 7e3fdfea0..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/newmap_test.go +++ /dev/null @@ -1,114 +0,0 @@ -package mxj - -import ( - "bytes" - "fmt" - "io" - "testing" -) - -func TestNewMapHeader(t *testing.T) { - fmt.Println("\n---------------- newmap_test.go ...\n") -} - -func TestNewMap(t *testing.T) { - j := []byte(`{ "A":"this", "B":"is", "C":"a", "D":"test" }`) - fmt.Println("j:", string(j)) - - m, _ := NewMapJson(j) - fmt.Printf("m: %#v\n", m) - - fmt.Println("\n", `eval - m.NewMap("A:AA", "B:BB", "C:cc", "D:help")`) - n, err := m.NewMap("A:AA", "B:BB", "C:cc", "D:help") - if err != nil { - fmt.Println("err:", err.Error()) - } - j, _ = n.Json() - fmt.Println("n.Json():", string(j)) - x, _ := n.Xml() - fmt.Println("n.Xml():\n", string(x)) - x, _ = n.XmlIndent("", " ") - fmt.Println("n.XmlIndent():\n", string(x)) - - fmt.Println("\n", `eval - m.NewMap("A:AA.A", "B:AA.B", "C:AA.B.cc", "D:hello.help")`) - n, err = m.NewMap("A:AA.A", "B:AA.B", "C:AA.B.cc", "D:hello.help") - if err != nil { - fmt.Println("err:", err.Error()) - } - j, _ = n.Json() - fmt.Println("n.Json():", string(j)) - x, _ = n.Xml() - fmt.Println("n.Xml():\n", string(x)) - x, _ = n.XmlIndent("", " ") - fmt.Println("n.XmlIndent():\n", string(x)) - - var keypairs = []string{"A:xml.AA", "B:xml.AA.hello.again", "C:xml.AA", "D:xml.AA.hello.help"} - fmt.Println("\n", `eval - m.NewMap keypairs:`, keypairs) - n, err = m.NewMap(keypairs...) - if err != nil { - fmt.Println("err:", err.Error()) - } - j, _ = n.Json() - fmt.Println("n.Json():", string(j)) - x, _ = n.Xml() - fmt.Println("n.Xml():\n", string(x)) - x, _ = n.XmlIndent("", " ") - fmt.Println("n.XmlIndent():\n", string(x)) -} - -// Need to normalize from an XML stream the values for "netid" and "idnet". -// Solution: make everything "netid" -// Demo how to re-label a key using mv.NewMap() - -var msg1 = []byte(` - - - - no - default:text - default:word - - -`) - -var msg2 = []byte(` - - - - yes - default:text - default:word - - -`) - -func TestNetId(t *testing.T) { - // let's create a message stream - buf := new(bytes.Buffer) - // load a couple of messages into it - _, _ = buf.Write(msg1) - _, _ = buf.Write(msg2) - - n := 0 - for { - n++ - // read the stream as Map values - quit on io.EOF - m, raw, merr := NewMapXmlReaderRaw(buf) - if merr != nil && merr != io.EOF { - // handle error - for demo we just print it and continue - fmt.Printf("msg: %d - merr: %s\n", n, merr.Error()) - continue - } else if merr == io.EOF { - break - } - - // the first keypair retains values if data correct - // the second keypair relabels "idnet" to "netid" - n, _ := m.NewMap("data.netid", "data.idnet:data.netid") - x, _ := n.XmlIndent("", " ") - - fmt.Println("original value:", string(raw)) - fmt.Println("new value:") - fmt.Println(string(x)) - } -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/readme.md b/Godeps/_workspace/src/github.com/clbanning/mxj/readme.md deleted file mode 100644 index 76cff5df9..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/readme.md +++ /dev/null @@ -1,113 +0,0 @@ -

mxj - to/from maps, XML and JSON

-Marshal/Unmarshal XML to/from JSON and `map[string]interface{}` values, and extract/modify values from maps by key or key-path, including wildcards. - -mxj supplants the legacy x2j and j2x packages. If you want the old syntax, use mxj/x2j and mxj/j2x packages. - -

Notices

- 2014-11-09: IncludeTagSeqNum() adds "_seq" key with XML doc positional information. - (NOTE: PreserveXmlList() is similar and will be here soon.) - 2014-09-18: inspired by NYTimes fork, added PrependAttrWithHyphen() to allow stripping hyphen from attribute tag. - 2014-08-02: AnyXml() and AnyXmlIndent() will try to marshal arbitrary values to XML. - 2014-04-28: ValuesForPath() and NewMap() now accept path with indexed array references. - -

Basic Unmarshal XML / JSON / struct

-
type Map map[string]interface{}
- -Create a `Map` value, 'm', from any `map[string]interface{}` value, 'v': -
m := Map(v)
- -Unmarshal / marshal XML as a `Map` value, 'm': -
m, err := NewMapXml(xmlValue) // unmarshal
-xmlValue, err := m.Xml()      // marshal
- -Unmarshal XML from an `io.Reader` as a `Map` value, 'm': -
m, err := NewMapReader(xmlReader)         // repeated calls, as with an os.File Reader, will process stream
-m, raw, err := NewMapReaderRaw(xmlReader) // 'raw' is the raw XML that was decoded
- -Marshal `Map` value, 'm', to an XML Writer (`io.Writer`): -
err := m.XmlWriter(xmlWriter)
-raw, err := m.XmlWriterRaw(xmlWriter) // 'raw' is the raw XML that was written on xmlWriter
- -Also, for prettified output: -
xmlValue, err := m.XmlIndent(prefix, indent, ...)
-err := m.XmlIndentWriter(xmlWriter, prefix, indent, ...)
-raw, err := m.XmlIndentWriterRaw(xmlWriter, prefix, indent, ...)
- -Bulk process XML with error handling (note: handlers must return a boolean value): -
err := HandleXmlReader(xmlReader, mapHandler(Map), errHandler(error))
-err := HandleXmlReaderRaw(xmlReader, mapHandler(Map, []byte), errHandler(error, []byte))
- -Converting XML to JSON: see Examples for `NewMapXml` and `HandleXmlReader`. - -There are comparable functions and methods for JSON processing. - -Arbitrary structure values can be decoded to / encoded from `Map` values: -
m, err := NewMapStruct(structVal)
-err := m.Struct(structPointer)
- -

Extract / modify Map values

-To work with XML tag values, JSON or Map key values or structure field values, decode the XML, JSON -or structure to a `Map` value, 'm', or cast a `map[string]interface{}` value to a `Map` value, 'm', then: -
paths := m.PathsForKey(key)
-path := m.PathForKeyShortest(key)
-values, err := m.ValuesForKey(key, subkeys)
-values, err := m.ValuesForPath(path, subkeys)
-count, err := m.UpdateValuesForPath(newVal, path, subkeys)
- -Get everything at once, irrespective of path depth: -
leafnodes := m.LeafNodes()
-leafvalues := m.LeafValues()
- -A new `Map` with whatever keys are desired can be created from the current `Map` and then encoded in XML -or JSON. (Note: keys can use dot-notation.) -
newMap := m.NewMap("oldKey_1:newKey_1", "oldKey_2:newKey_2", ..., "oldKey_N:newKey_N")
-newXml := newMap.Xml()   // for example
-newJson := newMap.Json() // ditto
- -

Usage

- -The package is fairly well self-documented with examples. (http://godoc.org/github.com/clbanning/mxj) - -Also, the subdirectory "examples" contains a wide range of examples, several taken from golang-nuts discussions. - -

XML parsing conventions

- - - Attributes are parsed to `map[string]interface{}` values by prefixing a hyphen, `-`, - to the attribute label. (Unless overridden by `PrependAttrWithHyphen(false)`.) - - If the element is a simple element and has attributes, the element value - is given the key `#text` for its `map[string]interface{}` representation. (See - the 'atomFeedString.xml' test data, below.) - -

XML encoding conventions

- - - 'nil' `Map` values, which may represent 'null' JSON values, are encoded as ``. - NOTE: the operation is not symmetric as `` elements are decoded as `tag:""` `Map` values, - which, then, encode in JSON as `"tag":""` values. - -

Running "go test"

- -Because there are no guarantees on the sequence map elements are retrieved, the tests have been -written for visual verification in most cases. One advantage is that you can easily use the -output from running "go test" as examples of calling the various functions and methods. - -

Motivation

- -I make extensive use of JSON for messaging and typically unmarshal the messages into -`map[string]interface{}` variables. This is easily done using `json.Unmarshal` from the -standard Go libraries. Unfortunately, many legacy solutions use structured -XML messages; in those environments the applications would have to be refitted to -interoperate with my components. - -The better solution is to just provide an alternative HTTP handler that receives -XML messages and parses it into a `map[string]interface{}` variable and then reuse -all the JSON-based code. The Go `xml.Unmarshal()` function does not provide the same -option of unmarshaling XML messages into `map[string]interface{}` variables. So I wrote -a couple of small functions to fill this gap and released them as the x2j package. - -Over the next year and a half additional features were added, and the companion j2x -package was released to address XML encoding of arbitrary JSON and `map[string]interface{}` -values. As part of a refactoring of our production system and looking at how we had been -using the x2j and j2x packages we found that we rarely performed direct XML-to-JSON or -JSON-to_XML conversion and that working with the XML or JSON as `map[string]interface{}` -values was the primary value. Thus, everything was refactored into the mxj package. - diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/seqnum_test.go b/Godeps/_workspace/src/github.com/clbanning/mxj/seqnum_test.go deleted file mode 100644 index 7b48a7ca9..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/seqnum_test.go +++ /dev/null @@ -1,52 +0,0 @@ -// seqnum.go - -package mxj - -import ( - "fmt" - "testing" -) - -var seqdata1 = []byte(` - - - - - `) - -var seqdata2 = []byte(` - - - - 1 - hello - true - - - `) - -func TestSeqNumHeader(t *testing.T) { - fmt.Println("\n---------------- seqnum_test.go ...\n") -} - -func TestSeqNum(t *testing.T) { - IncludeTagSeqNum(true) - - m, err := NewMapXml(seqdata1, Cast) - if err != nil { - t.Fatal(err) - } - fmt.Printf("m1: %#v\n", m) - j, _ := m.JsonIndent("", " ") - fmt.Println(string(j)) - - m, err = NewMapXml(seqdata2, Cast) - if err != nil { - t.Fatal(err) - } - fmt.Printf("m2: %#v\n", m) - j, _ = m.JsonIndent("", " ") - fmt.Println(string(j)) - - IncludeTagSeqNum(false) -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/struct.go b/Godeps/_workspace/src/github.com/clbanning/mxj/struct.go deleted file mode 100644 index 3bb2ef7c0..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/struct.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2012-2014 Charles Banning. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file - -package mxj - -import ( - "encoding/json" - "errors" - "github.com/fatih/structs" - "reflect" -) - -// Create a new Map value from a structure. Error returned if argument is not a structure -// or if there is a json.Marshal or json.Unmarshal error. -// Only public structure fields are decoded in the Map value. Also, json.Marshal structure encoding rules -// are followed for decoding the structure fields. -func NewMapStruct(structVal interface{}) (Map, error) { - if !structs.IsStruct(structVal) { - return nil, errors.New("NewMapStruct() error: argument is not type Struct") - } - return structs.Map(structVal), nil -} - -// Marshal a map[string]interface{} into a structure referenced by 'structPtr'. Error returned -// if argument is not a pointer or if json.Unmarshal returns an error. -// json.Unmarshal structure encoding rules are followed to encode public structure fields. -func (mv Map) Struct(structPtr interface{}) error { - m := map[string]interface{}(mv) - j, err := json.Marshal(m) - if err != nil { - return err - } - - // should check that we're getting a pointer. - if reflect.ValueOf(structPtr).Kind() != reflect.Ptr { - return errors.New("mv.Struct() error: argument is not type Ptr") - } - return json.Unmarshal(j, structPtr) -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/struct_test.go b/Godeps/_workspace/src/github.com/clbanning/mxj/struct_test.go deleted file mode 100644 index 799de778d..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/struct_test.go +++ /dev/null @@ -1,84 +0,0 @@ -package mxj - -import ( - "fmt" - "testing" -) - -func TestStructHeader(t *testing.T) { - fmt.Println("\n---------------- struct_test.go ...\n") -} - -func TestNewMapStruct(t *testing.T) { - type str struct { - IntVal int `json:"int"` - StrVal string `json:"str"` - FloatVal float64 `json:"float"` - BoolVal bool `json:"bool"` - private string - } - s := str{IntVal: 4, StrVal: "now's the time", FloatVal: 3.14159, BoolVal: true, private: "It's my party"} - - m, merr := NewMapStruct(s) - if merr != nil { - t.Fatal("merr:", merr.Error()) - } - - fmt.Printf("NewMapStruct, s: %#v\n", s) - fmt.Printf("NewMapStruct, m: %#v\n", m) - - m, merr = NewMapStruct(s) - if merr != nil { - t.Fatal("merr:", merr.Error()) - } - - fmt.Printf("NewMapStruct, s: %#v\n", s) - fmt.Printf("NewMapStruct, m: %#v\n", m) -} - -func TestNewMapStructError(t *testing.T) { - var s string - _, merr := NewMapStruct(s) - if merr == nil { - t.Fatal("NewMapStructError, merr is nil") - } - - fmt.Println("NewMapStructError, merr:", merr.Error()) -} - -func TestStruct(t *testing.T) { - type str struct { - IntVal int `json:"int"` - StrVal string `json:"str"` - FloatVal float64 `json:"float"` - BoolVal bool `json:"bool"` - private string - } - var s str - m := Map{"int": 4, "str": "now's the time", "float": 3.14159, "bool": true, "private": "Somewhere over the rainbow"} - - mverr := m.Struct(&s) - if mverr != nil { - t.Fatal("mverr:", mverr.Error()) - } - - fmt.Printf("Struct, m: %#v\n", m) - fmt.Printf("Struct, s: %#v\n", s) -} - -func TestStructError(t *testing.T) { - type str struct { - IntVal int `json:"int"` - StrVal string `json:"str"` - FloatVal float64 `json:"float"` - BoolVal bool `json:"bool"` - } - var s str - mv := Map{"int": 4, "str": "now's the time", "float": 3.14159, "bool": true} - - mverr := mv.Struct(s) - if mverr == nil { - t.Fatal("StructError, no error returned") - } - fmt.Println("StructError, mverr:", mverr.Error()) -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/updatevalues.go b/Godeps/_workspace/src/github.com/clbanning/mxj/updatevalues.go deleted file mode 100644 index 72413d2d4..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/updatevalues.go +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright 2012-2014 Charles Banning. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file - -// updatevalues.go - modify a value based on path and possibly sub-keys - -package mxj - -import ( - "fmt" - "strconv" - "strings" -) - -// Update value based on path and possible sub-key values. -// A count of the number of values changed and any error are returned. -// If the count == 0, then no path (and subkeys) matched. -// 'newVal' can be a Map or map[string]interface{} value with a single 'key' that is the key to be modified -// or a string value "key:value[:type]" where type is "bool" or "num" to cast the value. -// 'path' is dot-notation list of keys to traverse; last key in path can be newVal key -// NOTE: 'path' spec does not currently support indexed array references. -// 'subkeys' are "key:value[:type]" entries that must match for path node -// The subkey can be wildcarded - "key:*" - to require that it's there with some value. -// If a subkey is preceeded with the '!' character, the key:value[:type] entry is treated as an -// exclusion critera - e.g., "!author:William T. Gaddis". -func (mv Map) UpdateValuesForPath(newVal interface{}, path string, subkeys ...string) (int, error) { - m := map[string]interface{}(mv) - - // extract the subkeys - var subKeyMap map[string]interface{} - if len(subkeys) > 0 { - var err error - subKeyMap, err = getSubKeyMap(subkeys...) - if err != nil { - return 0, err - } - } - - // extract key and value from newVal - var key string - var val interface{} - switch newVal.(type) { - case map[string]interface{}, Map: - switch newVal.(type) { // "fallthrough is not permitted in type switch" (Spec) - case Map: - newVal = newVal.(Map).Old() - } - if len(newVal.(map[string]interface{})) != 1 { - return 0, fmt.Errorf("newVal map can only have len == 1 - %+v", newVal) - } - for key, val = range newVal.(map[string]interface{}) { - } - case string: // split it as a key:value pair - ss := strings.Split(newVal.(string), ":") - n := len(ss) - if n < 2 || n > 3 { - return 0, fmt.Errorf("unknown newVal spec - %+v", newVal) - } - key = ss[0] - if n == 2 { - val = interface{}(ss[1]) - } else if n == 3 { - switch ss[2] { - case "bool", "boolean": - nv, err := strconv.ParseBool(ss[1]) - if err != nil { - return 0, fmt.Errorf("can't convert newVal to bool - %+v", newVal) - } - val = interface{}(nv) - case "num", "numeric", "float", "int": - nv, err := strconv.ParseFloat(ss[1], 64) - if err != nil { - return 0, fmt.Errorf("can't convert newVal to float64 - %+v", newVal) - } - val = interface{}(nv) - default: - return 0, fmt.Errorf("unknown type for newVal value - %+v", newVal) - } - } - default: - return 0, fmt.Errorf("invalid newVal type - %+v", newVal) - } - - // parse path - keys := strings.Split(path, ".") - - var count int - updateValuesForKeyPath(key, val, m, keys, subKeyMap, &count) - - return count, nil -} - -// navigate the path -func updateValuesForKeyPath(key string, value interface{}, m interface{}, keys []string, subkeys map[string]interface{}, cnt *int) { - // ----- at end node: looking at possible node to get 'key' ---- - if len(keys) == 1 { - updateValue(key, value, m, keys[0], subkeys, cnt) - return - } - - // ----- here we are navigating the path thru the penultimate node -------- - // key of interest is keys[0] - the next in the path - switch keys[0] { - case "*": // wildcard - scan all values - switch m.(type) { - case map[string]interface{}: - for _, v := range m.(map[string]interface{}) { - updateValuesForKeyPath(key, value, v, keys[1:], subkeys, cnt) - } - case []interface{}: - for _, v := range m.([]interface{}) { - switch v.(type) { - // flatten out a list of maps - keys are processed - case map[string]interface{}: - for _, vv := range v.(map[string]interface{}) { - updateValuesForKeyPath(key, value, vv, keys[1:], subkeys, cnt) - } - default: - updateValuesForKeyPath(key, value, v, keys[1:], subkeys, cnt) - } - } - } - default: // key - must be map[string]interface{} - switch m.(type) { - case map[string]interface{}: - if v, ok := m.(map[string]interface{})[keys[0]]; ok { - updateValuesForKeyPath(key, value, v, keys[1:], subkeys, cnt) - } - case []interface{}: // may be buried in list - for _, v := range m.([]interface{}) { - switch v.(type) { - case map[string]interface{}: - if vv, ok := v.(map[string]interface{})[keys[0]]; ok { - updateValuesForKeyPath(key, value, vv, keys[1:], subkeys, cnt) - } - } - } - } - } -} - -// change value if key and subkeys are present -func updateValue(key string, value interface{}, m interface{}, keys0 string, subkeys map[string]interface{}, cnt *int) { - // there are two possible options for the value of 'keys0': map[string]interface, []interface{} - // and 'key' is a key in the map or is a key in a map in a list. - switch m.(type) { - case map[string]interface{}: // gotta have the last key - if keys0 == "*" { - for k, _ := range m.(map[string]interface{}) { - updateValue(key, value, m, k, subkeys, cnt) - } - return - } - endVal, _ := m.(map[string]interface{})[keys0] - - // if newV key is the end of path, replace the value for path-end - // may be []interface{} - means replace just an entry w/ subkeys - // otherwise replace the keys0 value if subkeys are there - // NOTE: this will replace the subkeys, also - if key == keys0 { - switch endVal.(type) { - case map[string]interface{}: - if ok := hasSubKeys(m, subkeys); ok { - (m.(map[string]interface{}))[keys0] = value - (*cnt)++ - } - case []interface{}: - // without subkeys can't select list member to modify - // so key:value spec is it ... - if len(subkeys) == 0 { - (m.(map[string]interface{}))[keys0] = value - (*cnt)++ - break - } - nv := make([]interface{}, 0) - var valmodified bool - for _, v := range endVal.([]interface{}) { - // check entry subkeys - if ok := hasSubKeys(v, subkeys); ok { - // replace v with value - nv = append(nv, value) - valmodified = true - (*cnt)++ - continue - } - nv = append(nv, v) - } - if valmodified { - (m.(map[string]interface{}))[keys0] = interface{}(nv) - } - default: // anything else is a strict replacement - if len(subkeys) == 0 { - (m.(map[string]interface{}))[keys0] = value - (*cnt)++ - } - } - return - } - - // so value is for an element of endVal - // if endVal is a map then 'key' must be there w/ subkeys - // if endVal is a list then 'key' must be in a list member w/ subkeys - switch endVal.(type) { - case map[string]interface{}: - if ok := hasSubKeys(endVal, subkeys); !ok { - return - } - if _, ok := (endVal.(map[string]interface{}))[key]; ok { - (endVal.(map[string]interface{}))[key] = value - (*cnt)++ - } - case []interface{}: // keys0 points to a list, check subkeys - for _, v := range endVal.([]interface{}) { - // got to be a map so we can replace value for 'key' - vv, vok := v.(map[string]interface{}) - if !vok { - continue - } - if _, ok := vv[key]; !ok { - continue - } - if !hasSubKeys(vv, subkeys) { - continue - } - vv[key] = value - (*cnt)++ - } - } - case []interface{}: // key may be in a list member - // don't need to handle keys0 == "*"; we're looking at everything, anyway. - for _, v := range m.([]interface{}) { - // only map values - we're looking for 'key' - mm, ok := v.(map[string]interface{}) - if !ok { - continue - } - if _, ok := mm[key]; !ok { - continue - } - if !hasSubKeys(mm, subkeys) { - continue - } - mm[key] = value - (*cnt)++ - } - } - - // return -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/updatevalues_test.go b/Godeps/_workspace/src/github.com/clbanning/mxj/updatevalues_test.go deleted file mode 100644 index dca2da91b..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/updatevalues_test.go +++ /dev/null @@ -1,187 +0,0 @@ -// modifyvalues_test.go - test keyvalues.go methods - -package mxj - -import ( - "fmt" - "testing" -) - -func TestUVHeader(t *testing.T) { - fmt.Println("\n---------------- updatevalues_test.go ...\n") -} - -func TestUpdateValuesForPath_Author(t *testing.T) { - m, merr := NewMapXml(doc1) - if merr != nil { - t.Fatal("merr:", merr.Error()) - } - fmt.Println("m:", m) - - ss, _ := m.ValuesForPath("doc.books.book.author") - for _, v := range ss { - fmt.Println("v:", v) - } - fmt.Println("m.UpdateValuesForPath(\"author:NoName\", \"doc.books.book.author\")") - n, err := m.UpdateValuesForPath("author:NoName", "doc.books.book.author") - if err != nil { - t.Fatal("err:", err.Error()) - } - fmt.Println(n, "updates") - ss, _ = m.ValuesForPath("doc.books.book.author") - for _, v := range ss { - fmt.Println("v:", v) - } - - fmt.Println("m.UpdateValuesForPath(\"author:William Gadddis\", \"doc.books.book.author\", \"title:The Recognitions\")") - n, err = m.UpdateValuesForPath("author:William Gadddis", "doc.books.book.author", "title:The Recognitions") - o, _ := m.UpdateValuesForPath("author:Austin Tappen Wright", "doc.books.book", "title:Islandia") - p, _ := m.UpdateValuesForPath("author:John Hawkes", "doc.books.book", "title:The Beetle Leg") - q, _ := m.UpdateValuesForPath("author:T. E. Porter", "doc.books.book", "title:King's Day") - if err != nil { - t.Fatal("err:", err.Error()) - } - fmt.Println(n+o+p+q, "updates") - ss, _ = m.ValuesForPath("doc.books.book.author") - for _, v := range ss { - fmt.Println("v:", v) - } - - fmt.Println("m.UpdateValuesForPath(\"author:William T. Gaddis\", \"doc.books.book.*\", \"title:The Recognitions\")") - n, _ = m.UpdateValuesForPath("author:William T. Gaddis", "doc.books.book.*", "title:The Recognitions") - fmt.Println(n, "updates") - ss, _ = m.ValuesForPath("doc.books.book.author") - for _, v := range ss { - fmt.Println("v:", v) - } - - fmt.Println("m.UpdateValuesForPath(\"title:The Cannibal\", \"doc.books.book.title\", \"author:John Hawkes\")") - n, _ = m.UpdateValuesForPath("title:The Cannibal", "doc.books.book.title", "author:John Hawkes") - o, _ = m.UpdateValuesForPath("review:A novel on his experiences in WWII.", "doc.books.book.review", "title:The Cannibal") - fmt.Println(n+o, "updates") - ss, _ = m.ValuesForPath("doc.books.book") - for _, v := range ss { - fmt.Println("v:", v) - } - - fmt.Println("m.UpdateValuesForPath(\"books:\", \"doc.books\")") - n, _ = m.UpdateValuesForPath("books:", "doc.books") - fmt.Println(n, "updates") - fmt.Println("m:", m) - - fmt.Println("m.UpdateValuesForPath(mm, \"*\")") - mm, _ := NewMapXml(doc1) - n, err = m.UpdateValuesForPath(mm, "*") - if err != nil { - t.Fatal("err:", err.Error()) - } - fmt.Println(n, "updates") - fmt.Println("m:", m) - - // ---------------------- newDoc - var newDoc = []byte(`simple element`) - m, merr = NewMapXml(newDoc) - if merr != nil { - t.Fatal("merr:", merr.Error()) - } - fmt.Println("\nnewDoc:", string(newDoc)) - fmt.Println("m:", m) - fmt.Println("m.UpdateValuesForPath(\"#text:maybe not so simple element\", \"tag\")") - n, _ = m.UpdateValuesForPath("#text:maybe not so simple element", "tag") - fmt.Println("n:", n, "m:", m) - fmt.Println("m.UpdateValuesForPath(\"#text:simple element again\", \"*\")") - n, _ = m.UpdateValuesForPath("#text:simple element again", "*") - fmt.Println("n:", n, "m:", m) - - /* - fmt.Println("UpdateValuesForPath, doc.books.book, title:The Recognitions : NoBook") - n, err = m.UpdateValuesForPath("NoBook", "doc.books.book", "title:The Recognitions") - if err != nil { - t.Fatal("err:", err.Error()) - } - fmt.Println(n, "updates") - ss, _ = m.ValuesForPath("doc.books.book") - for _, v := range ss { - fmt.Println("v:", v) - } - - fmt.Println("UpdateValuesForPath, doc.books.book.title -seq=3: The Blood Oranges") - n, err = m.UpdateValuesForPath("The Blood Oranges", "doc.books.book.title", "-seq:3") - if err != nil { - t.Fatal("err:", err.Error()) - } - fmt.Println(n, "updates") - ss, _ = m.ValuesForPath("doc.books.book.title") - for _, v := range ss { - fmt.Println("v:", v) - } - */ -} - -var authorDoc = []byte(` - - - William Gaddis - - - The Recognitions - 1955 - A novel that changed the face of American literature. - - - JR - 1975 - Winner of National Book Award for Fiction. - - - - - John Hawkes - - - The Cannibal - 1949 - A novel on his experiences in WWII. - - - The Beetle Leg - 1951 - A lyrical novel about the construction of Ft. Peck Dam in Montana. - - - The Blood Oranges - 1970 - Where everyone wants to vacation. - - - -`) - -func TestAuthorDoc(t *testing.T) { - m, merr := NewMapXml(authorDoc) - if merr != nil { - t.Fatal("merr:", merr.Error()) - } - fmt.Println(m.StringIndent()) - - fmt.Println("m.UpdateValuesForPath(\"review:National Book Award winner.\", \"*.*.*.*\", \"title:JR\")") - n, _ := m.UpdateValuesForPath("review:National Book Award winner.", "*.*.*.*", "title:JR") - fmt.Println(n, "updates") - ss, _ := m.ValuesForPath("biblio.author", "name:William Gaddis") - for _, v := range ss { - fmt.Println("v:", v) - } - - fmt.Println("m.UpdateValuesForPath(newVal, path, oldVal)") - path := m.PathForKeyShortest("date") - v, _ := m.ValuesForPath(path) - var counter int - for _, vv := range v { - oldVal := "date:" + vv.(string) - newVal := "date:" + vv.(string) + ":num" - n, _ = m.UpdateValuesForPath(newVal, path, oldVal) - counter += n - } - fmt.Println(counter, "updates") - fmt.Println(m.StringIndent()) -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/x2j/x2j.go b/Godeps/_workspace/src/github.com/clbanning/mxj/x2j/x2j.go deleted file mode 100644 index 5891aa1df..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/x2j/x2j.go +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright 2012-2014 Charles Banning. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file - -// x2j - For (mostly) backwards compatibility with legacy x2j package. -// Wrappers for end-to-end XML to JSON transformation and value manipulation. -package x2j - -import ( - . "github.com/clbanning/mxj" - "io" -) - -// FromXml() --> map[string]interface{} -func XmlToMap(xmlVal []byte) (map[string]interface{}, error) { - m, err := NewMapXml(xmlVal) - if err != nil { - return nil, err - } - return map[string]interface{}(m), nil -} - -// map[string]interface{} --> ToXml() -func MapToXml(m map[string]interface{}) ([]byte, error) { - return Map(m).Xml() -} - -// FromXml() --> ToJson(). -func XmlToJson(xmlVal []byte, safeEncoding ...bool) ([]byte, error) { - m, err := NewMapXml(xmlVal) - if err != nil { - return nil, err - } - return m.Json(safeEncoding...) -} - -// FromXml() --> ToJsonWriterRaw(). -func XmlToJsonWriter(xmlVal []byte, jsonWriter io.Writer, safeEncoding ...bool) ([]byte, error) { - m, err := NewMapXml(xmlVal) - if err != nil { - return nil, err - } - return m.JsonWriterRaw(jsonWriter, safeEncoding...) -} - -// FromXmlReaderRaw() --> ToJson(). -func XmlReaderToJson(xmlReader io.Reader, safeEncoding ...bool) ([]byte, []byte, error) { - m, xraw, err := NewMapXmlReaderRaw(xmlReader) - if err != nil { - return xraw, nil, err - } - j, jerr := m.Json(safeEncoding...) - return xraw, j, jerr -} - -// FromXmlReader() --> ToJsonWriter(). Handy for bulk transformation of documents. -func XmlReaderToJsonWriter(xmlReader io.Reader, jsonWriter io.Writer, safeEncoding ...bool) ([]byte, []byte, error) { - m, xraw, err := NewMapXmlReaderRaw(xmlReader) - if err != nil { - return xraw, nil, err - } - jraw, jerr := m.JsonWriterRaw(jsonWriter, safeEncoding...) - return xraw, jraw, jerr -} - -// XML wrappers for Map methods implementing tag path and value functions. - -// Wrap PathsForKey for XML. -func XmlPathsForTag(xmlVal []byte, tag string) ([]string, error) { - m, err := NewMapXml(xmlVal) - if err != nil { - return nil, err - } - paths := m.PathsForKey(tag) - return paths, nil -} - -// Wrap PathForKeyShortest for XML. -func XmlPathForTagShortest(xmlVal []byte, tag string) (string, error) { - m, err := NewMapXml(xmlVal) - if err != nil { - return "", err - } - path := m.PathForKeyShortest(tag) - return path, nil -} - -// Wrap ValuesForKey for XML. -// 'attrs' are key:value pairs for attributes, where key is attribute label prepended with a hypen, '-'. -func XmlValuesForTag(xmlVal []byte, tag string, attrs ...string) ([]interface{}, error) { - m, err := NewMapXml(xmlVal) - if err != nil { - return nil, err - } - return m.ValuesForKey(tag, attrs...) -} - -// Wrap ValuesForPath for XML. -// 'attrs' are key:value pairs for attributes, where key is attribute label prepended with a hypen, '-'. -func XmlValuesForPath(xmlVal []byte, path string, attrs ...string) ([]interface{}, error) { - m, err := NewMapXml(xmlVal) - if err != nil { - return nil, err - } - return m.ValuesForPath(path, attrs...) -} - -// Wrap UpdateValuesForPath for XML -// 'xmlVal' is XML value -// 'newTagValue' is the value to replace an existing value at the end of 'path' -// 'path' is the dot-notation path with the tag whose value is to be replaced at the end -// (can include wildcard character, '*') -// 'subkeys' are key:value pairs of tag:values that must match for the tag -func XmlUpdateValsForPath(xmlVal []byte, newTagValue interface{}, path string, subkeys ...string) ([]byte, error) { - m, err := NewMapXml(xmlVal) - if err != nil { - return nil, err - } - _, err = m.UpdateValuesForPath(newTagValue, path, subkeys...) - if err != nil { - return nil, err - } - return m.Xml() -} - -// Wrap NewMap for XML and return as XML -// 'xmlVal' is an XML value -// 'tagpairs' are "oldTag:newTag" values that conform to 'keypairs' in (Map)NewMap. -func XmlNewXml(xmlVal []byte, tagpairs ...string) ([]byte, error) { - m, err := NewMapXml(xmlVal) - if err != nil { - return nil, err - } - n, err := m.NewMap(tagpairs...) - if err != nil { - return nil, err - } - return n.Xml() -} - -// Wrap NewMap for XML and return as JSON -// 'xmlVal' is an XML value -// 'tagpairs' are "oldTag:newTag" values that conform to 'keypairs' in (Map)NewMap. -func XmlNewJson(xmlVal []byte, tagpairs ...string) ([]byte, error) { - m, err := NewMapXml(xmlVal) - if err != nil { - return nil, err - } - n, err := m.NewMap(tagpairs...) - if err != nil { - return nil, err - } - return n.Json() -} - -// Wrap LeafNodes for XML. -// 'xmlVal' is an XML value -func XmlLeafNodes(xmlVal []byte) ([]LeafNode, error) { - m, err := NewMapXml(xmlVal) - if err != nil { - return nil, err - } - return m.LeafNodes(), nil -} - -// Wrap LeafValues for XML. -// 'xmlVal' is an XML value -func XmlLeafValues(xmlVal []byte) ([]interface{}, error) { - m, err := NewMapXml(xmlVal) - if err != nil { - return nil, err - } - return m.LeafValues(), nil -} - -// Wrap LeafPath for XML. -// 'xmlVal' is an XML value -func XmlLeafPath(xmlVal []byte) ([]string, error) { - m, err := NewMapXml(xmlVal) - if err != nil { - return nil, err - } - return m.LeafPaths(), nil -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/xml.go b/Godeps/_workspace/src/github.com/clbanning/mxj/xml.go deleted file mode 100644 index 691bc0216..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/xml.go +++ /dev/null @@ -1,838 +0,0 @@ -// Copyright 2012-2014 Charles Banning. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file - -// xml.go - basically the core of X2j for map[string]interface{} values. -// NewMapXml, NewMapXmlReader, mv.Xml, mv.XmlWriter -// see x2j and j2x for wrappers to provide end-to-end transformation of XML and JSON messages. - -package mxj - -import ( - "bytes" - "encoding/xml" - "errors" - "fmt" - "io" - "regexp" - "strconv" - "strings" - "time" -) - -// ------------------- NewMapXml & NewMapXmlReader ... from x2j2 ------------------------- - -// If XmlCharsetReader != nil, it will be used to decode the XML, if required. -// import ( -// charset "code.google.com/p/go-charset/charset" -// github.com/clbanning/mxj -// ) -// ... -// mxj.XmlCharsetReader = charset.NewReader -// m, merr := mxj.NewMapXml(xmlValue) -var XmlCharsetReader func(charset string, input io.Reader) (io.Reader, error) - -// NewMapXml - convert a XML doc into a Map -// (This is analogous to unmarshalling a JSON string to map[string]interface{} using json.Unmarshal().) -// If the optional argument 'cast' is 'true', then values will be converted to boolean or float64 if possible. -// -// Converting XML to JSON is a simple as: -// ... -// mapVal, merr := mxj.NewMapXml(xmlVal) -// if merr != nil { -// // handle error -// } -// jsonVal, jerr := mapVal.Json() -// if jerr != nil { -// // handle error -// } -func NewMapXml(xmlVal []byte, cast ...bool) (Map, error) { - var r bool - if len(cast) == 1 { - r = cast[0] - } - n, err := xmlToTree(xmlVal) - if err != nil { - return nil, err - } - - m := make(map[string]interface{}, 0) - m[n.key] = n.treeToMap(r) - - return m, nil -} - -// Get next XML doc from an io.Reader as a Map value. Returns Map value. -func NewMapXmlReader(xmlReader io.Reader, cast ...bool) (Map, error) { - var r bool - if len(cast) == 1 { - r = cast[0] - } - - // build the node tree - n, err := xmlReaderToTree(xmlReader) - if err != nil { - return nil, err - } - - // create the Map value - m := make(map[string]interface{}) - m[n.key] = n.treeToMap(r) - - return m, nil -} - -// XmlWriterBufSize - set the size of io.Writer for the TeeReader used by NewMapXmlReaderRaw() -// and HandleXmlReaderRaw(). This reduces repeated memory allocations and copy() calls in most cases. -var XmlWriterBufSize int = 256 - -// Get next XML doc from an io.Reader as a Map value. Returns Map value and slice with the raw XML. -// NOTES: 1. Due to the implementation of xml.Decoder, the raw XML off the reader is buffered to []byte -// using a ByteReader. If the io.Reader is an os.File, there may be significant performance impact. -// See the examples - getmetrics1.go through getmetrics4.go - for comparative use cases on a large -// data set. If the io.Reader is wrapping a []byte value in-memory, however, such as http.Request.Body -// you CAN use it to efficiently unmarshal a XML doc and retrieve the raw XML in a single call. -// 2. The 'raw' return value may be larger than the XML text value. To log it, cast it to a string. -func NewMapXmlReaderRaw(xmlReader io.Reader, cast ...bool) (Map, []byte, error) { - var r bool - if len(cast) == 1 { - r = cast[0] - } - // create TeeReader so we can retrieve raw XML - buf := make([]byte, XmlWriterBufSize) - wb := bytes.NewBuffer(buf) - trdr := myTeeReader(xmlReader, wb) // see code at EOF - - // build the node tree - n, err := xmlReaderToTree(trdr) - - // retrieve the raw XML that was decoded - b := make([]byte, wb.Len()) - _, _ = wb.Read(b) - - if err != nil { - return nil, b, err - } - - // create the Map value - m := make(map[string]interface{}) - m[n.key] = n.treeToMap(r) - - return m, b, nil -} - -// xmlReaderToTree() - parse a XML io.Reader to a tree of nodes -func xmlReaderToTree(rdr io.Reader) (*node, error) { - // parse the Reader - p := xml.NewDecoder(rdr) - p.CharsetReader = XmlCharsetReader - return xmlToTreeParser("", nil, p) -} - -// for building the parse tree -type node struct { - dup bool // is member of a list - attr bool // is an attribute - key string // XML tag - val string // element value - nodes []*node -} - -// xmlToTree - convert a XML doc into a tree of nodes. -func xmlToTree(doc []byte) (*node, error) { - // xml.Decoder doesn't properly handle whitespace in some doc - // see songTextString.xml test case ... - reg, _ := regexp.Compile("[ \t\n\r]*<") - doc = reg.ReplaceAll(doc, []byte("<")) - - b := bytes.NewReader(doc) - p := xml.NewDecoder(b) - p.CharsetReader = XmlCharsetReader - n, berr := xmlToTreeParser("", nil, p) - if berr != nil { - return nil, berr - } - - return n, nil -} - -// we allow people to drop hyphen when unmarshaling the XML doc. -var useHyphen bool = true - -// PrependAttrWithHyphen. Prepend attribute tags with a hyphen. -// Default is 'true'. -// Note: -// If 'false', unmarshaling and marshaling is not symmetric. Attributes will be -// marshal'd as attr and may be part of a list. -func PrependAttrWithHyphen(v bool) { - useHyphen = v -} - -// Include sequence id with inner tags. - per Sean Murphy, murphysean84@gmail.com. -var includeTagSeqNum bool - -// IncludeTagSeqNum - include a "_seq":N key:value pair with each inner tag, denoting -// its position when parsed. E.g., -/* - - - - - hello - - - parses as: - - { - Obj:{ - "-c":"la", - "-h":"da", - "-x":"dee", - "intObj":[ - { - "-id"="3", - "_seq":"0" // if mxj.Cast is passed, then: "_seq":0 - }, - { - "-id"="2", - "_seq":"2" - }], - "intObj1":{ - "-id":"1", - "_seq":"1" - }, - "StrObj":{ - "#text":"hello", // simple element value gets "#text" tag - "_seq":"3" - } - } - } -*/ -func IncludeTagSeqNum(b bool) { - includeTagSeqNum = b -} - -// xmlToTreeParser - load a 'clean' XML doc into a tree of *node. -func xmlToTreeParser(skey string, a []xml.Attr, p *xml.Decoder) (*node, error) { - n := new(node) - n.nodes = make([]*node, 0) - var seq int // for includeTagSeqNum - - if skey != "" { - n.key = skey - if len(a) > 0 { - for _, v := range a { - na := new(node) - na.attr = true - if useHyphen { - na.key = `-` + v.Name.Local - } else { - na.key = v.Name.Local - } - na.val = v.Value - n.nodes = append(n.nodes, na) - } - } - } - for { - t, err := p.Token() - if err != nil { - if err != io.EOF { - return nil, errors.New("xml.Decoder.Token() - " + err.Error()) - } - return nil, err - } - switch t.(type) { - case xml.StartElement: - tt := t.(xml.StartElement) - // handle root - if n.key == "" { - n.key = tt.Name.Local - if len(tt.Attr) > 0 { - for _, v := range tt.Attr { - na := new(node) - na.attr = true - if useHyphen { - na.key = `-` + v.Name.Local - } else { - na.key = v.Name.Local - } - na.val = v.Value - n.nodes = append(n.nodes, na) - } - } - } else { - nn, nnerr := xmlToTreeParser(tt.Name.Local, tt.Attr, p) - if nnerr != nil { - return nil, nnerr - } - n.nodes = append(n.nodes, nn) - if includeTagSeqNum { // 2014.11.09 - sn := &node{false, false, "_seq", strconv.Itoa(seq), nil} - nn.nodes = append(nn.nodes, sn) - seq++ - } - } - case xml.EndElement: - // scan n.nodes for duplicate n.key values - n.markDuplicateKeys() - return n, nil - case xml.CharData: - tt := string(t.(xml.CharData)) - // clean up possible noise - tt = strings.Trim(tt, "\t\r\b\n ") - if len(n.nodes) > 0 && len(tt) > 0 { - // if len(n.nodes) > 0 { - nn := new(node) - nn.key = "#text" - nn.val = tt - n.nodes = append(n.nodes, nn) - } else { - n.val = tt - } - if includeTagSeqNum { // 2014.11.09 - if len(n.nodes) == 0 { // treat like a simple element with attributes - nn := new(node) - nn.key = "#text" - nn.val = tt - n.nodes = append(n.nodes, nn) - } - sn := &node{false, false, "_seq", strconv.Itoa(seq), nil} - n.nodes = append(n.nodes, sn) - seq++ - } - default: - // noop - } - } - // Logically we can't get here, but provide an error message anyway. - return nil, fmt.Errorf("Unknown parse error in xmlToTree() for: %s", n.key) -} - -// (*node)markDuplicateKeys - set node.dup flag for loading map[string]interface{}. -func (n *node) markDuplicateKeys() { - l := len(n.nodes) - for i := 0; i < l; i++ { - if n.nodes[i].dup { - continue - } - for j := i + 1; j < l; j++ { - if n.nodes[i].key == n.nodes[j].key { - n.nodes[i].dup = true - n.nodes[j].dup = true - } - } - } -} - -// (*node)treeToMap - convert a tree of nodes into a map[string]interface{}. -// (Parses to map that is structurally the same as from json.Unmarshal().) -// Note: root is not instantiated; call with: "m[n.key] = n.treeToMap(cast)". -func (n *node) treeToMap(r bool) interface{} { - if len(n.nodes) == 0 { - return cast(n.val, r) - } - - m := make(map[string]interface{}, 0) - for _, v := range n.nodes { - // 2014.11.9 - may have to back out - if includeTagSeqNum { - if len(v.nodes) == 1 { - m[v.key] = cast(v.val, r) - continue - } - } - - // just a value - if !v.dup && len(v.nodes) == 0 { - m[v.key] = cast(v.val, r) - continue - } - // a list of values - if v.dup { - var a []interface{} - if vv, ok := m[v.key]; ok { - a = vv.([]interface{}) - } else { - a = make([]interface{}, 0) - } - a = append(a, v.treeToMap(r)) - m[v.key] = interface{}(a) - continue - } - - // it's a unique key - m[v.key] = v.treeToMap(r) - } - - return interface{}(m) -} - -// cast - try to cast string values to bool or float64 -func cast(s string, r bool) interface{} { - if r { - // handle numeric strings ahead of boolean - if f, err := strconv.ParseFloat(s, 64); err == nil { - return interface{}(f) - } - // ParseBool treats "1"==true & "0"==false - // but be more strick - only allow TRUE, True, true, FALSE, False, false - if s != "t" && s != "T" && s != "f" && s != "F" { - if b, err := strconv.ParseBool(s); err == nil { - return interface{}(b) - } - } - } - return interface{}(s) -} - -// ------------------ END: NewMapXml & NewMapXmlReader ------------------------- - -// ------------------ mv.Xml & mv.XmlWriter - from j2x ------------------------ - -const ( - DefaultRootTag = "doc" -) - -var useGoXmlEmptyElemSyntax bool - -// XmlGoEmptyElemSyntax() - rather than . -// Go's encoding/xml package marshals empty XML elements as . By default this package -// encodes empty elements as . If you're marshaling Map values that include structures -// (which are passed to xml.Marshal for encoding), this will let you conform to the standard package. -// -// Alternatively, you can replace the encoding/xml/marshal.go file in the standard libary with the -// patched version in the "xml_marshal" folder in this package. Then use xml.SetUseNullEndTag(true) -// to have all XML encoding use for empty elements. -func XmlGoEmptyElemSyntax() { - useGoXmlEmptyElemSyntax = true -} - -// XmlDefaultEmptyElemSyntax() - rather than . -// Return XML encoding for empty elements to the default package setting. -// Reverses effect of XmlGoEmptyElemSyntax(). -func XmlDefaultEmptyElemSyntax() { - useGoXmlEmptyElemSyntax = false -} - -// Encode a Map as XML. The companion of NewMapXml(). -// The following rules apply. -// - The key label "#text" is treated as the value for a simple element with attributes. -// - Map keys that begin with a hyphen, '-', are interpreted as attributes. -// It is an error if the attribute doesn't have a []byte, string, number, or boolean value. -// - Map value type encoding: -// > string, bool, float64, int, int32, int64, float32: per "%v" formating -// > []bool, []uint8: by casting to string -// > structures, etc.: handed to xml.Marshal() - if there is an error, the element -// value is "UNKNOWN" -// - Elements with only attribute values or are null are terminated using "/>". -// - If len(mv) == 1 and no rootTag is provided, then the map key is used as the root tag, possible. -// Thus, `{ "key":"value" }` encodes as "value". -// - To encode empty elements in a syntax consistent with encoding/xml call UseGoXmlEmptyElementSyntax(). -func (mv Map) Xml(rootTag ...string) ([]byte, error) { - m := map[string]interface{}(mv) - var err error - s := new(string) - p := new(pretty) // just a stub - - if len(m) == 1 && len(rootTag) == 0 { - for key, value := range m { - // if it an array, see if all values are map[string]interface{} - // we force a new root tag if we'll end up with no key:value in the list - // so: key:[string_val, bool:true] --> string_valtrue - switch value.(type) { - case []interface{}: - for _, v := range value.([]interface{}) { - switch v.(type) { - case map[string]interface{}: // noop - default: // anything else - err = mapToXmlIndent(false, s, DefaultRootTag, m, p) - goto done - } - } - } - err = mapToXmlIndent(false, s, key, value, p) - } - } else if len(rootTag) == 1 { - err = mapToXmlIndent(false, s, rootTag[0], m, p) - } else { - err = mapToXmlIndent(false, s, DefaultRootTag, m, p) - } -done: - return []byte(*s), err -} - -// The following implementation is provided only for symmetry with NewMapXmlReader[Raw] -// The names will also provide a key for the number of return arguments. - -// Writes the Map as XML on the Writer. -// See Xml() for encoding rules. -func (mv Map) XmlWriter(xmlWriter io.Writer, rootTag ...string) error { - x, err := mv.Xml(rootTag...) - if err != nil { - return err - } - - _, err = xmlWriter.Write(x) - return err -} - -// Writes the Map as XML on the Writer. []byte is the raw XML that was written. -// See Xml() for encoding rules. -func (mv Map) XmlWriterRaw(xmlWriter io.Writer, rootTag ...string) ([]byte, error) { - x, err := mv.Xml(rootTag...) - if err != nil { - return x, err - } - - _, err = xmlWriter.Write(x) - return x, err -} - -// Writes the Map as pretty XML on the Writer. -// See Xml() for encoding rules. -func (mv Map) XmlIndentWriter(xmlWriter io.Writer, prefix, indent string, rootTag ...string) error { - x, err := mv.XmlIndent(prefix, indent, rootTag...) - if err != nil { - return err - } - - _, err = xmlWriter.Write(x) - return err -} - -// Writes the Map as pretty XML on the Writer. []byte is the raw XML that was written. -// See Xml() for encoding rules. -func (mv Map) XmlIndentWriterRaw(xmlWriter io.Writer, prefix, indent string, rootTag ...string) ([]byte, error) { - x, err := mv.XmlIndent(prefix, indent, rootTag...) - if err != nil { - return x, err - } - - _, err = xmlWriter.Write(x) - return x, err -} - -// -------------------- END: mv.Xml & mv.XmlWriter ------------------------------- - -// -------------- Handle XML stream by processing Map value -------------------- - -// Default poll delay to keep Handler from spinning on an open stream -// like sitting on os.Stdin waiting for imput. -var xhandlerPollInterval = time.Duration(1e6) - -// Bulk process XML using handlers that process a Map value. -// 'rdr' is an io.Reader for XML (stream) -// 'mapHandler' is the Map processor. Return of 'false' stops io.Reader processing. -// 'errHandler' is the error processor. Return of 'false' stops io.Reader processing and returns the error. -// Note: mapHandler() and errHandler() calls are blocking, so reading and processing of messages is serialized. -// This means that you can stop reading the file on error or after processing a particular message. -// To have reading and handling run concurrently, pass argument to a go routine in handler and return 'true'. -func HandleXmlReader(xmlReader io.Reader, mapHandler func(Map) bool, errHandler func(error) bool) error { - var n int - for { - m, merr := NewMapXmlReader(xmlReader) - n++ - - // handle error condition with errhandler - if merr != nil && merr != io.EOF { - merr = fmt.Errorf("[xmlReader: %d] %s", n, merr.Error()) - if ok := errHandler(merr); !ok { - // caused reader termination - return merr - } - continue - } - - // pass to maphandler - if len(m) != 0 { - if ok := mapHandler(m); !ok { - break - } - } else if merr != io.EOF { - <-time.After(xhandlerPollInterval) - } - - if merr == io.EOF { - break - } - } - return nil -} - -// Bulk process XML using handlers that process a Map value and the raw XML. -// 'rdr' is an io.Reader for XML (stream) -// 'mapHandler' is the Map and raw XML - []byte - processor. Return of 'false' stops io.Reader processing. -// 'errHandler' is the error and raw XML processor. Return of 'false' stops io.Reader processing and returns the error. -// Note: mapHandler() and errHandler() calls are blocking, so reading and processing of messages is serialized. -// This means that you can stop reading the file on error or after processing a particular message. -// To have reading and handling run concurrently, pass argument(s) to a go routine in handler and return 'true'. -// See NewMapXmlReaderRaw for comment on performance associated with retrieving raw XML from a Reader. -func HandleXmlReaderRaw(xmlReader io.Reader, mapHandler func(Map, []byte) bool, errHandler func(error, []byte) bool) error { - var n int - for { - m, raw, merr := NewMapXmlReaderRaw(xmlReader) - n++ - - // handle error condition with errhandler - if merr != nil && merr != io.EOF { - merr = fmt.Errorf("[xmlReader: %d] %s", n, merr.Error()) - if ok := errHandler(merr, raw); !ok { - // caused reader termination - return merr - } - continue - } - - // pass to maphandler - if len(m) != 0 { - if ok := mapHandler(m, raw); !ok { - break - } - } else if merr != io.EOF { - <-time.After(xhandlerPollInterval) - } - - if merr == io.EOF { - break - } - } - return nil -} - -// ----------------- END: Handle XML stream by processing Map value -------------- - -// -------- a hack of io.TeeReader ... need one that's an io.ByteReader for xml.NewDecoder() ---------- - -// This is a clone of io.TeeReader with the additional method t.ReadByte(). -// Thus, this TeeReader is also an io.ByteReader. -// This is necessary because xml.NewDecoder uses a ByteReader not a Reader. It appears to have been written -// with bufio.Reader or bytes.Reader in mind ... not a generic io.Reader, which doesn't have to have ReadByte().. -// If NewDecoder is passed a Reader that does not satisfy ByteReader() it wraps the Reader with -// bufio.NewReader and uses ReadByte rather than Read that runs the TeeReader pipe logic. - -type teeReader struct { - r io.Reader - w io.Writer - b []byte -} - -func myTeeReader(r io.Reader, w io.Writer) io.Reader { - b := make([]byte, 1) - return &teeReader{r, w, b} -} - -// need for io.Reader - but we don't use it ... -func (t *teeReader) Read(p []byte) (n int, err error) { - return 0, nil -} - -func (t *teeReader) ReadByte() (c byte, err error) { - n, err := t.r.Read(t.b) - if n > 0 { - if _, err := t.w.Write(t.b[:1]); err != nil { - return t.b[0], err - } - } - return t.b[0], err -} - -// ----------------------- END: io.TeeReader hack ----------------------------------- - -// ---------------------- XmlIndent - from j2x package ---------------------------- - -// Encode a map[string]interface{} as a pretty XML string. -// See Xml for encoding rules. -func (mv Map) XmlIndent(prefix, indent string, rootTag ...string) ([]byte, error) { - m := map[string]interface{}(mv) - - var err error - s := new(string) - p := new(pretty) - p.indent = indent - p.padding = prefix - - if len(m) == 1 && len(rootTag) == 0 { - // this can extract the key for the single map element - // use it if it isn't a key for a list - for key, value := range m { - if _, ok := value.([]interface{}); ok { - err = mapToXmlIndent(true, s, DefaultRootTag, m, p) - } else { - err = mapToXmlIndent(true, s, key, value, p) - } - } - } else if len(rootTag) == 1 { - err = mapToXmlIndent(true, s, rootTag[0], m, p) - } else { - err = mapToXmlIndent(true, s, DefaultRootTag, m, p) - } - return []byte(*s), err -} - -type pretty struct { - indent string - cnt int - padding string - mapDepth int - start int -} - -func (p *pretty) Indent() { - p.padding += p.indent - p.cnt++ -} - -func (p *pretty) Outdent() { - if p.cnt > 0 { - p.padding = p.padding[:len(p.padding)-len(p.indent)] - p.cnt-- - } -} - -// where the work actually happens -// returns an error if an attribute is not atomic -func mapToXmlIndent(doIndent bool, s *string, key string, value interface{}, pp *pretty) error { - var endTag bool - var isSimple bool - p := &pretty{pp.indent, pp.cnt, pp.padding, pp.mapDepth, pp.start} - - switch value.(type) { - case map[string]interface{}, []byte, string, float64, bool, int, int32, int64, float32: - if doIndent { - *s += p.padding - } - *s += `<` + key - } - switch value.(type) { - case map[string]interface{}: - vv := value.(map[string]interface{}) - lenvv := len(vv) - // scan out attributes - keys have prepended hyphen, '-' - var cntAttr int - for k, v := range vv { - if k[:1] == "-" { - switch v.(type) { - case string, float64, bool, int, int32, int64, float32: - *s += ` ` + k[1:] + `="` + fmt.Sprintf("%v", v) + `"` - cntAttr++ - case []byte: // allow standard xml pkg []byte transform, as below - *s += ` ` + k[1:] + `="` + fmt.Sprintf("%v", string(v.([]byte))) + `"` - cntAttr++ - default: - return fmt.Errorf("invalid attribute value for: %s", k) - } - } - } - // only attributes? - if cntAttr == lenvv { - break - } - // simple element? Note: '#text" is an invalid XML tag. - if v, ok := vv["#text"]; ok { - if cntAttr+1 < lenvv { - return errors.New("#text key occurs with other non-attribute keys") - } - *s += ">" + fmt.Sprintf("%v", v) - endTag = true - break - } - // close tag with possible attributes - *s += ">" - if doIndent { - *s += "\n" - } - // something more complex - p.mapDepth++ - var i int - for k, v := range vv { - if k[:1] == "-" { - continue - } - switch v.(type) { - case []interface{}: - default: - if i == 0 && doIndent { - p.Indent() - } - } - i++ - mapToXmlIndent(doIndent, s, k, v, p) - switch v.(type) { - case []interface{}: // handled in []interface{} case - default: - if doIndent { - p.Outdent() - } - } - i-- - } - p.mapDepth-- - endTag = true - case []interface{}: - for _, v := range value.([]interface{}) { - if doIndent { - p.Indent() - } - mapToXmlIndent(doIndent, s, key, v, p) - if doIndent { - p.Outdent() - } - } - return nil - case nil: - // terminate the tag - *s += "<" + key - break - default: // handle anything - even goofy stuff - switch value.(type) { - case string, float64, bool, int, int32, int64, float32: - *s += ">" + fmt.Sprintf("%v", value) - case []byte: // NOTE: byte is just an alias for uint8 - // similar to how xml.Marshal handles []byte structure members - *s += ">" + string(value.([]byte)) - default: - var v []byte - var err error - if doIndent { - v, err = xml.MarshalIndent(value, p.padding, p.indent) - } else { - v, err = xml.Marshal(value) - } - if err != nil { - *s += ">UNKNOWN" - } else { - *s += string(v) - } - } - isSimple = true - endTag = true - } - - if endTag { - if doIndent { - if !isSimple { - // if p.mapDepth == 0 { - // p.Outdent() - // } - *s += p.padding - } - } - switch value.(type) { - case map[string]interface{}, []byte, string, float64, bool, int, int32, int64, float32: - *s += `" - } - } else if useGoXmlEmptyElemSyntax { - *s += ">" - } else { - *s += "/>" - } - if doIndent { - if p.cnt > p.start { - *s += "\n" - } - p.Outdent() - } - - return nil -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/xml_marshal/README b/Godeps/_workspace/src/github.com/clbanning/mxj/xml_marshal/README deleted file mode 100644 index ca36c45b5..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/xml_marshal/README +++ /dev/null @@ -1,26 +0,0 @@ -The mxj package terminates empty elements using '/>' rather than ''. - -The Xml(), XmlIndent(), XmlWriter() marshals Map values that can have structures or any other Go type -that xml.Marshal() can encode. If you want to have xml.Marshal() encode empty elements in a manner -consist with maputil, then you need to hack the src/pkg/encoding/xml/marshal.go file to support that -convention. - -The marshal.go.v1_2 file in this repo does that for Go v1.2; use it in place of the standard library -marshal.go file. - -The example_test.go.v1_2 file extends the package example_test.go file in the src/pkg/encoding/xml -directory to provide an example of the SetUseNullEndTag() function that you'll see in the new godoc -documentation for encoding/xml. xml.SetUseNullEndTag(true) causes xml.Marshal() to encode empty XML -elements as , just like this package. - -With the new marshal.go, you can then force all marshaling that uses encoding/xml to use mxj's -syntax rather than the Go standard syntax. - -NOTE: -If you install this patch then only use either - - - xml.SetUseNullEndTag() -or - - mxj.XmlGoEmptyElemSyntax() - -to have consistent encoding of empty XML elements. diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/xml_marshal/example_test.go.v1_2 b/Godeps/_workspace/src/github.com/clbanning/mxj/xml_marshal/example_test.go.v1_2 deleted file mode 100644 index 2e035a430..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/xml_marshal/example_test.go.v1_2 +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright 2012 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package xml_test - -import ( - "encoding/xml" - "fmt" - "os" -) - -func ExampleMarshalIndent() { - type Address struct { - City, State string - } - type Person struct { - XMLName xml.Name `xml:"person"` - Id int `xml:"id,attr"` - FirstName string `xml:"name>first"` - LastName string `xml:"name>last"` - Age int `xml:"age"` - Height float32 `xml:"height,omitempty"` - Married bool - Address - Comment string `xml:",comment"` - } - - v := &Person{Id: 13, FirstName: "John", LastName: "Doe", Age: 42} - v.Comment = " Need more details. " - v.Address = Address{"Hanga Roa", "Easter Island"} - - output, err := xml.MarshalIndent(v, " ", " ") - if err != nil { - fmt.Printf("error: %v\n", err) - } - - os.Stdout.Write(output) - // Output: - // - // - // John - // Doe - // - // 42 - // false - // Hanga Roa - // Easter Island - // - // -} - -func ExampleEncoder() { - type Address struct { - City, State string - } - type Person struct { - XMLName xml.Name `xml:"person"` - Id int `xml:"id,attr"` - FirstName string `xml:"name>first"` - LastName string `xml:"name>last"` - Age int `xml:"age"` - Height float32 `xml:"height,omitempty"` - Married bool - Address - Comment string `xml:",comment"` - } - - v := &Person{Id: 13, FirstName: "John", LastName: "Doe", Age: 42} - v.Comment = " Need more details. " - v.Address = Address{"Hanga Roa", "Easter Island"} - - enc := xml.NewEncoder(os.Stdout) - enc.Indent(" ", " ") - if err := enc.Encode(v); err != nil { - fmt.Printf("error: %v\n", err) - } - - // Output: - // - // - // John - // Doe - // - // 42 - // false - // Hanga Roa - // Easter Island - // - // -} - -// This example demonstrates unmarshaling an XML excerpt into a value with -// some preset fields. Note that the Phone field isn't modified and that -// the XML element is ignored. Also, the Groups field is assigned -// considering the element path provided in its tag. -func ExampleUnmarshal() { - type Email struct { - Where string `xml:"where,attr"` - Addr string - } - type Address struct { - City, State string - } - type Result struct { - XMLName xml.Name `xml:"Person"` - Name string `xml:"FullName"` - Phone string - Email []Email - Groups []string `xml:"Group>Value"` - Address - } - v := Result{Name: "none", Phone: "none"} - - data := ` - - Grace R. Emlin - Example Inc. - - gre@example.com - - - gre@work.com - - - Friends - Squash - - Hanga Roa - Easter Island - - ` - err := xml.Unmarshal([]byte(data), &v) - if err != nil { - fmt.Printf("error: %v", err) - return - } - fmt.Printf("XMLName: %#v\n", v.XMLName) - fmt.Printf("Name: %q\n", v.Name) - fmt.Printf("Phone: %q\n", v.Phone) - fmt.Printf("Email: %v\n", v.Email) - fmt.Printf("Groups: %v\n", v.Groups) - fmt.Printf("Address: %v\n", v.Address) - // Output: - // XMLName: xml.Name{Space:"", Local:"Person"} - // Name: "Grace R. Emlin" - // Phone: "none" - // Email: [{home gre@example.com} {work gre@work.com}] - // Groups: [Friends Squash] - // Address: {Hanga Roa Easter Island} -} - -// This example demonstrates how SetUseNullEndTag changes the end tag syntax for Marshal. -func ExampleSetUseNullEndTag() { - type NullValStruct struct { - I int - B []byte - S string - } - s := new(NullValStruct) - - v, err := xml.Marshal(s) - if err != nil { - fmt.Println("err:", err.Error()) - } else { - fmt.Println("s:", string(v)) - } - - xml.SetUseNullEndTag(true) - v, err = xml.Marshal(s) - if err != nil { - fmt.Println("err:", err.Error()) - } else { - fmt.Println("s:", string(v)) - } - - type NewStruct struct { - NVS NullValStruct - S string - F float64 - } - ss := new(NewStruct) - - v, err = xml.Marshal(ss) - if err != nil { - fmt.Println("err:", err.Error()) - } else { - fmt.Println("ss:", string(v)) - } - - v, err = xml.MarshalIndent(ss," "," ") - if err != nil { - fmt.Println("err:", err.Error()) - } else { - fmt.Println("ss indent:\n",string(v)) - } - // Output: - // s: 0 - // s: 0 - // ss: 00 - // ss indent: - // - // - // 0 - // - // - // - // - // 0 - // -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/xml_marshal/marshal.go.v1_2 b/Godeps/_workspace/src/github.com/clbanning/mxj/xml_marshal/marshal.go.v1_2 deleted file mode 100644 index b51d0c1e8..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/xml_marshal/marshal.go.v1_2 +++ /dev/null @@ -1,1034 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package xml - -import ( - "bufio" - "bytes" - "encoding" - "fmt" - "io" - "reflect" - "strconv" - "strings" -) - -const ( - // A generic XML header suitable for use with the output of Marshal. - // This is not automatically added to any output of this package, - // it is provided as a convenience. - Header = `` + "\n" -) - -// Marshal returns the XML encoding of v. -// -// Marshal handles an array or slice by marshalling each of the elements. -// Marshal handles a pointer by marshalling the value it points at or, if the -// pointer is nil, by writing nothing. Marshal handles an interface value by -// marshalling the value it contains or, if the interface value is nil, by -// writing nothing. Marshal handles all other data by writing one or more XML -// elements containing the data. -// -// The name for the XML elements is taken from, in order of preference: -// - the tag on the XMLName field, if the data is a struct -// - the value of the XMLName field of type xml.Name -// - the tag of the struct field used to obtain the data -// - the name of the struct field used to obtain the data -// - the name of the marshalled type -// -// The XML element for a struct contains marshalled elements for each of the -// exported fields of the struct, with these exceptions: -// - the XMLName field, described above, is omitted. -// - a field with tag "-" is omitted. -// - a field with tag "name,attr" becomes an attribute with -// the given name in the XML element. -// - a field with tag ",attr" becomes an attribute with the -// field name in the XML element. -// - a field with tag ",chardata" is written as character data, -// not as an XML element. -// - a field with tag ",innerxml" is written verbatim, not subject -// to the usual marshalling procedure. -// - a field with tag ",comment" is written as an XML comment, not -// subject to the usual marshalling procedure. It must not contain -// the "--" string within it. -// - a field with a tag including the "omitempty" option is omitted -// if the field value is empty. The empty values are false, 0, any -// nil pointer or interface value, and any array, slice, map, or -// string of length zero. -// - an anonymous struct field is handled as if the fields of its -// value were part of the outer struct. -// -// If a field uses a tag "a>b>c", then the element c will be nested inside -// parent elements a and b. Fields that appear next to each other that name -// the same parent will be enclosed in one XML element. -// -// See MarshalIndent for an example. -// -// Marshal will return an error if asked to marshal a channel, function, or map. -func Marshal(v interface{}) ([]byte, error) { - var b bytes.Buffer - if err := NewEncoder(&b).Encode(v); err != nil { - return nil, err - } - return b.Bytes(), nil -} - -// Marshaler is the interface implemented by objects that can marshal -// themselves into valid XML elements. -// -// MarshalXML encodes the receiver as zero or more XML elements. -// By convention, arrays or slices are typically encoded as a sequence -// of elements, one per entry. -// Using start as the element tag is not required, but doing so -// will enable Unmarshal to match the XML elements to the correct -// struct field. -// One common implementation strategy is to construct a separate -// value with a layout corresponding to the desired XML and then -// to encode it using e.EncodeElement. -// Another common strategy is to use repeated calls to e.EncodeToken -// to generate the XML output one token at a time. -// The sequence of encoded tokens must make up zero or more valid -// XML elements. -type Marshaler interface { - MarshalXML(e *Encoder, start StartElement) error -} - -// MarshalerAttr is the interface implemented by objects that can marshal -// themselves into valid XML attributes. -// -// MarshalXMLAttr returns an XML attribute with the encoded value of the receiver. -// Using name as the attribute name is not required, but doing so -// will enable Unmarshal to match the attribute to the correct -// struct field. -// If MarshalXMLAttr returns the zero attribute Attr{}, no attribute -// will be generated in the output. -// MarshalXMLAttr is used only for struct fields with the -// "attr" option in the field tag. -type MarshalerAttr interface { - MarshalXMLAttr(name Name) (Attr, error) -} - -// MarshalIndent works like Marshal, but each XML element begins on a new -// indented line that starts with prefix and is followed by one or more -// copies of indent according to the nesting depth. -func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) { - var b bytes.Buffer - enc := NewEncoder(&b) - enc.Indent(prefix, indent) - if err := enc.Encode(v); err != nil { - return nil, err - } - return b.Bytes(), nil -} - -// An Encoder writes XML data to an output stream. -type Encoder struct { - p printer -} - -// NewEncoder returns a new encoder that writes to w. -func NewEncoder(w io.Writer) *Encoder { - e := &Encoder{printer{Writer: bufio.NewWriter(w)}} - e.p.encoder = e - return e -} - -// Indent sets the encoder to generate XML in which each element -// begins on a new indented line that starts with prefix and is followed by -// one or more copies of indent according to the nesting depth. -func (enc *Encoder) Indent(prefix, indent string) { - enc.p.prefix = prefix - enc.p.indent = indent -} - -// Encode writes the XML encoding of v to the stream. -// -// See the documentation for Marshal for details about the conversion -// of Go values to XML. -// -// Encode calls Flush before returning. -func (enc *Encoder) Encode(v interface{}) error { - err := enc.p.marshalValue(reflect.ValueOf(v), nil, nil) - if err != nil { - return err - } - return enc.p.Flush() -} - -// EncodeElement writes the XML encoding of v to the stream, -// using start as the outermost tag in the encoding. -// -// See the documentation for Marshal for details about the conversion -// of Go values to XML. -// -// EncodeElement calls Flush before returning. -func (enc *Encoder) EncodeElement(v interface{}, start StartElement) error { - err := enc.p.marshalValue(reflect.ValueOf(v), nil, &start) - if err != nil { - return err - } - return enc.p.Flush() -} - -var ( - endComment = []byte("-->") - endProcInst = []byte("?>") - endDirective = []byte(">") -) - -// EncodeToken writes the given XML token to the stream. -// It returns an error if StartElement and EndElement tokens are not properly matched. -// -// EncodeToken does not call Flush, because usually it is part of a larger operation -// such as Encode or EncodeElement (or a custom Marshaler's MarshalXML invoked -// during those), and those will call Flush when finished. -// -// Callers that create an Encoder and then invoke EncodeToken directly, without -// using Encode or EncodeElement, need to call Flush when finished to ensure -// that the XML is written to the underlying writer. -func (enc *Encoder) EncodeToken(t Token) error { - p := &enc.p - switch t := t.(type) { - case StartElement: - if err := p.writeStart(&t); err != nil { - return err - } - case EndElement: - if err := p.writeEnd(t.Name); err != nil { - return err - } - case CharData: - EscapeText(p, t) - case Comment: - if bytes.Contains(t, endComment) { - return fmt.Errorf("xml: EncodeToken of Comment containing --> marker") - } - p.WriteString("") - return p.cachedWriteError() - case ProcInst: - if t.Target == "xml" || !isNameString(t.Target) { - return fmt.Errorf("xml: EncodeToken of ProcInst with invalid Target") - } - if bytes.Contains(t.Inst, endProcInst) { - return fmt.Errorf("xml: EncodeToken of ProcInst containing ?> marker") - } - p.WriteString(" 0 { - p.WriteByte(' ') - p.Write(t.Inst) - } - p.WriteString("?>") - case Directive: - if bytes.Contains(t, endDirective) { - return fmt.Errorf("xml: EncodeToken of Directive containing > marker") - } - p.WriteString("") - } - return p.cachedWriteError() -} - -// Flush flushes any buffered XML to the underlying writer. -// See the EncodeToken documentation for details about when it is necessary. -func (enc *Encoder) Flush() error { - return enc.p.Flush() -} - -type printer struct { - *bufio.Writer - encoder *Encoder - seq int - indent string - prefix string - depth int - indentedIn bool - putNewline bool - attrNS map[string]string // map prefix -> name space - attrPrefix map[string]string // map name space -> prefix - prefixes []string - tags []Name -} - -// createAttrPrefix finds the name space prefix attribute to use for the given name space, -// defining a new prefix if necessary. It returns the prefix. -func (p *printer) createAttrPrefix(url string) string { - if prefix := p.attrPrefix[url]; prefix != "" { - return prefix - } - - // The "http://www.w3.org/XML/1998/namespace" name space is predefined as "xml" - // and must be referred to that way. - // (The "http://www.w3.org/2000/xmlns/" name space is also predefined as "xmlns", - // but users should not be trying to use that one directly - that's our job.) - if url == xmlURL { - return "xml" - } - - // Need to define a new name space. - if p.attrPrefix == nil { - p.attrPrefix = make(map[string]string) - p.attrNS = make(map[string]string) - } - - // Pick a name. We try to use the final element of the path - // but fall back to _. - prefix := strings.TrimRight(url, "/") - if i := strings.LastIndex(prefix, "/"); i >= 0 { - prefix = prefix[i+1:] - } - if prefix == "" || !isName([]byte(prefix)) || strings.Contains(prefix, ":") { - prefix = "_" - } - if strings.HasPrefix(prefix, "xml") { - // xmlanything is reserved. - prefix = "_" + prefix - } - if p.attrNS[prefix] != "" { - // Name is taken. Find a better one. - for p.seq++; ; p.seq++ { - if id := prefix + "_" + strconv.Itoa(p.seq); p.attrNS[id] == "" { - prefix = id - break - } - } - } - - p.attrPrefix[url] = prefix - p.attrNS[prefix] = url - - p.WriteString(`xmlns:`) - p.WriteString(prefix) - p.WriteString(`="`) - EscapeText(p, []byte(url)) - p.WriteString(`" `) - - p.prefixes = append(p.prefixes, prefix) - - return prefix -} - -// deleteAttrPrefix removes an attribute name space prefix. -func (p *printer) deleteAttrPrefix(prefix string) { - delete(p.attrPrefix, p.attrNS[prefix]) - delete(p.attrNS, prefix) -} - -func (p *printer) markPrefix() { - p.prefixes = append(p.prefixes, "") -} - -func (p *printer) popPrefix() { - for len(p.prefixes) > 0 { - prefix := p.prefixes[len(p.prefixes)-1] - p.prefixes = p.prefixes[:len(p.prefixes)-1] - if prefix == "" { - break - } - p.deleteAttrPrefix(prefix) - } -} - -var ( - marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem() - marshalerAttrType = reflect.TypeOf((*MarshalerAttr)(nil)).Elem() - textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem() -) - -// CLB, 11/30/13 -var useNullEndTag bool - -// SetUseNullEndTag - 'true': have Marshal/MarshalIndent use in place of for empty element. -func SetUseNullEndTag(b bool) { - useNullEndTag = b -} - -// marshalValue writes one or more XML elements representing val. -// If val was obtained from a struct field, finfo must have its details. -func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplate *StartElement) error { - if startTemplate != nil && startTemplate.Name.Local == "" { - return fmt.Errorf("xml: EncodeElement of StartElement with missing name") - } - - if !val.IsValid() { - return nil - } - if finfo != nil && finfo.flags&fOmitEmpty != 0 && isEmptyValue(val) { - return nil - } - - // Drill into interfaces and pointers. - // This can turn into an infinite loop given a cyclic chain, - // but it matches the Go 1 behavior. - for val.Kind() == reflect.Interface || val.Kind() == reflect.Ptr { - if val.IsNil() { - return nil - } - val = val.Elem() - } - - kind := val.Kind() - typ := val.Type() - - // Check for marshaler. - if val.CanInterface() && typ.Implements(marshalerType) { - return p.marshalInterface(val.Interface().(Marshaler), defaultStart(typ, finfo, startTemplate)) - } - if val.CanAddr() { - pv := val.Addr() - if pv.CanInterface() && pv.Type().Implements(marshalerType) { - return p.marshalInterface(pv.Interface().(Marshaler), defaultStart(pv.Type(), finfo, startTemplate)) - } - } - - // Check for text marshaler. - if val.CanInterface() && typ.Implements(textMarshalerType) { - return p.marshalTextInterface(val.Interface().(encoding.TextMarshaler), defaultStart(typ, finfo, startTemplate)) - } - if val.CanAddr() { - pv := val.Addr() - if pv.CanInterface() && pv.Type().Implements(textMarshalerType) { - return p.marshalTextInterface(pv.Interface().(encoding.TextMarshaler), defaultStart(pv.Type(), finfo, startTemplate)) - } - } - - // Slices and arrays iterate over the elements. They do not have an enclosing tag. - if (kind == reflect.Slice || kind == reflect.Array) && typ.Elem().Kind() != reflect.Uint8 { - for i, n := 0, val.Len(); i < n; i++ { - if err := p.marshalValue(val.Index(i), finfo, startTemplate); err != nil { - return err - } - } - return nil - } - - tinfo, err := getTypeInfo(typ) - if err != nil { - return err - } - - // Create start element. - // Precedence for the XML element name is: - // 0. startTemplate - // 1. XMLName field in underlying struct; - // 2. field name/tag in the struct field; and - // 3. type name - var start StartElement - - if startTemplate != nil { - start.Name = startTemplate.Name - start.Attr = append(start.Attr, startTemplate.Attr...) - } else if tinfo.xmlname != nil { - xmlname := tinfo.xmlname - if xmlname.name != "" { - start.Name.Space, start.Name.Local = xmlname.xmlns, xmlname.name - } else if v, ok := xmlname.value(val).Interface().(Name); ok && v.Local != "" { - start.Name = v - } - } - if start.Name.Local == "" && finfo != nil { - start.Name.Space, start.Name.Local = finfo.xmlns, finfo.name - } - if start.Name.Local == "" { - name := typ.Name() - if name == "" { - return &UnsupportedTypeError{typ} - } - start.Name.Local = name - } - - // Attributes - for i := range tinfo.fields { - finfo := &tinfo.fields[i] - if finfo.flags&fAttr == 0 { - continue - } - fv := finfo.value(val) - name := Name{Space: finfo.xmlns, Local: finfo.name} - - if finfo.flags&fOmitEmpty != 0 && isEmptyValue(fv) { - continue - } - - if fv.Kind() == reflect.Interface && fv.IsNil() { - continue - } - - if fv.CanInterface() && fv.Type().Implements(marshalerAttrType) { - attr, err := fv.Interface().(MarshalerAttr).MarshalXMLAttr(name) - if err != nil { - return err - } - if attr.Name.Local != "" { - start.Attr = append(start.Attr, attr) - } - continue - } - - if fv.CanAddr() { - pv := fv.Addr() - if pv.CanInterface() && pv.Type().Implements(marshalerAttrType) { - attr, err := pv.Interface().(MarshalerAttr).MarshalXMLAttr(name) - if err != nil { - return err - } - if attr.Name.Local != "" { - start.Attr = append(start.Attr, attr) - } - continue - } - } - - if fv.CanInterface() && fv.Type().Implements(textMarshalerType) { - text, err := fv.Interface().(encoding.TextMarshaler).MarshalText() - if err != nil { - return err - } - start.Attr = append(start.Attr, Attr{name, string(text)}) - continue - } - - if fv.CanAddr() { - pv := fv.Addr() - if pv.CanInterface() && pv.Type().Implements(textMarshalerType) { - text, err := pv.Interface().(encoding.TextMarshaler).MarshalText() - if err != nil { - return err - } - start.Attr = append(start.Attr, Attr{name, string(text)}) - continue - } - } - - // Dereference or skip nil pointer, interface values. - switch fv.Kind() { - case reflect.Ptr, reflect.Interface: - if fv.IsNil() { - continue - } - fv = fv.Elem() - } - - s, b, err := p.marshalSimple(fv.Type(), fv) - if err != nil { - return err - } - if b != nil { - s = string(b) - } - start.Attr = append(start.Attr, Attr{name, s}) - } - -/* CLB, 11/30/13 - if err := p.writeStart(&start); err != nil { - return err - } -*/ - - // CLB, 11/30/13 - var noVal bool - - if val.Kind() == reflect.Struct { - if err := p.writeStart(&start); err != nil { - return err - } - err = p.marshalStruct(tinfo, val) - } else { - s, b, err1 := p.marshalSimple(typ, val) - // CLB, 11/30/13 - if s == "" && len(b) == 0 && useNullEndTag { - if err := p.writeStartDone(&start); err != nil { - return err - } - noVal = true - goto finishProc - } - if err := p.writeStart(&start); err != nil { - return err - } - if err1 != nil { - err = err1 - } else if b != nil { - EscapeText(p, b) - } else { - p.EscapeString(s) - } - } - if err != nil { - return err - } - -// CLB, 11/30/13 -finishProc: - - if noVal && useNullEndTag { - if err := p.writeEndDone(start.Name); err != nil { - return err - } - } else if err := p.writeEnd(start.Name); err != nil { - return err - } - - return p.cachedWriteError() -} - -// defaultStart returns the default start element to use, -// given the reflect type, field info, and start template. -func defaultStart(typ reflect.Type, finfo *fieldInfo, startTemplate *StartElement) StartElement { - var start StartElement - // Precedence for the XML element name is as above, - // except that we do not look inside structs for the first field. - if startTemplate != nil { - start.Name = startTemplate.Name - start.Attr = append(start.Attr, startTemplate.Attr...) - } else if finfo != nil && finfo.name != "" { - start.Name.Local = finfo.name - start.Name.Space = finfo.xmlns - } else if typ.Name() != "" { - start.Name.Local = typ.Name() - } else { - // Must be a pointer to a named type, - // since it has the Marshaler methods. - start.Name.Local = typ.Elem().Name() - } - return start -} - -// marshalInterface marshals a Marshaler interface value. -func (p *printer) marshalInterface(val Marshaler, start StartElement) error { - // Push a marker onto the tag stack so that MarshalXML - // cannot close the XML tags that it did not open. - p.tags = append(p.tags, Name{}) - n := len(p.tags) - - err := val.MarshalXML(p.encoder, start) - if err != nil { - return err - } - - // Make sure MarshalXML closed all its tags. p.tags[n-1] is the mark. - if len(p.tags) > n { - return fmt.Errorf("xml: %s.MarshalXML wrote invalid XML: <%s> not closed", receiverType(val), p.tags[len(p.tags)-1].Local) - } - p.tags = p.tags[:n-1] - return nil -} - -// marshalTextInterface marshals a TextMarshaler interface value. -func (p *printer) marshalTextInterface(val encoding.TextMarshaler, start StartElement) error { - if err := p.writeStart(&start); err != nil { - return err - } - text, err := val.MarshalText() - if err != nil { - return err - } - EscapeText(p, text) - return p.writeEnd(start.Name) -} - -// writeStart writes the given start element. -func (p *printer) writeStart(start *StartElement) error { - if start.Name.Local == "" { - return fmt.Errorf("xml: start tag with no name") - } - - p.tags = append(p.tags, start.Name) - p.markPrefix() - - p.writeIndent(1) - p.WriteByte('<') - p.WriteString(start.Name.Local) - - if start.Name.Space != "" { - p.WriteString(` xmlns="`) - p.EscapeString(start.Name.Space) - p.WriteByte('"') - } - - // Attributes - for _, attr := range start.Attr { - name := attr.Name - if name.Local == "" { - continue - } - p.WriteByte(' ') - if name.Space != "" { - p.WriteString(p.createAttrPrefix(name.Space)) - p.WriteByte(':') - } - p.WriteString(name.Local) - p.WriteString(`="`) - p.EscapeString(attr.Value) - p.WriteByte('"') - } - p.WriteByte('>') - return nil -} - -// CLB, 11/30/13 - -// writeStartDone writes the given start element. -func (p *printer) writeStartDone(start *StartElement) error { - if start.Name.Local == "" { - return fmt.Errorf("xml: start tag with no name") - } - - p.tags = append(p.tags, start.Name) - p.markPrefix() - - p.writeIndent(1) - p.WriteByte('<') - p.WriteString(start.Name.Local) - - if start.Name.Space != "" { - p.WriteString(` xmlns="`) - p.EscapeString(start.Name.Space) - p.WriteByte('"') - } - - // Attributes - for _, attr := range start.Attr { - name := attr.Name - if name.Local == "" { - continue - } - p.WriteByte(' ') - if name.Space != "" { - p.WriteString(p.createAttrPrefix(name.Space)) - p.WriteByte(':') - } - p.WriteString(name.Local) - p.WriteString(`="`) - p.EscapeString(attr.Value) - p.WriteByte('"') - } - // CLB, 11/30/13 - p.WriteString(`/>`) - return nil -} - -func (p *printer) writeEnd(name Name) error { - if name.Local == "" { - return fmt.Errorf("xml: end tag with no name") - } - if len(p.tags) == 0 || p.tags[len(p.tags)-1].Local == "" { - return fmt.Errorf("xml: end tag without start tag", name.Local) - } - if top := p.tags[len(p.tags)-1]; top != name { - if top.Local != name.Local { - return fmt.Errorf("xml: end tag does not match start tag <%s>", name.Local, top.Local) - } - return fmt.Errorf("xml: end tag in namespace %s does not match start tag <%s> in namespace %s", name.Local, name.Space, top.Local, top.Space) - } - p.tags = p.tags[:len(p.tags)-1] - - p.writeIndent(-1) - p.WriteByte('<') - p.WriteByte('/') - p.WriteString(name.Local) - p.WriteByte('>') - p.popPrefix() - return nil -} - -// CLB, 11/30/13 -func (p *printer) writeEndDone(name Name) error { - if name.Local == "" { - return fmt.Errorf("xml: end tag with no name") - } - if len(p.tags) == 0 || p.tags[len(p.tags)-1].Local == "" { - return fmt.Errorf("xml: end tag without start tag", name.Local) - } - if top := p.tags[len(p.tags)-1]; top != name { - if top.Local != name.Local { - return fmt.Errorf("xml: end tag does not match start tag <%s>", name.Local, top.Local) - } - return fmt.Errorf("xml: end tag in namespace %s does not match start tag <%s> in namespace %s", name.Local, name.Space, top.Local, top.Space) - } - p.tags = p.tags[:len(p.tags)-1] - -// CLB, 11/30/13 - p.writeIndent(-1) -/* - p.WriteByte('<') - p.WriteByte('/') - p.WriteString(name.Local) - p.WriteByte('>') -*/ - p.popPrefix() - return nil -} - -func (p *printer) marshalSimple(typ reflect.Type, val reflect.Value) (string, []byte, error) { - switch val.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return strconv.FormatInt(val.Int(), 10), nil, nil - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return strconv.FormatUint(val.Uint(), 10), nil, nil - case reflect.Float32, reflect.Float64: - return strconv.FormatFloat(val.Float(), 'g', -1, val.Type().Bits()), nil, nil - case reflect.String: - return val.String(), nil, nil - case reflect.Bool: - return strconv.FormatBool(val.Bool()), nil, nil - case reflect.Array: - if typ.Elem().Kind() != reflect.Uint8 { - break - } - // [...]byte - var bytes []byte - if val.CanAddr() { - bytes = val.Slice(0, val.Len()).Bytes() - } else { - bytes = make([]byte, val.Len()) - reflect.Copy(reflect.ValueOf(bytes), val) - } - return "", bytes, nil - case reflect.Slice: - if typ.Elem().Kind() != reflect.Uint8 { - break - } - // []byte - return "", val.Bytes(), nil - } - return "", nil, &UnsupportedTypeError{typ} -} - -var ddBytes = []byte("--") - -func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error { - s := parentStack{p: p} - for i := range tinfo.fields { - finfo := &tinfo.fields[i] - if finfo.flags&fAttr != 0 { - continue - } - vf := finfo.value(val) - - // Dereference or skip nil pointer, interface values. - switch vf.Kind() { - case reflect.Ptr, reflect.Interface: - if !vf.IsNil() { - vf = vf.Elem() - } - } - - switch finfo.flags & fMode { - case fCharData: - if vf.CanInterface() && vf.Type().Implements(textMarshalerType) { - data, err := vf.Interface().(encoding.TextMarshaler).MarshalText() - if err != nil { - return err - } - Escape(p, data) - continue - } - if vf.CanAddr() { - pv := vf.Addr() - if pv.CanInterface() && pv.Type().Implements(textMarshalerType) { - data, err := pv.Interface().(encoding.TextMarshaler).MarshalText() - if err != nil { - return err - } - Escape(p, data) - continue - } - } - var scratch [64]byte - switch vf.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - Escape(p, strconv.AppendInt(scratch[:0], vf.Int(), 10)) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - Escape(p, strconv.AppendUint(scratch[:0], vf.Uint(), 10)) - case reflect.Float32, reflect.Float64: - Escape(p, strconv.AppendFloat(scratch[:0], vf.Float(), 'g', -1, vf.Type().Bits())) - case reflect.Bool: - Escape(p, strconv.AppendBool(scratch[:0], vf.Bool())) - case reflect.String: - if err := EscapeText(p, []byte(vf.String())); err != nil { - return err - } - case reflect.Slice: - if elem, ok := vf.Interface().([]byte); ok { - if err := EscapeText(p, elem); err != nil { - return err - } - } - } - continue - - case fComment: - k := vf.Kind() - if !(k == reflect.String || k == reflect.Slice && vf.Type().Elem().Kind() == reflect.Uint8) { - return fmt.Errorf("xml: bad type for comment field of %s", val.Type()) - } - if vf.Len() == 0 { - continue - } - p.writeIndent(0) - p.WriteString("" is invalid grammar. Make it "- -->" - p.WriteByte(' ') - } - p.WriteString("-->") - continue - - case fInnerXml: - iface := vf.Interface() - switch raw := iface.(type) { - case []byte: - p.Write(raw) - continue - case string: - p.WriteString(raw) - continue - } - - case fElement, fElement | fAny: - if err := s.trim(finfo.parents); err != nil { - return err - } - if len(finfo.parents) > len(s.stack) { - if vf.Kind() != reflect.Ptr && vf.Kind() != reflect.Interface || !vf.IsNil() { - if err := s.push(finfo.parents[len(s.stack):]); err != nil { - return err - } - } - } - } - if err := p.marshalValue(vf, finfo, nil); err != nil { - return err - } - } - s.trim(nil) - return p.cachedWriteError() -} - -// return the bufio Writer's cached write error -func (p *printer) cachedWriteError() error { - _, err := p.Write(nil) - return err -} - -func (p *printer) writeIndent(depthDelta int) { - if len(p.prefix) == 0 && len(p.indent) == 0 { - return - } - if depthDelta < 0 { - p.depth-- - if p.indentedIn { - p.indentedIn = false - return - } - p.indentedIn = false - } - if p.putNewline { - p.WriteByte('\n') - } else { - p.putNewline = true - } - if len(p.prefix) > 0 { - p.WriteString(p.prefix) - } - if len(p.indent) > 0 { - for i := 0; i < p.depth; i++ { - p.WriteString(p.indent) - } - } - if depthDelta > 0 { - p.depth++ - p.indentedIn = true - } -} - -type parentStack struct { - p *printer - stack []string -} - -// trim updates the XML context to match the longest common prefix of the stack -// and the given parents. A closing tag will be written for every parent -// popped. Passing a zero slice or nil will close all the elements. -func (s *parentStack) trim(parents []string) error { - split := 0 - for ; split < len(parents) && split < len(s.stack); split++ { - if parents[split] != s.stack[split] { - break - } - } - for i := len(s.stack) - 1; i >= split; i-- { - if err := s.p.writeEnd(Name{Local: s.stack[i]}); err != nil { - return err - } - } - s.stack = parents[:split] - return nil -} - -// push adds parent elements to the stack and writes open tags. -func (s *parentStack) push(parents []string) error { - for i := 0; i < len(parents); i++ { - if err := s.p.writeStart(&StartElement{Name: Name{Local: parents[i]}}); err != nil { - return err - } - } - s.stack = append(s.stack, parents...) - return nil -} - -// A MarshalXMLError is returned when Marshal encounters a type -// that cannot be converted into XML. -type UnsupportedTypeError struct { - Type reflect.Type -} - -func (e *UnsupportedTypeError) Error() string { - return "xml: unsupported type: " + e.Type.String() -} - -func isEmptyValue(v reflect.Value) bool { - switch v.Kind() { - case reflect.Array, reflect.Map, reflect.Slice, reflect.String: - return v.Len() == 0 - case reflect.Bool: - return !v.Bool() - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return v.Int() == 0 - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return v.Uint() == 0 - case reflect.Float32, reflect.Float64: - return v.Float() == 0 - case reflect.Interface, reflect.Ptr: - return v.IsNil() - } - return false -} diff --git a/Godeps/_workspace/src/github.com/clbanning/mxj/xml_test.go b/Godeps/_workspace/src/github.com/clbanning/mxj/xml_test.go deleted file mode 100644 index 955923df7..000000000 --- a/Godeps/_workspace/src/github.com/clbanning/mxj/xml_test.go +++ /dev/null @@ -1,207 +0,0 @@ -package mxj - -import ( - "bytes" - "fmt" - "io" - "testing" -) - -func TestXmlHeader(t *testing.T) { - fmt.Println("\n---------------- xml_test.go ...\n") -} - -func TestNewMapXml(t *testing.T) { - x := []byte(`something more12`) - - mv, merr := NewMapXml(x) - if merr != nil { - t.Fatal("merr:", merr.Error()) - } - - fmt.Println("NewMapXml, x :", string(x)) - fmt.Println("NewMapXml, mv:", mv) -} - -func TestAttrHyphenFalse(t *testing.T) { - PrependAttrWithHyphen(false) - x := []byte(`something more12`) - - mv, merr := NewMapXml(x) - if merr != nil { - t.Fatal("merr:", merr.Error()) - } - - fmt.Println("AttrHyphenFalse, x :", string(x)) - fmt.Println("AttrHyphenFalse, mv:", mv) - PrependAttrWithHyphen(true) -} - -func TestNewMapXmlError(t *testing.T) { - x := []byte(`something more12`) - - m, merr := NewMapJson(x) - if merr == nil { - t.Fatal("NewMapXmlError, m:", m) - } - - fmt.Println("NewMapXmlError, x :", string(x)) - fmt.Println("NewMapXmlError, merr:", merr.Error()) - - x = []byte(`something more12`) - m, merr = NewMapJson(x) - if merr == nil { - t.Fatal("NewMapXmlError, m:", m) - } - - fmt.Println("NewMapXmlError, x :", string(x)) - fmt.Println("NewMapXmlError, merr:", merr.Error()) -} - -func TestNewMapXmlReader(t *testing.T) { - x := []byte(`is a testsomething more12`) - - r := bytes.NewReader(x) - - for { - m, raw, err := NewMapXmlReaderRaw(r) - if err != nil && err != io.EOF { - t.Fatal("err:", err.Error()) - } - if err == io.EOF && len(m) == 0 { - break - } - fmt.Println("NewMapXmlReader, raw:", string(raw)) - fmt.Println("NewMapXmlReader, m :", m) - } -} - -// --------------------- Xml() and XmlWriter() test cases ------------------- - -func TestXml_1(t *testing.T) { - mv := Map{"tag1": "some data", "tag2": "more data", "boolean": true, "float": 3.14159625, "null": nil} - - x, err := mv.Xml() - if err != nil { - t.Fatal("err:", err.Error()) - } - - fmt.Println("Xml_1, mv:", mv) - fmt.Println("Xml_1, x :", string(x)) -} - -func TestXml_2(t *testing.T) { - a := []interface{}{"string", true, 36.4} - mv := Map{"array": a} - - x, err := mv.Xml() - if err != nil { - t.Fatal("err:", err.Error()) - } - - fmt.Println("Xml_2, mv:", mv) - fmt.Println("Xml_2, x :", string(x)) -} - -func TestXml_3(t *testing.T) { - a := []interface{}{"string", true, 36.4} - mv := Map{"array": []interface{}{a, "string2"}} - - x, err := mv.Xml() - if err != nil { - t.Fatal("err:", err.Error()) - } - - fmt.Println("Xml_3, mv:", mv) - fmt.Println("Xml_3, x :", string(x)) -} - -func TestXml_4(t *testing.T) { - a := []interface{}{"string", true, 36.4} - mv := Map{"array": map[string]interface{}{"innerkey": []interface{}{a, "string2"}}} - - x, err := mv.Xml() - if err != nil { - t.Fatal("err:", err.Error()) - } - - fmt.Println("Xml_4, mv:", mv) - fmt.Println("Xml_4, x :", string(x)) -} - -func TestXml_5(t *testing.T) { - a := []interface{}{"string", true, 36.4} - mv := Map{"array": []interface{}{map[string]interface{}{"innerkey": []interface{}{a, "string2"}}, map[string]interface{}{"some": "more"}}} - - x, err := mv.Xml() - if err != nil { - t.Fatal("err:", err.Error()) - } - - fmt.Println("Xml_5, mv:", mv) - fmt.Println("Xml_5, x :", string(x)) -} - -func TestXmlWriter(t *testing.T) { - mv := Map{"tag1": "some data", "tag2": "more data", "boolean": true, "float": 3.14159625} - w := new(bytes.Buffer) - - raw, err := mv.XmlWriterRaw(w, "myRootTag") - if err != nil { - t.Fatal("err:", err.Error()) - } - - b := make([]byte, w.Len()) - _, err = w.Read(b) - if err != nil { - t.Fatal("err:", err.Error()) - } - - fmt.Println("XmlWriter, raw:", string(raw)) - fmt.Println("XmlWriter, b :", string(b)) -} - -// -------------------------- XML Handler test cases ------------------------- - -/* tested in bulk_test.go ... -var xhdata = []byte(`is a testsomething more12`) - -func TestHandleXmlReader(t *testing.T) { - fmt.Println("HandleXmlReader:", string(xhdata)) - - rdr := bytes.NewReader(xhdata) - err := HandleXmlReader(rdr, xmhandler, xehandler) - if err != nil { - t.Fatal("err:", err.Error()) - } -} - -var xt *testing.T - -func xmhandler(m Map, raw []byte) bool { - x, xerr := m.Xml() - if xerr != nil { - xt.Fatal("... xmhandler:", xerr.Error()) - return false - } - - fmt.Println("... xmhandler, raw:", string(raw)) - fmt.Println("... xmhandler, x :", string(x)) - return true -} - -func xehandler(err error, raw []byte) bool { - if err == nil { - // shouldn't be here - xt.Fatal("... xehandler: ") - return false - } - if err == io.EOF { - return true - } - - fmt.Println("... xehandler raw:", string(raw)) - fmt.Println("... xehandler err:", err.Error()) - return true -} -*/ diff --git a/Godeps/_workspace/src/github.com/fatih/structs/.travis.yml b/Godeps/_workspace/src/github.com/fatih/structs/.travis.yml deleted file mode 100644 index 28381ef8e..000000000 --- a/Godeps/_workspace/src/github.com/fatih/structs/.travis.yml +++ /dev/null @@ -1,11 +0,0 @@ -language: go -go: 1.3 -before_install: -- go get github.com/axw/gocov/gocov -- go get github.com/mattn/goveralls -- go get code.google.com/p/go.tools/cmd/cover -script: -- $HOME/gopath/bin/goveralls -repotoken $COVERALLS_TOKEN -env: - global: - - secure: hkc+92KPmMFqIH9n4yWdnH1JpZjahmOyDJwpTh8Yl0JieJNG0XEXpOqNao27eA0cLF+UHdyjFeGcPUJKNmgE46AoQjtovt+ICjCXKR2yF6S2kKJcUOz/Vd6boZF7qHV06jjxyxOebpID5iSoW6UfFr001bFxpd3jaSLFTzSHWRQ= diff --git a/Godeps/_workspace/src/github.com/fatih/structs/README.md b/Godeps/_workspace/src/github.com/fatih/structs/README.md deleted file mode 100644 index 87fccf24a..000000000 --- a/Godeps/_workspace/src/github.com/fatih/structs/README.md +++ /dev/null @@ -1,159 +0,0 @@ -# Structs [![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](http://godoc.org/github.com/fatih/structs) [![Build Status](http://img.shields.io/travis/fatih/structs.svg?style=flat-square)](https://travis-ci.org/fatih/structs) [![Coverage Status](http://img.shields.io/coveralls/fatih/structs.svg?style=flat-square)](https://coveralls.io/r/fatih/structs) - -Structs contains various utilities to work with Go (Golang) structs. It was -initially used by me to convert a struct into a `map[string]interface{}`. With -time I've added other utilities for structs. It's basically a high level -package based on primitives from the reflect package. Feel free to add new -functions or improve the existing code. - -## Install - -```bash -go get github.com/fatih/structs -``` - -## Usage and Examples - -Just like the standard lib `strings`, `bytes` and co packages, `structs` has -many global functions to manipulate or organize your struct data. Lets define -and declare a struct: - -```go -type Server struct { - Name string `json:"name,omitempty"` - ID int - Enabled bool - users []string // not exported - http.Server // embedded -} - -server := &Server{ - Name: "gopher", - ID: 123456, - Enabled: true, -} -``` - -```go -// Convert a struct to a map[string]interface{} -// => {"Name":"gopher", "ID":123456, "Enabled":true} -m := structs.Map(server) - -// Convert the values of a struct to a []interface{} -// => ["gopher", 123456, true] -v := structs.Values(server) - -// Convert the values of a struct to a []*Field -// (see "Field methods" for more info about fields) -f := structs.Fields(server) - -// Return the struct name => "Server" -n := structs.Name(server) - -// Check if any field of a struct is initialized or not. -h := structs.HasZero(server) - -// Check if all fields of a struct is initialized or not. -z := structs.IsZero(server) - -// Check if server is a struct or a pointer to struct -i := structs.IsStruct(server) -``` - -### Struct methods - -The structs functions can be also used as independent methods by creating a new -`*structs.Struct`. This is handy if you want to have more control over the -structs (such as retrieving a single Field). - -```go -// Create a new struct type: -s := structs.New(server) - -m := s.Map() // Get a map[string]interface{} -v := s.Values() // Get a []interface{} -f := s.Fields() // Get a []*Field -f := s.Field(name) // Get a *Field based on the given field name -f, ok := s.FieldsOk(name) // Get a *Field based on the given field name -n := s.Name() // Get the struct name -h := s.HasZero() // Check if any field is initialized -z := s.IsZero() // Check if all fields are initialized -``` - -### Field methods - -We can easily examine a single Field for more detail. Below you can see how we -get and interact with various field methods: - - -```go -s := structs.New(server) - -// Get the Field struct for the "Name" field -name := s.Field("Name") - -// Get the underlying value, value => "gopher" -value := name.Value().(string) - -// Set the field's value -name.Set("another gopher") - -// Get the field's kind, kind => "string" -name.Kind() - -// Check if the field is exported or not -if name.IsExported() { - fmt.Println("Name field is exported") -} - -// Check if the value is a zero value, such as "" for string, 0 for int -if !name.IsZero() { - fmt.Println("Name is initialized") -} - -// Check if the field is an anonymous (embedded) field -if !name.IsEmbedded() { - fmt.Println("Name is not an embedded field") -} - -// Get the Field's tag value for tag name "json", tag value => "name,omitempty" -tagValue := name.Tag("json") -``` - -Nested structs are supported too: - -```go -addrField := s.Field("Server").Field("Addr") - -// Get the value for addr -a := addrField.Value().(string) - -// Or get all fields -httpServer := s.Field("Server").Fields() -``` - -We can also get a slice of Fields from the Struct type to iterate over all -fields. This is handy if you wish to examine all fields: - -```go -// Convert the fields of a struct to a []*Field -fields := s.Fields() - -for _, f := range fields { - fmt.Printf("field name: %+v\n", f.Name()) - - if f.IsExported() { - fmt.Printf("value : %+v\n", f.Value()) - fmt.Printf("is zero : %+v\n", f.IsZero()) - } -} -``` - -## Credits - - * [Fatih Arslan](https://github.com/fatih) - * [Cihangir Savas](https://github.com/cihangir) - -## License - -The MIT License (MIT) - see LICENSE.md for more details diff --git a/Godeps/_workspace/src/github.com/fatih/structs/field.go b/Godeps/_workspace/src/github.com/fatih/structs/field.go deleted file mode 100644 index 4b5e15b06..000000000 --- a/Godeps/_workspace/src/github.com/fatih/structs/field.go +++ /dev/null @@ -1,126 +0,0 @@ -package structs - -import ( - "errors" - "fmt" - "reflect" -) - -var ( - errNotExported = errors.New("field is not exported") - errNotSettable = errors.New("field is not settable") -) - -// Field represents a single struct field that encapsulates high level -// functions around the field. -type Field struct { - value reflect.Value - field reflect.StructField - defaultTag string -} - -// Tag returns the value associated with key in the tag string. If there is no -// such key in the tag, Tag returns the empty string. -func (f *Field) Tag(key string) string { - return f.field.Tag.Get(key) -} - -// Value returns the underlying value of of the field. It panics if the field -// is not exported. -func (f *Field) Value() interface{} { - return f.value.Interface() -} - -// IsEmbedded returns true if the given field is an anonymous field (embedded) -func (f *Field) IsEmbedded() bool { - return f.field.Anonymous -} - -// IsExported returns true if the given field is exported. -func (f *Field) IsExported() bool { - return f.field.PkgPath == "" -} - -// IsZero returns true if the given field is not initalized (has a zero value). -// It panics if the field is not exported. -func (f *Field) IsZero() bool { - zero := reflect.Zero(f.value.Type()).Interface() - current := f.Value() - - return reflect.DeepEqual(current, zero) -} - -// Name returns the name of the given field -func (f *Field) Name() string { - return f.field.Name -} - -// Kind returns the fields kind, such as "string", "map", "bool", etc .. -func (f *Field) Kind() reflect.Kind { - return f.value.Kind() -} - -// Set sets the field to given value v. It retuns an error if the field is not -// settable (not addresable or not exported) or if the given value's type -// doesn't match the fields type. -func (f *Field) Set(val interface{}) error { - // we can't set unexported fields, so be sure this field is exported - if !f.IsExported() { - return errNotExported - } - - // do we get here? not sure... - if !f.value.CanSet() { - return errNotSettable - } - - given := reflect.ValueOf(val) - - if f.value.Kind() != given.Kind() { - return fmt.Errorf("wrong kind. got: %s want: %s", given.Kind(), f.value.Kind()) - } - - f.value.Set(given) - return nil -} - -// Fields returns a slice of Fields. This is particular handy to get the fields -// of a nested struct . A struct tag with the content of "-" ignores the -// checking of that particular field. Example: -// -// // Field is ignored by this package. -// Field *http.Request `structs:"-"` -// -// It panics if field is not exported or if field's kind is not struct -func (f *Field) Fields() []*Field { - return getFields(f.value, f.defaultTag) -} - -// Field returns the field from a nested struct. It panics if the nested struct -// is not exported or if the field was not found. -func (f *Field) Field(name string) *Field { - field, ok := f.FieldOk(name) - if !ok { - panic("field not found") - } - - return field -} - -// Field returns the field from a nested struct. The boolean returns true if -// the field was found. It panics if the nested struct is not exported or if -// the field was not found. -func (f *Field) FieldOk(name string) (*Field, bool) { - v := strctVal(f.value.Interface()) - t := v.Type() - - field, ok := t.FieldByName(name) - if !ok { - return nil, false - } - - return &Field{ - field: field, - value: v.FieldByName(name), - }, true -} diff --git a/Godeps/_workspace/src/github.com/fatih/structs/field_test.go b/Godeps/_workspace/src/github.com/fatih/structs/field_test.go deleted file mode 100644 index 46187d655..000000000 --- a/Godeps/_workspace/src/github.com/fatih/structs/field_test.go +++ /dev/null @@ -1,324 +0,0 @@ -package structs - -import ( - "reflect" - "testing" -) - -// A test struct that defines all cases -type Foo struct { - A string - B int `structs:"y"` - C bool `json:"c"` - d string // not exported - E *Baz - x string `xml:"x"` // not exported, with tag - Y []string - Z map[string]interface{} - *Bar // embedded -} - -type Baz struct { - A string - B int -} - -type Bar struct { - E string - F int - g []string -} - -func newStruct() *Struct { - b := &Bar{ - E: "example", - F: 2, - g: []string{"zeynep", "fatih"}, - } - - // B and x is not initialized for testing - f := &Foo{ - A: "gopher", - C: true, - d: "small", - E: nil, - Y: []string{"example"}, - Z: nil, - } - f.Bar = b - - return New(f) -} - -func TestField_Set(t *testing.T) { - s := newStruct() - - f := s.Field("A") - err := f.Set("fatih") - if err != nil { - t.Error(err) - } - - if f.Value().(string) != "fatih" { - t.Errorf("Setted value is wrong: %s want: %s", f.Value().(string), "fatih") - } - - f = s.Field("Y") - err = f.Set([]string{"override", "with", "this"}) - if err != nil { - t.Error(err) - } - - sliceLen := len(f.Value().([]string)) - if sliceLen != 3 { - t.Errorf("Setted values slice length is wrong: %d, want: %d", sliceLen, 3) - } - - f = s.Field("C") - err = f.Set(false) - if err != nil { - t.Error(err) - } - - if f.Value().(bool) { - t.Errorf("Setted value is wrong: %s want: %s", f.Value().(bool), false) - } - - // let's pass a different type - f = s.Field("A") - err = f.Set(123) // Field A is of type string, but we are going to pass an integer - if err == nil { - t.Error("Setting a field's value with a different type than the field's type should return an error") - } - - // old value should be still there :) - if f.Value().(string) != "fatih" { - t.Errorf("Setted value is wrong: %s want: %s", f.Value().(string), "fatih") - } - - // let's access an unexported field, which should give an error - f = s.Field("d") - err = f.Set("large") - if err != errNotExported { - t.Error(err) - } - - // let's set a pointer to struct - b := &Bar{ - E: "gopher", - F: 2, - } - - f = s.Field("Bar") - err = f.Set(b) - if err != nil { - t.Error(err) - } - - baz := &Baz{ - A: "helloWorld", - B: 42, - } - - f = s.Field("E") - err = f.Set(baz) - if err != nil { - t.Error(err) - } - - ba := s.Field("E").Value().(*Baz) - - if ba.A != "helloWorld" { - t.Errorf("could not set baz. Got: %s Want: helloWorld", ba.A) - } -} - -func TestField(t *testing.T) { - s := newStruct() - - defer func() { - err := recover() - if err == nil { - t.Error("Retrieveing a non existing field from the struct should panic") - } - }() - - _ = s.Field("no-field") -} - -func TestField_Kind(t *testing.T) { - s := newStruct() - - f := s.Field("A") - if f.Kind() != reflect.String { - t.Errorf("Field A has wrong kind: %s want: %s", f.Kind(), reflect.String) - } - - f = s.Field("B") - if f.Kind() != reflect.Int { - t.Errorf("Field B has wrong kind: %s want: %s", f.Kind(), reflect.Int) - } - - // unexported - f = s.Field("d") - if f.Kind() != reflect.String { - t.Errorf("Field d has wrong kind: %s want: %s", f.Kind(), reflect.String) - } -} - -func TestField_Tag(t *testing.T) { - s := newStruct() - - v := s.Field("B").Tag("json") - if v != "" { - t.Errorf("Field's tag value of a non existing tag should return empty, got: %s", v) - } - - v = s.Field("C").Tag("json") - if v != "c" { - t.Errorf("Field's tag value of the existing field C should return 'c', got: %s", v) - } - - v = s.Field("d").Tag("json") - if v != "" { - t.Errorf("Field's tag value of a non exported field should return empty, got: %s", v) - } - - v = s.Field("x").Tag("xml") - if v != "x" { - t.Errorf("Field's tag value of a non exported field with a tag should return 'x', got: %s", v) - } - - v = s.Field("A").Tag("json") - if v != "" { - t.Errorf("Field's tag value of a existing field without a tag should return empty, got: %s", v) - } -} - -func TestField_Value(t *testing.T) { - s := newStruct() - - v := s.Field("A").Value() - val, ok := v.(string) - if !ok { - t.Errorf("Field's value of a A should be string") - } - - if val != "gopher" { - t.Errorf("Field's value of a existing tag should return 'gopher', got: %s", val) - } - - defer func() { - err := recover() - if err == nil { - t.Error("Value of a non exported field from the field should panic") - } - }() - - // should panic - _ = s.Field("d").Value() -} - -func TestField_IsEmbedded(t *testing.T) { - s := newStruct() - - if !s.Field("Bar").IsEmbedded() { - t.Errorf("Fields 'Bar' field is an embedded field") - } - - if s.Field("d").IsEmbedded() { - t.Errorf("Fields 'd' field is not an embedded field") - } -} - -func TestField_IsExported(t *testing.T) { - s := newStruct() - - if !s.Field("Bar").IsExported() { - t.Errorf("Fields 'Bar' field is an exported field") - } - - if !s.Field("A").IsExported() { - t.Errorf("Fields 'A' field is an exported field") - } - - if s.Field("d").IsExported() { - t.Errorf("Fields 'd' field is not an exported field") - } -} - -func TestField_IsZero(t *testing.T) { - s := newStruct() - - if s.Field("A").IsZero() { - t.Errorf("Fields 'A' field is an initialized field") - } - - if !s.Field("B").IsZero() { - t.Errorf("Fields 'B' field is not an initialized field") - } -} - -func TestField_Name(t *testing.T) { - s := newStruct() - - if s.Field("A").Name() != "A" { - t.Errorf("Fields 'A' field should have the name 'A'") - } -} - -func TestField_Field(t *testing.T) { - s := newStruct() - - e := s.Field("Bar").Field("E") - - val, ok := e.Value().(string) - if !ok { - t.Error("The value of the field 'e' inside 'Bar' struct should be string") - } - - if val != "example" { - t.Errorf("The value of 'e' should be 'example, got: %s", val) - } - - defer func() { - err := recover() - if err == nil { - t.Error("Field of a non existing nested struct should panic") - } - }() - - _ = s.Field("Bar").Field("e") -} - -func TestField_Fields(t *testing.T) { - s := newStruct() - fields := s.Field("Bar").Fields() - - if len(fields) != 3 { - t.Errorf("We expect 3 fields in embedded struct, was: %d", len(fields)) - } -} - -func TestField_FieldOk(t *testing.T) { - s := newStruct() - - b, ok := s.FieldOk("Bar") - if !ok { - t.Error("The field 'Bar' should exists.") - } - - e, ok := b.FieldOk("E") - if !ok { - t.Error("The field 'E' should exists.") - } - - val, ok := e.Value().(string) - if !ok { - t.Error("The value of the field 'e' inside 'Bar' struct should be string") - } - - if val != "example" { - t.Errorf("The value of 'e' should be 'example, got: %s", val) - } -} diff --git a/Godeps/_workspace/src/github.com/fatih/structs/structs.go b/Godeps/_workspace/src/github.com/fatih/structs/structs.go deleted file mode 100644 index 47bf35453..000000000 --- a/Godeps/_workspace/src/github.com/fatih/structs/structs.go +++ /dev/null @@ -1,422 +0,0 @@ -// Package structs contains various utilities functions to work with structs. -package structs - -import "reflect" - -var ( - // DefaultTagName is the default tag name for struct fields which provides - // a more granular to tweak certain structs. Lookup the necessary functions - // for more info. - DefaultTagName = "structs" // struct's field default tag name -) - -// Struct encapsulates a struct type to provide several high level functions -// around the struct. -type Struct struct { - raw interface{} - value reflect.Value - TagName string -} - -// New returns a new *Struct with the struct s. It panics if the s's kind is -// not struct. -func New(s interface{}) *Struct { - return &Struct{ - raw: s, - value: strctVal(s), - TagName: DefaultTagName, - } -} - -// Map converts the given struct to a map[string]interface{}, where the keys -// of the map are the field names and the values of the map the associated -// values of the fields. The default key string is the struct field name but -// can be changed in the struct field's tag value. The "structs" key in the -// struct's field tag value is the key name. Example: -// -// // Field appears in map as key "myName". -// Name string `structs:"myName"` -// -// A tag value with the content of "-" ignores that particular field. Example: -// -// // Field is ignored by this package. -// Field bool `structs:"-"` -// -// A tag value with the option of "omitnested" stops iterating further if the type -// is a struct. Example: -// -// // Field is not processed further by this package. -// Field time.Time `structs:"myName,omitnested"` -// Field *http.Request `structs:",omitnested"` -// -// A tag value with the option of "omitempty" ignores that particular field if -// the field value is empty. Example: -// -// // Field appears in map as key "myName", but the field is -// // skipped if empty. -// Field string `structs:"myName,omitempty"` -// -// // Field appears in map as key "Field" (the default), but -// // the field is skipped if empty. -// Field string `structs:",omitempty"` -// -// Note that only exported fields of a struct can be accessed, non exported -// fields will be neglected. -func (s *Struct) Map() map[string]interface{} { - out := make(map[string]interface{}) - - fields := s.structFields() - - for _, field := range fields { - name := field.Name - val := s.value.FieldByName(name) - - var finalVal interface{} - - tagName, tagOpts := parseTag(field.Tag.Get(s.TagName)) - if tagName != "" { - name = tagName - } - - // if the value is a zero value and the field is marked as omitempty do - // not include - if tagOpts.Has("omitempty") { - zero := reflect.Zero(val.Type()).Interface() - current := val.Interface() - - if reflect.DeepEqual(current, zero) { - continue - } - } - - if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") { - // look out for embedded structs, and convert them to a - // map[string]interface{} too - finalVal = Map(val.Interface()) - } else { - finalVal = val.Interface() - } - - out[name] = finalVal - } - - return out -} - -// Values converts the given s struct's field values to a []interface{}. A -// struct tag with the content of "-" ignores the that particular field. -// Example: -// -// // Field is ignored by this package. -// Field int `structs:"-"` -// -// A value with the option of "omitnested" stops iterating further if the type -// is a struct. Example: -// -// // Fields is not processed further by this package. -// Field time.Time `structs:",omitnested"` -// Field *http.Request `structs:",omitnested"` -// -// A tag value with the option of "omitempty" ignores that particular field and -// is not added to the values if the field value is empty. Example: -// -// // Field is skipped if empty -// Field string `structs:",omitempty"` -// -// Note that only exported fields of a struct can be accessed, non exported -// fields will be neglected. -func (s *Struct) Values() []interface{} { - fields := s.structFields() - - var t []interface{} - - for _, field := range fields { - val := s.value.FieldByName(field.Name) - - _, tagOpts := parseTag(field.Tag.Get(s.TagName)) - - // if the value is a zero value and the field is marked as omitempty do - // not include - if tagOpts.Has("omitempty") { - zero := reflect.Zero(val.Type()).Interface() - current := val.Interface() - - if reflect.DeepEqual(current, zero) { - continue - } - } - - if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") { - // look out for embedded structs, and convert them to a - // []interface{} to be added to the final values slice - for _, embeddedVal := range Values(val.Interface()) { - t = append(t, embeddedVal) - } - } else { - t = append(t, val.Interface()) - } - } - - return t -} - -// Fields returns a slice of Fields. A struct tag with the content of "-" -// ignores the checking of that particular field. Example: -// -// // Field is ignored by this package. -// Field bool `structs:"-"` -// -// It panics if s's kind is not struct. -func (s *Struct) Fields() []*Field { - return getFields(s.value, s.TagName) -} - -func getFields(v reflect.Value, tagName string) []*Field { - if v.Kind() == reflect.Ptr { - v = v.Elem() - } - - t := v.Type() - - var fields []*Field - - for i := 0; i < t.NumField(); i++ { - field := t.Field(i) - - if tag := field.Tag.Get(tagName); tag == "-" { - continue - } - - f := &Field{ - field: field, - value: v.FieldByName(field.Name), - } - - fields = append(fields, f) - - } - - return fields -} - -// Field returns a new Field struct that provides several high level functions -// around a single struct field entity. It panics if the field is not found. -func (s *Struct) Field(name string) *Field { - f, ok := s.FieldOk(name) - if !ok { - panic("field not found") - } - - return f -} - -// Field returns a new Field struct that provides several high level functions -// around a single struct field entity. The boolean returns true if the field -// was found. -func (s *Struct) FieldOk(name string) (*Field, bool) { - t := s.value.Type() - - field, ok := t.FieldByName(name) - if !ok { - return nil, false - } - - return &Field{ - field: field, - value: s.value.FieldByName(name), - defaultTag: s.TagName, - }, true -} - -// IsZero returns true if all fields in a struct is a zero value (not -// initialized) A struct tag with the content of "-" ignores the checking of -// that particular field. Example: -// -// // Field is ignored by this package. -// Field bool `structs:"-"` -// -// A value with the option of "omitnested" stops iterating further if the type -// is a struct. Example: -// -// // Field is not processed further by this package. -// Field time.Time `structs:"myName,omitnested"` -// Field *http.Request `structs:",omitnested"` -// -// Note that only exported fields of a struct can be accessed, non exported -// fields will be neglected. It panics if s's kind is not struct. -func (s *Struct) IsZero() bool { - fields := s.structFields() - - for _, field := range fields { - val := s.value.FieldByName(field.Name) - - _, tagOpts := parseTag(field.Tag.Get(s.TagName)) - - if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") { - ok := IsZero(val.Interface()) - if !ok { - return false - } - - continue - } - - // zero value of the given field, such as "" for string, 0 for int - zero := reflect.Zero(val.Type()).Interface() - - // current value of the given field - current := val.Interface() - - if !reflect.DeepEqual(current, zero) { - return false - } - } - - return true -} - -// HasZero returns true if a field in a struct is not initialized (zero value). -// A struct tag with the content of "-" ignores the checking of that particular -// field. Example: -// -// // Field is ignored by this package. -// Field bool `structs:"-"` -// -// A value with the option of "omitnested" stops iterating further if the type -// is a struct. Example: -// -// // Field is not processed further by this package. -// Field time.Time `structs:"myName,omitnested"` -// Field *http.Request `structs:",omitnested"` -// -// Note that only exported fields of a struct can be accessed, non exported -// fields will be neglected. It panics if s's kind is not struct. -func (s *Struct) HasZero() bool { - fields := s.structFields() - - for _, field := range fields { - val := s.value.FieldByName(field.Name) - - _, tagOpts := parseTag(field.Tag.Get(s.TagName)) - - if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") { - ok := HasZero(val.Interface()) - if ok { - return true - } - - continue - } - - // zero value of the given field, such as "" for string, 0 for int - zero := reflect.Zero(val.Type()).Interface() - - // current value of the given field - current := val.Interface() - - if reflect.DeepEqual(current, zero) { - return true - } - } - - return false -} - -// Name returns the structs's type name within its package. For more info refer -// to Name() function. -func (s *Struct) Name() string { - return s.value.Type().Name() -} - -// structFields returns the exported struct fields for a given s struct. This -// is a convenient helper method to avoid duplicate code in some of the -// functions. -func (s *Struct) structFields() []reflect.StructField { - t := s.value.Type() - - var f []reflect.StructField - - for i := 0; i < t.NumField(); i++ { - field := t.Field(i) - // we can't access the value of unexported fields - if field.PkgPath != "" { - continue - } - - // don't check if it's omitted - if tag := field.Tag.Get(s.TagName); tag == "-" { - continue - } - - f = append(f, field) - } - - return f -} - -func strctVal(s interface{}) reflect.Value { - v := reflect.ValueOf(s) - - // if pointer get the underlying element≤ - if v.Kind() == reflect.Ptr { - v = v.Elem() - } - - if v.Kind() != reflect.Struct { - panic("not struct") - } - - return v -} - -// Map converts the given struct to a map[string]interface{}. For more info -// refer to Struct types Map() method. It panics if s's kind is not struct. -func Map(s interface{}) map[string]interface{} { - return New(s).Map() -} - -// Values converts the given struct to a []interface{}. For more info refer to -// Struct types Values() method. It panics if s's kind is not struct. -func Values(s interface{}) []interface{} { - return New(s).Values() -} - -// Fields returns a slice of *Field. For more info refer to Struct types -// Fields() method. It panics if s's kind is not struct. -func Fields(s interface{}) []*Field { - return New(s).Fields() -} - -// IsZero returns true if all fields is equal to a zero value. For more info -// refer to Struct types IsZero() method. It panics if s's kind is not struct. -func IsZero(s interface{}) bool { - return New(s).IsZero() -} - -// HasZero returns true if any field is equal to a zero value. For more info -// refer to Struct types HasZero() method. It panics if s's kind is not struct. -func HasZero(s interface{}) bool { - return New(s).HasZero() -} - -// IsStruct returns true if the given variable is a struct or a pointer to -// struct. -func IsStruct(s interface{}) bool { - v := reflect.ValueOf(s) - if v.Kind() == reflect.Ptr { - v = v.Elem() - } - - // uninitialized zero value of a struct - if v.Kind() == reflect.Invalid { - return false - } - - return v.Kind() == reflect.Struct -} - -// Name returns the structs's type name within its package. It returns an -// empty string for unnamed types. It panics if s's kind is not struct. -func Name(s interface{}) string { - return New(s).Name() -} diff --git a/Godeps/_workspace/src/github.com/fatih/structs/structs_example_test.go b/Godeps/_workspace/src/github.com/fatih/structs/structs_example_test.go deleted file mode 100644 index 32bb82937..000000000 --- a/Godeps/_workspace/src/github.com/fatih/structs/structs_example_test.go +++ /dev/null @@ -1,351 +0,0 @@ -package structs - -import ( - "fmt" - "time" -) - -func ExampleNew() { - type Server struct { - Name string - ID int32 - Enabled bool - } - - server := &Server{ - Name: "Arslan", - ID: 123456, - Enabled: true, - } - - s := New(server) - - fmt.Printf("Name : %v\n", s.Name()) - fmt.Printf("Values : %v\n", s.Values()) - fmt.Printf("Value of ID : %v\n", s.Field("ID").Value()) - // Output: - // Name : Server - // Values : [Arslan 123456 true] - // Value of ID : 123456 - -} - -func ExampleMap() { - type Server struct { - Name string - ID int32 - Enabled bool - } - - s := &Server{ - Name: "Arslan", - ID: 123456, - Enabled: true, - } - - m := Map(s) - - fmt.Printf("%#v\n", m["Name"]) - fmt.Printf("%#v\n", m["ID"]) - fmt.Printf("%#v\n", m["Enabled"]) - // Output: - // "Arslan" - // 123456 - // true - -} - -func ExampleMap_tags() { - // Custom tags can change the map keys instead of using the fields name - type Server struct { - Name string `structs:"server_name"` - ID int32 `structs:"server_id"` - Enabled bool `structs:"enabled"` - } - - s := &Server{ - Name: "Zeynep", - ID: 789012, - } - - m := Map(s) - - // access them by the custom tags defined above - fmt.Printf("%#v\n", m["server_name"]) - fmt.Printf("%#v\n", m["server_id"]) - fmt.Printf("%#v\n", m["enabled"]) - // Output: - // "Zeynep" - // 789012 - // false - -} - -func ExampleMap_nested() { - // By default field with struct types are processed too. We can stop - // processing them via "omitnested" tag option. - type Server struct { - Name string `structs:"server_name"` - ID int32 `structs:"server_id"` - Time time.Time `structs:"time,omitnested"` // do not convert to map[string]interface{} - } - - const shortForm = "2006-Jan-02" - t, _ := time.Parse("2006-Jan-02", "2013-Feb-03") - - s := &Server{ - Name: "Zeynep", - ID: 789012, - Time: t, - } - - m := Map(s) - - // access them by the custom tags defined above - fmt.Printf("%v\n", m["server_name"]) - fmt.Printf("%v\n", m["server_id"]) - fmt.Printf("%v\n", m["time"].(time.Time)) - // Output: - // Zeynep - // 789012 - // 2013-02-03 00:00:00 +0000 UTC -} - -func ExampleMap_omitEmpty() { - // By default field with struct types of zero values are processed too. We - // can stop processing them via "omitempty" tag option. - type Server struct { - Name string `structs:",omitempty"` - ID int32 `structs:"server_id,omitempty"` - Location string - } - - // Only add location - s := &Server{ - Location: "Tokyo", - } - - m := Map(s) - - // map contains only the Location field - fmt.Printf("%v\n", m) - // Output: - // map[Location:Tokyo] -} - -func ExampleValues() { - type Server struct { - Name string - ID int32 - Enabled bool - } - - s := &Server{ - Name: "Fatih", - ID: 135790, - Enabled: false, - } - - m := Values(s) - - fmt.Printf("Values: %+v\n", m) - // Output: - // Values: [Fatih 135790 false] -} - -func ExampleValues_omitEmpty() { - // By default field with struct types of zero values are processed too. We - // can stop processing them via "omitempty" tag option. - type Server struct { - Name string `structs:",omitempty"` - ID int32 `structs:"server_id,omitempty"` - Location string - } - - // Only add location - s := &Server{ - Location: "Ankara", - } - - m := Values(s) - - // values contains only the Location field - fmt.Printf("Values: %+v\n", m) - // Output: - // Values: [Ankara] -} - -func ExampleValues_tags() { - type Location struct { - City string - Country string - } - - type Server struct { - Name string - ID int32 - Enabled bool - Location Location `structs:"-"` // values from location are not included anymore - } - - s := &Server{ - Name: "Fatih", - ID: 135790, - Enabled: false, - Location: Location{City: "Ankara", Country: "Turkey"}, - } - - // Let get all values from the struct s. Note that we don't include values - // from the Location field - m := Values(s) - - fmt.Printf("Values: %+v\n", m) - // Output: - // Values: [Fatih 135790 false] -} - -func ExampleFields() { - type Access struct { - Name string - LastAccessed time.Time - Number int - } - - s := &Access{ - Name: "Fatih", - LastAccessed: time.Now(), - Number: 1234567, - } - - fields := Fields(s) - - for i, field := range fields { - fmt.Printf("[%d] %+v\n", i, field.Name()) - } - - // Output: - // [0] Name - // [1] LastAccessed - // [2] Number -} - -func ExampleFields_nested() { - type Person struct { - Name string - Number int - } - - type Access struct { - Person Person - HasPermission bool - LastAccessed time.Time - } - - s := &Access{ - Person: Person{Name: "fatih", Number: 1234567}, - LastAccessed: time.Now(), - HasPermission: true, - } - - // Let's get all fields from the struct s. - fields := Fields(s) - - for _, field := range fields { - if field.Name() == "Person" { - fmt.Printf("Access.Person.Name: %+v\n", field.Field("Name").Value()) - } - } - - // Output: - // Access.Person.Name: fatih -} - -func ExampleField() { - type Person struct { - Name string - Number int - } - - type Access struct { - Person Person - HasPermission bool - LastAccessed time.Time - } - - access := &Access{ - Person: Person{Name: "fatih", Number: 1234567}, - LastAccessed: time.Now(), - HasPermission: true, - } - - // Create a new Struct type - s := New(access) - - // Get the Field type for "Person" field - p := s.Field("Person") - - // Get the underlying "Name field" and print the value of it - name := p.Field("Name") - - fmt.Printf("Value of Person.Access.Name: %+v\n", name.Value()) - - // Output: - // Value of Person.Access.Name: fatih - -} - -func ExampleIsZero() { - type Server struct { - Name string - ID int32 - Enabled bool - } - - // Nothing is initalized - a := &Server{} - isZeroA := IsZero(a) - - // Name and Enabled is initialized, but not ID - b := &Server{ - Name: "Golang", - Enabled: true, - } - isZeroB := IsZero(b) - - fmt.Printf("%#v\n", isZeroA) - fmt.Printf("%#v\n", isZeroB) - // Output: - // true - // false -} - -func ExampleHasZero() { - // Let's define an Access struct. Note that the "Enabled" field is not - // going to be checked because we added the "structs" tag to the field. - type Access struct { - Name string - LastAccessed time.Time - Number int - Enabled bool `structs:"-"` - } - - // Name and Number is not initialized. - a := &Access{ - LastAccessed: time.Now(), - } - hasZeroA := HasZero(a) - - // Name and Number is initialized. - b := &Access{ - Name: "Fatih", - LastAccessed: time.Now(), - Number: 12345, - } - hasZeroB := HasZero(b) - - fmt.Printf("%#v\n", hasZeroA) - fmt.Printf("%#v\n", hasZeroB) - // Output: - // true - // false -} diff --git a/Godeps/_workspace/src/github.com/fatih/structs/structs_test.go b/Godeps/_workspace/src/github.com/fatih/structs/structs_test.go deleted file mode 100644 index 02788b105..000000000 --- a/Godeps/_workspace/src/github.com/fatih/structs/structs_test.go +++ /dev/null @@ -1,847 +0,0 @@ -package structs - -import ( - "fmt" - "reflect" - "testing" - "time" -) - -func TestMapNonStruct(t *testing.T) { - foo := []string{"foo"} - - defer func() { - err := recover() - if err == nil { - t.Error("Passing a non struct into Map should panic") - } - }() - - // this should panic. We are going to recover and and test it - _ = Map(foo) -} - -func TestStructIndexes(t *testing.T) { - type C struct { - something int - Props map[string]interface{} - } - - defer func() { - err := recover() - if err != nil { - fmt.Printf("err %+v\n", err) - t.Error("Using mixed indexes should not panic") - } - }() - - // They should not panic - _ = Map(&C{}) - _ = Fields(&C{}) - _ = Values(&C{}) - _ = IsZero(&C{}) - _ = HasZero(&C{}) -} - -func TestMap(t *testing.T) { - var T = struct { - A string - B int - C bool - }{ - A: "a-value", - B: 2, - C: true, - } - - a := Map(T) - - if typ := reflect.TypeOf(a).Kind(); typ != reflect.Map { - t.Errorf("Map should return a map type, got: %v", typ) - } - - // we have three fields - if len(a) != 3 { - t.Errorf("Map should return a map of len 3, got: %d", len(a)) - } - - inMap := func(val interface{}) bool { - for _, v := range a { - if reflect.DeepEqual(v, val) { - return true - } - } - - return false - } - - for _, val := range []interface{}{"a-value", 2, true} { - if !inMap(val) { - t.Errorf("Map should have the value %v", val) - } - } - -} - -func TestMap_Tag(t *testing.T) { - var T = struct { - A string `structs:"x"` - B int `structs:"y"` - C bool `structs:"z"` - }{ - A: "a-value", - B: 2, - C: true, - } - - a := Map(T) - - inMap := func(key interface{}) bool { - for k := range a { - if reflect.DeepEqual(k, key) { - return true - } - } - return false - } - - for _, key := range []string{"x", "y", "z"} { - if !inMap(key) { - t.Errorf("Map should have the key %v", key) - } - } - -} - -func TestMap_CustomTag(t *testing.T) { - var T = struct { - A string `dd:"x"` - B int `dd:"y"` - C bool `dd:"z"` - }{ - A: "a-value", - B: 2, - C: true, - } - - s := New(T) - s.TagName = "dd" - - a := s.Map() - - inMap := func(key interface{}) bool { - for k := range a { - if reflect.DeepEqual(k, key) { - return true - } - } - return false - } - - for _, key := range []string{"x", "y", "z"} { - if !inMap(key) { - t.Errorf("Map should have the key %v", key) - } - } - -} - -func TestMap_MultipleCustomTag(t *testing.T) { - var A = struct { - X string `aa:"ax"` - }{"a_value"} - - aStruct := New(A) - aStruct.TagName = "aa" - - var B = struct { - X string `bb:"bx"` - }{"b_value"} - - bStruct := New(B) - bStruct.TagName = "bb" - - a, b := aStruct.Map(), bStruct.Map() - if !reflect.DeepEqual(a, map[string]interface{}{"ax": "a_value"}) { - t.Error("Map should have field ax with value a_value") - } - - if !reflect.DeepEqual(b, map[string]interface{}{"bx": "b_value"}) { - t.Error("Map should have field bx with value b_value") - } -} - -func TestMap_OmitEmpty(t *testing.T) { - type A struct { - Name string - Value string `structs:",omitempty"` - Time time.Time `structs:",omitempty"` - } - a := A{} - - m := Map(a) - - _, ok := m["Value"].(map[string]interface{}) - if ok { - t.Error("Map should not contain the Value field that is tagged as omitempty") - } - - _, ok = m["Time"].(map[string]interface{}) - if ok { - t.Error("Map should not contain the Time field that is tagged as omitempty") - } -} - -func TestMap_OmitNested(t *testing.T) { - type A struct { - Name string - Value string - Time time.Time `structs:",omitnested"` - } - a := A{Time: time.Now()} - - type B struct { - Desc string - A A - } - b := &B{A: a} - - m := Map(b) - - in, ok := m["A"].(map[string]interface{}) - if !ok { - t.Error("Map nested structs is not available in the map") - } - - // should not happen - if _, ok := in["Time"].(map[string]interface{}); ok { - t.Error("Map nested struct should omit recursiving parsing of Time") - } - - if _, ok := in["Time"].(time.Time); !ok { - t.Error("Map nested struct should stop parsing of Time at is current value") - } -} - -func TestMap_Nested(t *testing.T) { - type A struct { - Name string - } - a := &A{Name: "example"} - - type B struct { - A *A - } - b := &B{A: a} - - m := Map(b) - - if typ := reflect.TypeOf(m).Kind(); typ != reflect.Map { - t.Errorf("Map should return a map type, got: %v", typ) - } - - in, ok := m["A"].(map[string]interface{}) - if !ok { - t.Error("Map nested structs is not available in the map") - } - - if name := in["Name"].(string); name != "example" { - t.Errorf("Map nested struct's name field should give example, got: %s", name) - } -} - -func TestMap_Anonymous(t *testing.T) { - type A struct { - Name string - } - a := &A{Name: "example"} - - type B struct { - *A - } - b := &B{} - b.A = a - - m := Map(b) - - if typ := reflect.TypeOf(m).Kind(); typ != reflect.Map { - t.Errorf("Map should return a map type, got: %v", typ) - } - - in, ok := m["A"].(map[string]interface{}) - if !ok { - t.Error("Embedded structs is not available in the map") - } - - if name := in["Name"].(string); name != "example" { - t.Errorf("Embedded A struct's Name field should give example, got: %s", name) - } -} - -func TestStruct(t *testing.T) { - var T = struct{}{} - - if !IsStruct(T) { - t.Errorf("T should be a struct, got: %T", T) - } - - if !IsStruct(&T) { - t.Errorf("T should be a struct, got: %T", T) - } - -} - -func TestValues(t *testing.T) { - var T = struct { - A string - B int - C bool - }{ - A: "a-value", - B: 2, - C: true, - } - - s := Values(T) - - if typ := reflect.TypeOf(s).Kind(); typ != reflect.Slice { - t.Errorf("Values should return a slice type, got: %v", typ) - } - - inSlice := func(val interface{}) bool { - for _, v := range s { - if reflect.DeepEqual(v, val) { - return true - } - } - return false - } - - for _, val := range []interface{}{"a-value", 2, true} { - if !inSlice(val) { - t.Errorf("Values should have the value %v", val) - } - } -} - -func TestValues_OmitEmpty(t *testing.T) { - type A struct { - Name string - Value int `structs:",omitempty"` - } - - a := A{Name: "example"} - s := Values(a) - - if len(s) != 1 { - t.Errorf("Values of omitted empty fields should be not counted") - } - - if s[0].(string) != "example" { - t.Errorf("Values of omitted empty fields should left the value example") - } -} - -func TestValues_OmitNested(t *testing.T) { - type A struct { - Name string - Value int - } - - a := A{ - Name: "example", - Value: 123, - } - - type B struct { - A A `structs:",omitnested"` - C int - } - b := &B{A: a, C: 123} - - s := Values(b) - - if len(s) != 2 { - t.Errorf("Values of omitted nested struct should be not counted") - } - - inSlice := func(val interface{}) bool { - for _, v := range s { - if reflect.DeepEqual(v, val) { - return true - } - } - return false - } - - for _, val := range []interface{}{123, a} { - if !inSlice(val) { - t.Errorf("Values should have the value %v", val) - } - } -} - -func TestValues_Nested(t *testing.T) { - type A struct { - Name string - } - a := A{Name: "example"} - - type B struct { - A A - C int - } - b := &B{A: a, C: 123} - - s := Values(b) - - inSlice := func(val interface{}) bool { - for _, v := range s { - if reflect.DeepEqual(v, val) { - return true - } - } - return false - } - - for _, val := range []interface{}{"example", 123} { - if !inSlice(val) { - t.Errorf("Values should have the value %v", val) - } - } -} - -func TestValues_Anonymous(t *testing.T) { - type A struct { - Name string - } - a := A{Name: "example"} - - type B struct { - A - C int - } - b := &B{C: 123} - b.A = a - - s := Values(b) - - inSlice := func(val interface{}) bool { - for _, v := range s { - if reflect.DeepEqual(v, val) { - return true - } - } - return false - } - - for _, val := range []interface{}{"example", 123} { - if !inSlice(val) { - t.Errorf("Values should have the value %v", val) - } - } -} - -func TestFields(t *testing.T) { - var T = struct { - A string - B int - C bool - }{ - A: "a-value", - B: 2, - C: true, - } - - s := Fields(T) - - if len(s) != 3 { - t.Errorf("Fields should return a slice of len 3, got: %d", len(s)) - } - - inSlice := func(val string) bool { - for _, v := range s { - if reflect.DeepEqual(v.Name(), val) { - return true - } - } - return false - } - - for _, val := range []string{"A", "B", "C"} { - if !inSlice(val) { - t.Errorf("Fields should have the value %v", val) - } - } -} - -func TestFields_OmitNested(t *testing.T) { - type A struct { - Name string - Enabled bool - } - a := A{Name: "example"} - - type B struct { - A A - C int - Value string `structs:"-"` - Number int - } - b := &B{A: a, C: 123} - - s := Fields(b) - - if len(s) != 3 { - t.Errorf("Fields should omit nested struct. Expecting 2 got: %d", len(s)) - } - - inSlice := func(val interface{}) bool { - for _, v := range s { - if reflect.DeepEqual(v.Name(), val) { - return true - } - } - return false - } - - for _, val := range []interface{}{"A", "C"} { - if !inSlice(val) { - t.Errorf("Fields should have the value %v", val) - } - } -} - -func TestFields_Anonymous(t *testing.T) { - type A struct { - Name string - } - a := A{Name: "example"} - - type B struct { - A - C int - } - b := &B{C: 123} - b.A = a - - s := Fields(b) - - inSlice := func(val interface{}) bool { - for _, v := range s { - if reflect.DeepEqual(v.Name(), val) { - return true - } - } - return false - } - - for _, val := range []interface{}{"A", "C"} { - if !inSlice(val) { - t.Errorf("Fields should have the value %v", val) - } - } -} - -func TestIsZero(t *testing.T) { - var T = struct { - A string - B int - C bool `structs:"-"` - D []string - }{} - - ok := IsZero(T) - if !ok { - t.Error("IsZero should return true because none of the fields are initialized.") - } - - var X = struct { - A string - F *bool - }{ - A: "a-value", - } - - ok = IsZero(X) - if ok { - t.Error("IsZero should return false because A is initialized") - } - - var Y = struct { - A string - B int - }{ - A: "a-value", - B: 123, - } - - ok = IsZero(Y) - if ok { - t.Error("IsZero should return false because A and B is initialized") - } -} - -func TestIsZero_OmitNested(t *testing.T) { - type A struct { - Name string - D string - } - a := A{Name: "example"} - - type B struct { - A A `structs:",omitnested"` - C int - } - b := &B{A: a, C: 123} - - ok := IsZero(b) - if ok { - t.Error("IsZero should return false because A, B and C are initialized") - } - - aZero := A{} - bZero := &B{A: aZero} - - ok = IsZero(bZero) - if !ok { - t.Error("IsZero should return true because neither A nor B is initialized") - } - -} - -func TestIsZero_Nested(t *testing.T) { - type A struct { - Name string - D string - } - a := A{Name: "example"} - - type B struct { - A A - C int - } - b := &B{A: a, C: 123} - - ok := IsZero(b) - if ok { - t.Error("IsZero should return false because A, B and C are initialized") - } - - aZero := A{} - bZero := &B{A: aZero} - - ok = IsZero(bZero) - if !ok { - t.Error("IsZero should return true because neither A nor B is initialized") - } - -} - -func TestIsZero_Anonymous(t *testing.T) { - type A struct { - Name string - D string - } - a := A{Name: "example"} - - type B struct { - A - C int - } - b := &B{C: 123} - b.A = a - - ok := IsZero(b) - if ok { - t.Error("IsZero should return false because A, B and C are initialized") - } - - aZero := A{} - bZero := &B{} - bZero.A = aZero - - ok = IsZero(bZero) - if !ok { - t.Error("IsZero should return true because neither A nor B is initialized") - } -} - -func TestHasZero(t *testing.T) { - var T = struct { - A string - B int - C bool `structs:"-"` - D []string - }{ - A: "a-value", - B: 2, - } - - ok := HasZero(T) - if !ok { - t.Error("HasZero should return true because A and B are initialized.") - } - - var X = struct { - A string - F *bool - }{ - A: "a-value", - } - - ok = HasZero(X) - if !ok { - t.Error("HasZero should return true because A is initialized") - } - - var Y = struct { - A string - B int - }{ - A: "a-value", - B: 123, - } - - ok = HasZero(Y) - if ok { - t.Error("HasZero should return false because A and B is initialized") - } -} - -func TestHasZero_OmitNested(t *testing.T) { - type A struct { - Name string - D string - } - a := A{Name: "example"} - - type B struct { - A A `structs:",omitnested"` - C int - } - b := &B{A: a, C: 123} - - // Because the Field A inside B is omitted HasZero should return false - // because it will stop iterating deeper andnot going to lookup for D - ok := HasZero(b) - if ok { - t.Error("HasZero should return false because A and C are initialized") - } -} - -func TestHasZero_Nested(t *testing.T) { - type A struct { - Name string - D string - } - a := A{Name: "example"} - - type B struct { - A A - C int - } - b := &B{A: a, C: 123} - - ok := HasZero(b) - if !ok { - t.Error("HasZero should return true because D is not initialized") - } -} - -func TestHasZero_Anonymous(t *testing.T) { - type A struct { - Name string - D string - } - a := A{Name: "example"} - - type B struct { - A - C int - } - b := &B{C: 123} - b.A = a - - ok := HasZero(b) - if !ok { - t.Error("HasZero should return false because D is not initialized") - } -} - -func TestName(t *testing.T) { - type Foo struct { - A string - B bool - } - f := &Foo{} - - n := Name(f) - if n != "Foo" { - t.Errorf("Name should return Foo, got: %s", n) - } - - unnamed := struct{ Name string }{Name: "Cihangir"} - m := Name(unnamed) - if m != "" { - t.Errorf("Name should return empty string for unnamed struct, got: %s", n) - } - - defer func() { - err := recover() - if err == nil { - t.Error("Name should panic if a non struct is passed") - } - }() - - Name([]string{}) -} - -func TestNestedNilPointer(t *testing.T) { - type Collar struct { - Engraving string - } - - type Dog struct { - Name string - Collar *Collar - } - - type Person struct { - Name string - Dog *Dog - } - - person := &Person{ - Name: "John", - } - - personWithDog := &Person{ - Name: "Ron", - Dog: &Dog{ - Name: "Rover", - }, - } - - personWithDogWithCollar := &Person{ - Name: "Kon", - Dog: &Dog{ - Name: "Ruffles", - Collar: &Collar{ - Engraving: "If lost, call Kon", - }, - }, - } - - defer func() { - err := recover() - if err != nil { - fmt.Printf("err %+v\n", err) - t.Error("Internal nil pointer should not panic") - } - }() - - _ = Map(person) // Panics - _ = Map(personWithDog) // Panics - _ = Map(personWithDogWithCollar) // Doesn't panic -} diff --git a/Godeps/_workspace/src/github.com/fatih/structs/tags.go b/Godeps/_workspace/src/github.com/fatih/structs/tags.go deleted file mode 100644 index 8859341c1..000000000 --- a/Godeps/_workspace/src/github.com/fatih/structs/tags.go +++ /dev/null @@ -1,32 +0,0 @@ -package structs - -import "strings" - -// tagOptions contains a slice of tag options -type tagOptions []string - -// Has returns true if the given optiton is available in tagOptions -func (t tagOptions) Has(opt string) bool { - for _, tagOpt := range t { - if tagOpt == opt { - return true - } - } - - return false -} - -// parseTag splits a struct field's tag into its name and a list of options -// which comes after a name. A tag is in the form of: "name,option1,option2". -// The name can be neglectected. -func parseTag(tag string) (string, tagOptions) { - // tag is one of followings: - // "" - // "name" - // "name,opt" - // "name,opt,opt2" - // ",opt" - - res := strings.Split(tag, ",") - return res[0], res[1:] -} diff --git a/Godeps/_workspace/src/github.com/fatih/structs/tags_test.go b/Godeps/_workspace/src/github.com/fatih/structs/tags_test.go deleted file mode 100644 index 5d12724f1..000000000 --- a/Godeps/_workspace/src/github.com/fatih/structs/tags_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package structs - -import "testing" - -func TestParseTag_Name(t *testing.T) { - tags := []struct { - tag string - has bool - }{ - {"", false}, - {"name", true}, - {"name,opt", true}, - {"name , opt, opt2", false}, // has a single whitespace - {", opt, opt2", false}, - } - - for _, tag := range tags { - name, _ := parseTag(tag.tag) - - if (name != "name") && tag.has { - t.Errorf("Parse tag should return name: %#v", tag) - } - } -} - -func TestParseTag_Opts(t *testing.T) { - tags := []struct { - opts string - has bool - }{ - {"name", false}, - {"name,opt", true}, - {"name , opt, opt2", false}, // has a single whitespace - {",opt, opt2", true}, - {", opt3, opt4", false}, - } - - // search for "opt" - for _, tag := range tags { - _, opts := parseTag(tag.opts) - - if opts.Has("opt") != tag.has { - t.Errorf("Tag opts should have opt: %#v", tag) - } - } -} diff --git a/Godeps/_workspace/src/gopkg.in/check.v1/benchmark_test.go b/Godeps/_workspace/src/gopkg.in/check.v1/benchmark_test.go index 0114c5b1a..4dd827c16 100644 --- a/Godeps/_workspace/src/gopkg.in/check.v1/benchmark_test.go +++ b/Godeps/_workspace/src/gopkg.in/check.v1/benchmark_test.go @@ -3,8 +3,8 @@ package check_test import ( - . "gopkg.in/check.v1" "time" + . "gopkg.in/check.v1" ) var benchmarkS = Suite(&BenchmarkS{}) diff --git a/Godeps/_workspace/src/gopkg.in/check.v1/printer_test.go b/Godeps/_workspace/src/gopkg.in/check.v1/printer_test.go index daa6a737a..538b2d52e 100644 --- a/Godeps/_workspace/src/gopkg.in/check.v1/printer_test.go +++ b/Godeps/_workspace/src/gopkg.in/check.v1/printer_test.go @@ -1,7 +1,7 @@ package check_test import ( - . "gopkg.in/check.v1" + . "gopkg.in/check.v1" ) var _ = Suite(&PrinterS{}) @@ -9,101 +9,96 @@ var _ = Suite(&PrinterS{}) type PrinterS struct{} func (s *PrinterS) TestCountSuite(c *C) { - suitesRun += 1 + suitesRun += 1 } var printTestFuncLine int func init() { - printTestFuncLine = getMyLine() + 3 + printTestFuncLine = getMyLine() + 3 } func printTestFunc() { - println(1) // Comment1 - if 2 == 2 { // Comment2 - println(3) // Comment3 - } - switch 5 { - case 6: - println(6) // Comment6 - println(7) - } - switch interface{}(9).(type) { // Comment9 - case int: - println(10) - println(11) - } - select { - case <-(chan bool)(nil): - println(14) - println(15) - default: - println(16) - println(17) - } - println(19, - 20) - _ = func() { - println(21) - println(22) - } - println(24, func() { - println(25) - }) - // Leading comment - // with multiple lines. - println(29) // Comment29 + println(1) // Comment1 + if 2 == 2 { // Comment2 + println(3) // Comment3 + } + switch 5 { + case 6: println(6) // Comment6 + println(7) + } + switch interface{}(9).(type) {// Comment9 + case int: println(10) + println(11) + } + select { + case <-(chan bool)(nil): println(14) + println(15) + default: println(16) + println(17) + } + println(19, + 20) + _ = func() { println(21) + println(22) + } + println(24, func() { + println(25) + }) + // Leading comment + // with multiple lines. + println(29) // Comment29 } var printLineTests = []struct { - line int - output string + line int + output string }{ - {1, "println(1) // Comment1"}, - {2, "if 2 == 2 { // Comment2\n ...\n}"}, - {3, "println(3) // Comment3"}, - {5, "switch 5 {\n...\n}"}, - {6, "case 6:\n println(6) // Comment6\n ..."}, - {7, "println(7)"}, - {9, "switch interface{}(9).(type) { // Comment9\n...\n}"}, - {10, "case int:\n println(10)\n ..."}, - {14, "case <-(chan bool)(nil):\n println(14)\n ..."}, - {15, "println(15)"}, - {16, "default:\n println(16)\n ..."}, - {17, "println(17)"}, - {19, "println(19,\n 20)"}, - {20, "println(19,\n 20)"}, - {21, "_ = func() {\n println(21)\n println(22)\n}"}, - {22, "println(22)"}, - {24, "println(24, func() {\n println(25)\n})"}, - {25, "println(25)"}, - {26, "println(24, func() {\n println(25)\n})"}, - {29, "// Leading comment\n// with multiple lines.\nprintln(29) // Comment29"}, + {1, "println(1) // Comment1"}, + {2, "if 2 == 2 { // Comment2\n ...\n}"}, + {3, "println(3) // Comment3"}, + {5, "switch 5 {\n...\n}"}, + {6, "case 6:\n println(6) // Comment6\n ..."}, + {7, "println(7)"}, + {9, "switch interface{}(9).(type) { // Comment9\n...\n}"}, + {10, "case int:\n println(10)\n ..."}, + {14, "case <-(chan bool)(nil):\n println(14)\n ..."}, + {15, "println(15)"}, + {16, "default:\n println(16)\n ..."}, + {17, "println(17)"}, + {19, "println(19,\n 20)"}, + {20, "println(19,\n 20)"}, + {21, "_ = func() {\n println(21)\n println(22)\n}"}, + {22, "println(22)"}, + {24, "println(24, func() {\n println(25)\n})"}, + {25, "println(25)"}, + {26, "println(24, func() {\n println(25)\n})"}, + {29, "// Leading comment\n// with multiple lines.\nprintln(29) // Comment29"}, } func (s *PrinterS) TestPrintLine(c *C) { - for _, test := range printLineTests { - output, err := PrintLine("printer_test.go", printTestFuncLine+test.line) - c.Assert(err, IsNil) - c.Assert(output, Equals, test.output) - } + for _, test := range printLineTests { + output, err := PrintLine("printer_test.go", printTestFuncLine+test.line) + c.Assert(err, IsNil) + c.Assert(output, Equals, test.output) + } } var indentTests = []struct { - in, out string + in, out string }{ - {"", ""}, - {"\n", "\n"}, - {"a", ">>>a"}, - {"a\n", ">>>a\n"}, - {"a\nb", ">>>a\n>>>b"}, - {" ", ">>> "}, + {"", ""}, + {"\n", "\n"}, + {"a", ">>>a"}, + {"a\n", ">>>a\n"}, + {"a\nb", ">>>a\n>>>b"}, + {" ", ">>> "}, } func (s *PrinterS) TestIndent(c *C) { - for _, test := range indentTests { - out := Indent(test.in, ">>>") - c.Assert(out, Equals, test.out) - } + for _, test := range indentTests { + out := Indent(test.in, ">>>") + c.Assert(out, Equals, test.out) + } } diff --git a/Godeps/_workspace/src/gopkg.in/check.v1/run_test.go b/Godeps/_workspace/src/gopkg.in/check.v1/run_test.go index 3ccb0eed7..f41fffc3f 100644 --- a/Godeps/_workspace/src/gopkg.in/check.v1/run_test.go +++ b/Godeps/_workspace/src/gopkg.in/check.v1/run_test.go @@ -400,7 +400,7 @@ func (s *RunS) TestStreamModeWithMiss(c *C) { // ----------------------------------------------------------------------- // Verify that that the keep work dir request indeed does so. -type WorkDirSuite struct{} +type WorkDirSuite struct {} func (s *WorkDirSuite) Test(c *C) { c.MkDir() @@ -411,7 +411,7 @@ func (s *RunS) TestKeepWorkDir(c *C) { runConf := RunConf{Output: &output, Verbose: true, KeepWorkDir: true} result := Run(&WorkDirSuite{}, &runConf) - c.Assert(result.String(), Matches, ".*\nWORK="+result.WorkDir) + c.Assert(result.String(), Matches, ".*\nWORK=" + result.WorkDir) stat, err := os.Stat(result.WorkDir) c.Assert(err, IsNil) diff --git a/pkg/api/Godeps/Godeps.json b/pkg/api/Godeps/Godeps.json new file mode 100644 index 000000000..1cd7f813f --- /dev/null +++ b/pkg/api/Godeps/Godeps.json @@ -0,0 +1,41 @@ +{ + "ImportPath": "github.com/minio-io/minio/pkg/api", + "GoVersion": "go1.4", + "Packages": [ + "./..." + ], + "Deps": [ + { + "ImportPath": "github.com/gorilla/context", + "Rev": "50c25fb3b2b3b3cc724e9b6ac75fb44b3bccd0da" + }, + { + "ImportPath": "github.com/gorilla/mux", + "Rev": "e444e69cbd2e2e3e0749a2f3c717cec491552bbf" + }, + { + "ImportPath": "github.com/minio-io/erasure", + "Rev": "3cece1a107115563682604b1430418e28f65dd80" + }, + { + "ImportPath": "github.com/minio-io/iodine", + "Rev": "55cc4d4256c68fbd6f0775f1a25e37e6a2f6457e" + }, + { + "ImportPath": "github.com/stretchr/objx", + "Rev": "cbeaeb16a013161a98496fad62933b1d21786672" + }, + { + "ImportPath": "github.com/stretchr/testify/assert", + "Rev": "e4ec8152c15fc46bd5056ce65997a07c7d415325" + }, + { + "ImportPath": "github.com/stretchr/testify/mock", + "Rev": "e4ec8152c15fc46bd5056ce65997a07c7d415325" + }, + { + "ImportPath": "gopkg.in/check.v1", + "Rev": "64131543e7896d5bcc6bd5a76287eb75ea96c673" + } + ] +} diff --git a/pkg/api/Godeps/Readme b/pkg/api/Godeps/Readme new file mode 100644 index 000000000..4cdaa53d5 --- /dev/null +++ b/pkg/api/Godeps/Readme @@ -0,0 +1,5 @@ +This directory tree is generated automatically by godep. + +Please do not edit. + +See https://github.com/tools/godep for more information. diff --git a/pkg/api/Godeps/_workspace/.gitignore b/pkg/api/Godeps/_workspace/.gitignore new file mode 100644 index 000000000..f037d684e --- /dev/null +++ b/pkg/api/Godeps/_workspace/.gitignore @@ -0,0 +1,2 @@ +/pkg +/bin diff --git a/pkg/api/Godeps/_workspace/src/github.com/gorilla/context/.travis.yml b/pkg/api/Godeps/_workspace/src/github.com/gorilla/context/.travis.yml new file mode 100644 index 000000000..d87d46576 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/gorilla/context/.travis.yml @@ -0,0 +1,7 @@ +language: go + +go: + - 1.0 + - 1.1 + - 1.2 + - tip diff --git a/pkg/api/Godeps/_workspace/src/github.com/gorilla/context/LICENSE b/pkg/api/Godeps/_workspace/src/github.com/gorilla/context/LICENSE new file mode 100644 index 000000000..0e5fb8728 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/gorilla/context/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2012 Rodrigo Moraes. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/pkg/api/Godeps/_workspace/src/github.com/gorilla/context/README.md b/pkg/api/Godeps/_workspace/src/github.com/gorilla/context/README.md new file mode 100644 index 000000000..c60a31b05 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/gorilla/context/README.md @@ -0,0 +1,7 @@ +context +======= +[![Build Status](https://travis-ci.org/gorilla/context.png?branch=master)](https://travis-ci.org/gorilla/context) + +gorilla/context is a general purpose registry for global request variables. + +Read the full documentation here: http://www.gorillatoolkit.org/pkg/context diff --git a/pkg/api/Godeps/_workspace/src/github.com/gorilla/context/context.go b/pkg/api/Godeps/_workspace/src/github.com/gorilla/context/context.go new file mode 100644 index 000000000..81cb128b1 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/gorilla/context/context.go @@ -0,0 +1,143 @@ +// Copyright 2012 The Gorilla Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package context + +import ( + "net/http" + "sync" + "time" +) + +var ( + mutex sync.RWMutex + data = make(map[*http.Request]map[interface{}]interface{}) + datat = make(map[*http.Request]int64) +) + +// Set stores a value for a given key in a given request. +func Set(r *http.Request, key, val interface{}) { + mutex.Lock() + if data[r] == nil { + data[r] = make(map[interface{}]interface{}) + datat[r] = time.Now().Unix() + } + data[r][key] = val + mutex.Unlock() +} + +// Get returns a value stored for a given key in a given request. +func Get(r *http.Request, key interface{}) interface{} { + mutex.RLock() + if ctx := data[r]; ctx != nil { + value := ctx[key] + mutex.RUnlock() + return value + } + mutex.RUnlock() + return nil +} + +// GetOk returns stored value and presence state like multi-value return of map access. +func GetOk(r *http.Request, key interface{}) (interface{}, bool) { + mutex.RLock() + if _, ok := data[r]; ok { + value, ok := data[r][key] + mutex.RUnlock() + return value, ok + } + mutex.RUnlock() + return nil, false +} + +// GetAll returns all stored values for the request as a map. Nil is returned for invalid requests. +func GetAll(r *http.Request) map[interface{}]interface{} { + mutex.RLock() + if context, ok := data[r]; ok { + result := make(map[interface{}]interface{}, len(context)) + for k, v := range context { + result[k] = v + } + mutex.RUnlock() + return result + } + mutex.RUnlock() + return nil +} + +// GetAllOk returns all stored values for the request as a map and a boolean value that indicates if +// the request was registered. +func GetAllOk(r *http.Request) (map[interface{}]interface{}, bool) { + mutex.RLock() + context, ok := data[r] + result := make(map[interface{}]interface{}, len(context)) + for k, v := range context { + result[k] = v + } + mutex.RUnlock() + return result, ok +} + +// Delete removes a value stored for a given key in a given request. +func Delete(r *http.Request, key interface{}) { + mutex.Lock() + if data[r] != nil { + delete(data[r], key) + } + mutex.Unlock() +} + +// Clear removes all values stored for a given request. +// +// This is usually called by a handler wrapper to clean up request +// variables at the end of a request lifetime. See ClearHandler(). +func Clear(r *http.Request) { + mutex.Lock() + clear(r) + mutex.Unlock() +} + +// clear is Clear without the lock. +func clear(r *http.Request) { + delete(data, r) + delete(datat, r) +} + +// Purge removes request data stored for longer than maxAge, in seconds. +// It returns the amount of requests removed. +// +// If maxAge <= 0, all request data is removed. +// +// This is only used for sanity check: in case context cleaning was not +// properly set some request data can be kept forever, consuming an increasing +// amount of memory. In case this is detected, Purge() must be called +// periodically until the problem is fixed. +func Purge(maxAge int) int { + mutex.Lock() + count := 0 + if maxAge <= 0 { + count = len(data) + data = make(map[*http.Request]map[interface{}]interface{}) + datat = make(map[*http.Request]int64) + } else { + min := time.Now().Unix() - int64(maxAge) + for r := range data { + if datat[r] < min { + clear(r) + count++ + } + } + } + mutex.Unlock() + return count +} + +// ClearHandler wraps an http.Handler and clears request values at the end +// of a request lifetime. +func ClearHandler(h http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + defer Clear(r) + h.ServeHTTP(w, r) + }) +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/gorilla/context/context_test.go b/pkg/api/Godeps/_workspace/src/github.com/gorilla/context/context_test.go new file mode 100644 index 000000000..9814c501e --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/gorilla/context/context_test.go @@ -0,0 +1,161 @@ +// Copyright 2012 The Gorilla Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package context + +import ( + "net/http" + "testing" +) + +type keyType int + +const ( + key1 keyType = iota + key2 +) + +func TestContext(t *testing.T) { + assertEqual := func(val interface{}, exp interface{}) { + if val != exp { + t.Errorf("Expected %v, got %v.", exp, val) + } + } + + r, _ := http.NewRequest("GET", "http://localhost:8080/", nil) + emptyR, _ := http.NewRequest("GET", "http://localhost:8080/", nil) + + // Get() + assertEqual(Get(r, key1), nil) + + // Set() + Set(r, key1, "1") + assertEqual(Get(r, key1), "1") + assertEqual(len(data[r]), 1) + + Set(r, key2, "2") + assertEqual(Get(r, key2), "2") + assertEqual(len(data[r]), 2) + + //GetOk + value, ok := GetOk(r, key1) + assertEqual(value, "1") + assertEqual(ok, true) + + value, ok = GetOk(r, "not exists") + assertEqual(value, nil) + assertEqual(ok, false) + + Set(r, "nil value", nil) + value, ok = GetOk(r, "nil value") + assertEqual(value, nil) + assertEqual(ok, true) + + // GetAll() + values := GetAll(r) + assertEqual(len(values), 3) + + // GetAll() for empty request + values = GetAll(emptyR) + if values != nil { + t.Error("GetAll didn't return nil value for invalid request") + } + + // GetAllOk() + values, ok = GetAllOk(r) + assertEqual(len(values), 3) + assertEqual(ok, true) + + // GetAllOk() for empty request + values, ok = GetAllOk(emptyR) + assertEqual(value, nil) + assertEqual(ok, false) + + // Delete() + Delete(r, key1) + assertEqual(Get(r, key1), nil) + assertEqual(len(data[r]), 2) + + Delete(r, key2) + assertEqual(Get(r, key2), nil) + assertEqual(len(data[r]), 1) + + // Clear() + Clear(r) + assertEqual(len(data), 0) +} + +func parallelReader(r *http.Request, key string, iterations int, wait, done chan struct{}) { + <-wait + for i := 0; i < iterations; i++ { + Get(r, key) + } + done <- struct{}{} + +} + +func parallelWriter(r *http.Request, key, value string, iterations int, wait, done chan struct{}) { + <-wait + for i := 0; i < iterations; i++ { + Set(r, key, value) + } + done <- struct{}{} + +} + +func benchmarkMutex(b *testing.B, numReaders, numWriters, iterations int) { + + b.StopTimer() + r, _ := http.NewRequest("GET", "http://localhost:8080/", nil) + done := make(chan struct{}) + b.StartTimer() + + for i := 0; i < b.N; i++ { + wait := make(chan struct{}) + + for i := 0; i < numReaders; i++ { + go parallelReader(r, "test", iterations, wait, done) + } + + for i := 0; i < numWriters; i++ { + go parallelWriter(r, "test", "123", iterations, wait, done) + } + + close(wait) + + for i := 0; i < numReaders+numWriters; i++ { + <-done + } + + } + +} + +func BenchmarkMutexSameReadWrite1(b *testing.B) { + benchmarkMutex(b, 1, 1, 32) +} +func BenchmarkMutexSameReadWrite2(b *testing.B) { + benchmarkMutex(b, 2, 2, 32) +} +func BenchmarkMutexSameReadWrite4(b *testing.B) { + benchmarkMutex(b, 4, 4, 32) +} +func BenchmarkMutex1(b *testing.B) { + benchmarkMutex(b, 2, 8, 32) +} +func BenchmarkMutex2(b *testing.B) { + benchmarkMutex(b, 16, 4, 64) +} +func BenchmarkMutex3(b *testing.B) { + benchmarkMutex(b, 1, 2, 128) +} +func BenchmarkMutex4(b *testing.B) { + benchmarkMutex(b, 128, 32, 256) +} +func BenchmarkMutex5(b *testing.B) { + benchmarkMutex(b, 1024, 2048, 64) +} +func BenchmarkMutex6(b *testing.B) { + benchmarkMutex(b, 2048, 1024, 512) +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/gorilla/context/doc.go b/pkg/api/Godeps/_workspace/src/github.com/gorilla/context/doc.go new file mode 100644 index 000000000..73c740031 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/gorilla/context/doc.go @@ -0,0 +1,82 @@ +// Copyright 2012 The Gorilla Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package context stores values shared during a request lifetime. + +For example, a router can set variables extracted from the URL and later +application handlers can access those values, or it can be used to store +sessions values to be saved at the end of a request. There are several +others common uses. + +The idea was posted by Brad Fitzpatrick to the go-nuts mailing list: + + http://groups.google.com/group/golang-nuts/msg/e2d679d303aa5d53 + +Here's the basic usage: first define the keys that you will need. The key +type is interface{} so a key can be of any type that supports equality. +Here we define a key using a custom int type to avoid name collisions: + + package foo + + import ( + "github.com/gorilla/context" + ) + + type key int + + const MyKey key = 0 + +Then set a variable. Variables are bound to an http.Request object, so you +need a request instance to set a value: + + context.Set(r, MyKey, "bar") + +The application can later access the variable using the same key you provided: + + func MyHandler(w http.ResponseWriter, r *http.Request) { + // val is "bar". + val := context.Get(r, foo.MyKey) + + // returns ("bar", true) + val, ok := context.GetOk(r, foo.MyKey) + // ... + } + +And that's all about the basic usage. We discuss some other ideas below. + +Any type can be stored in the context. To enforce a given type, make the key +private and wrap Get() and Set() to accept and return values of a specific +type: + + type key int + + const mykey key = 0 + + // GetMyKey returns a value for this package from the request values. + func GetMyKey(r *http.Request) SomeType { + if rv := context.Get(r, mykey); rv != nil { + return rv.(SomeType) + } + return nil + } + + // SetMyKey sets a value for this package in the request values. + func SetMyKey(r *http.Request, val SomeType) { + context.Set(r, mykey, val) + } + +Variables must be cleared at the end of a request, to remove all values +that were stored. This can be done in an http.Handler, after a request was +served. Just call Clear() passing the request: + + context.Clear(r) + +...or use ClearHandler(), which conveniently wraps an http.Handler to clear +variables at the end of a request lifetime. + +The Routers from the packages gorilla/mux and gorilla/pat call Clear() +so if you are using either of them you don't need to clear the context manually. +*/ +package context diff --git a/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/.travis.yml b/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/.travis.yml new file mode 100644 index 000000000..d87d46576 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/.travis.yml @@ -0,0 +1,7 @@ +language: go + +go: + - 1.0 + - 1.1 + - 1.2 + - tip diff --git a/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/LICENSE b/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/LICENSE new file mode 100644 index 000000000..0e5fb8728 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2012 Rodrigo Moraes. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/README.md b/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/README.md new file mode 100644 index 000000000..e60301b03 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/README.md @@ -0,0 +1,7 @@ +mux +=== +[![Build Status](https://travis-ci.org/gorilla/mux.png?branch=master)](https://travis-ci.org/gorilla/mux) + +gorilla/mux is a powerful URL router and dispatcher. + +Read the full documentation here: http://www.gorillatoolkit.org/pkg/mux diff --git a/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/bench_test.go b/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/bench_test.go new file mode 100644 index 000000000..c5f97b2b2 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/bench_test.go @@ -0,0 +1,21 @@ +// Copyright 2012 The Gorilla Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mux + +import ( + "net/http" + "testing" +) + +func BenchmarkMux(b *testing.B) { + router := new(Router) + handler := func(w http.ResponseWriter, r *http.Request) {} + router.HandleFunc("/v1/{v1}", handler) + + request, _ := http.NewRequest("GET", "/v1/anything", nil) + for i := 0; i < b.N; i++ { + router.ServeHTTP(nil, request) + } +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/doc.go b/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/doc.go new file mode 100644 index 000000000..b2deed34c --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/doc.go @@ -0,0 +1,199 @@ +// Copyright 2012 The Gorilla Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package gorilla/mux implements a request router and dispatcher. + +The name mux stands for "HTTP request multiplexer". Like the standard +http.ServeMux, mux.Router matches incoming requests against a list of +registered routes and calls a handler for the route that matches the URL +or other conditions. The main features are: + + * Requests can be matched based on URL host, path, path prefix, schemes, + header and query values, HTTP methods or using custom matchers. + * URL hosts and paths can have variables with an optional regular + expression. + * Registered URLs can be built, or "reversed", which helps maintaining + references to resources. + * Routes can be used as subrouters: nested routes are only tested if the + parent route matches. This is useful to define groups of routes that + share common conditions like a host, a path prefix or other repeated + attributes. As a bonus, this optimizes request matching. + * It implements the http.Handler interface so it is compatible with the + standard http.ServeMux. + +Let's start registering a couple of URL paths and handlers: + + func main() { + r := mux.NewRouter() + r.HandleFunc("/", HomeHandler) + r.HandleFunc("/products", ProductsHandler) + r.HandleFunc("/articles", ArticlesHandler) + http.Handle("/", r) + } + +Here we register three routes mapping URL paths to handlers. This is +equivalent to how http.HandleFunc() works: if an incoming request URL matches +one of the paths, the corresponding handler is called passing +(http.ResponseWriter, *http.Request) as parameters. + +Paths can have variables. They are defined using the format {name} or +{name:pattern}. If a regular expression pattern is not defined, the matched +variable will be anything until the next slash. For example: + + r := mux.NewRouter() + r.HandleFunc("/products/{key}", ProductHandler) + r.HandleFunc("/articles/{category}/", ArticlesCategoryHandler) + r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler) + +The names are used to create a map of route variables which can be retrieved +calling mux.Vars(): + + vars := mux.Vars(request) + category := vars["category"] + +And this is all you need to know about the basic usage. More advanced options +are explained below. + +Routes can also be restricted to a domain or subdomain. Just define a host +pattern to be matched. They can also have variables: + + r := mux.NewRouter() + // Only matches if domain is "www.domain.com". + r.Host("www.domain.com") + // Matches a dynamic subdomain. + r.Host("{subdomain:[a-z]+}.domain.com") + +There are several other matchers that can be added. To match path prefixes: + + r.PathPrefix("/products/") + +...or HTTP methods: + + r.Methods("GET", "POST") + +...or URL schemes: + + r.Schemes("https") + +...or header values: + + r.Headers("X-Requested-With", "XMLHttpRequest") + +...or query values: + + r.Queries("key", "value") + +...or to use a custom matcher function: + + r.MatcherFunc(func(r *http.Request, rm *RouteMatch) bool { + return r.ProtoMajor == 0 + }) + +...and finally, it is possible to combine several matchers in a single route: + + r.HandleFunc("/products", ProductsHandler). + Host("www.domain.com"). + Methods("GET"). + Schemes("http") + +Setting the same matching conditions again and again can be boring, so we have +a way to group several routes that share the same requirements. +We call it "subrouting". + +For example, let's say we have several URLs that should only match when the +host is "www.domain.com". Create a route for that host and get a "subrouter" +from it: + + r := mux.NewRouter() + s := r.Host("www.domain.com").Subrouter() + +Then register routes in the subrouter: + + s.HandleFunc("/products/", ProductsHandler) + s.HandleFunc("/products/{key}", ProductHandler) + s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler) + +The three URL paths we registered above will only be tested if the domain is +"www.domain.com", because the subrouter is tested first. This is not +only convenient, but also optimizes request matching. You can create +subrouters combining any attribute matchers accepted by a route. + +Subrouters can be used to create domain or path "namespaces": you define +subrouters in a central place and then parts of the app can register its +paths relatively to a given subrouter. + +There's one more thing about subroutes. When a subrouter has a path prefix, +the inner routes use it as base for their paths: + + r := mux.NewRouter() + s := r.PathPrefix("/products").Subrouter() + // "/products/" + s.HandleFunc("/", ProductsHandler) + // "/products/{key}/" + s.HandleFunc("/{key}/", ProductHandler) + // "/products/{key}/details" + s.HandleFunc("/{key}/details", ProductDetailsHandler) + +Now let's see how to build registered URLs. + +Routes can be named. All routes that define a name can have their URLs built, +or "reversed". We define a name calling Name() on a route. For example: + + r := mux.NewRouter() + r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). + Name("article") + +To build a URL, get the route and call the URL() method, passing a sequence of +key/value pairs for the route variables. For the previous route, we would do: + + url, err := r.Get("article").URL("category", "technology", "id", "42") + +...and the result will be a url.URL with the following path: + + "/articles/technology/42" + +This also works for host variables: + + r := mux.NewRouter() + r.Host("{subdomain}.domain.com"). + Path("/articles/{category}/{id:[0-9]+}"). + HandlerFunc(ArticleHandler). + Name("article") + + // url.String() will be "http://news.domain.com/articles/technology/42" + url, err := r.Get("article").URL("subdomain", "news", + "category", "technology", + "id", "42") + +All variables defined in the route are required, and their values must +conform to the corresponding patterns. These requirements guarantee that a +generated URL will always match a registered route -- the only exception is +for explicitly defined "build-only" routes which never match. + +There's also a way to build only the URL host or path for a route: +use the methods URLHost() or URLPath() instead. For the previous route, +we would do: + + // "http://news.domain.com/" + host, err := r.Get("article").URLHost("subdomain", "news") + + // "/articles/technology/42" + path, err := r.Get("article").URLPath("category", "technology", "id", "42") + +And if you use subrouters, host and path defined separately can be built +as well: + + r := mux.NewRouter() + s := r.Host("{subdomain}.domain.com").Subrouter() + s.Path("/articles/{category}/{id:[0-9]+}"). + HandlerFunc(ArticleHandler). + Name("article") + + // "http://news.domain.com/articles/technology/42" + url, err := r.Get("article").URL("subdomain", "news", + "category", "technology", + "id", "42") +*/ +package mux diff --git a/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/mux.go b/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/mux.go new file mode 100644 index 000000000..5b5f8e7db --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/mux.go @@ -0,0 +1,353 @@ +// Copyright 2012 The Gorilla Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mux + +import ( + "fmt" + "net/http" + "path" + + "github.com/gorilla/context" +) + +// NewRouter returns a new router instance. +func NewRouter() *Router { + return &Router{namedRoutes: make(map[string]*Route), KeepContext: false} +} + +// Router registers routes to be matched and dispatches a handler. +// +// It implements the http.Handler interface, so it can be registered to serve +// requests: +// +// var router = mux.NewRouter() +// +// func main() { +// http.Handle("/", router) +// } +// +// Or, for Google App Engine, register it in a init() function: +// +// func init() { +// http.Handle("/", router) +// } +// +// This will send all incoming requests to the router. +type Router struct { + // Configurable Handler to be used when no route matches. + NotFoundHandler http.Handler + // Parent route, if this is a subrouter. + parent parentRoute + // Routes to be matched, in order. + routes []*Route + // Routes by name for URL building. + namedRoutes map[string]*Route + // See Router.StrictSlash(). This defines the flag for new routes. + strictSlash bool + // If true, do not clear the request context after handling the request + KeepContext bool +} + +// Match matches registered routes against the request. +func (r *Router) Match(req *http.Request, match *RouteMatch) bool { + for _, route := range r.routes { + if route.Match(req, match) { + return true + } + } + return false +} + +// ServeHTTP dispatches the handler registered in the matched route. +// +// When there is a match, the route variables can be retrieved calling +// mux.Vars(request). +func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { + // Clean path to canonical form and redirect. + if p := cleanPath(req.URL.Path); p != req.URL.Path { + + // Added 3 lines (Philip Schlump) - It was droping the query string and #whatever from query. + // This matches with fix in go 1.2 r.c. 4 for same problem. Go Issue: + // http://code.google.com/p/go/issues/detail?id=5252 + url := *req.URL + url.Path = p + p = url.String() + + w.Header().Set("Location", p) + w.WriteHeader(http.StatusMovedPermanently) + return + } + var match RouteMatch + var handler http.Handler + if r.Match(req, &match) { + handler = match.Handler + setVars(req, match.Vars) + setCurrentRoute(req, match.Route) + } + if handler == nil { + handler = r.NotFoundHandler + if handler == nil { + handler = http.NotFoundHandler() + } + } + if !r.KeepContext { + defer context.Clear(req) + } + handler.ServeHTTP(w, req) +} + +// Get returns a route registered with the given name. +func (r *Router) Get(name string) *Route { + return r.getNamedRoutes()[name] +} + +// GetRoute returns a route registered with the given name. This method +// was renamed to Get() and remains here for backwards compatibility. +func (r *Router) GetRoute(name string) *Route { + return r.getNamedRoutes()[name] +} + +// StrictSlash defines the trailing slash behavior for new routes. The initial +// value is false. +// +// When true, if the route path is "/path/", accessing "/path" will redirect +// to the former and vice versa. In other words, your application will always +// see the path as specified in the route. +// +// When false, if the route path is "/path", accessing "/path/" will not match +// this route and vice versa. +// +// Special case: when a route sets a path prefix using the PathPrefix() method, +// strict slash is ignored for that route because the redirect behavior can't +// be determined from a prefix alone. However, any subrouters created from that +// route inherit the original StrictSlash setting. +func (r *Router) StrictSlash(value bool) *Router { + r.strictSlash = value + return r +} + +// ---------------------------------------------------------------------------- +// parentRoute +// ---------------------------------------------------------------------------- + +// getNamedRoutes returns the map where named routes are registered. +func (r *Router) getNamedRoutes() map[string]*Route { + if r.namedRoutes == nil { + if r.parent != nil { + r.namedRoutes = r.parent.getNamedRoutes() + } else { + r.namedRoutes = make(map[string]*Route) + } + } + return r.namedRoutes +} + +// getRegexpGroup returns regexp definitions from the parent route, if any. +func (r *Router) getRegexpGroup() *routeRegexpGroup { + if r.parent != nil { + return r.parent.getRegexpGroup() + } + return nil +} + +// ---------------------------------------------------------------------------- +// Route factories +// ---------------------------------------------------------------------------- + +// NewRoute registers an empty route. +func (r *Router) NewRoute() *Route { + route := &Route{parent: r, strictSlash: r.strictSlash} + r.routes = append(r.routes, route) + return route +} + +// Handle registers a new route with a matcher for the URL path. +// See Route.Path() and Route.Handler(). +func (r *Router) Handle(path string, handler http.Handler) *Route { + return r.NewRoute().Path(path).Handler(handler) +} + +// HandleFunc registers a new route with a matcher for the URL path. +// See Route.Path() and Route.HandlerFunc(). +func (r *Router) HandleFunc(path string, f func(http.ResponseWriter, + *http.Request)) *Route { + return r.NewRoute().Path(path).HandlerFunc(f) +} + +// Headers registers a new route with a matcher for request header values. +// See Route.Headers(). +func (r *Router) Headers(pairs ...string) *Route { + return r.NewRoute().Headers(pairs...) +} + +// Host registers a new route with a matcher for the URL host. +// See Route.Host(). +func (r *Router) Host(tpl string) *Route { + return r.NewRoute().Host(tpl) +} + +// MatcherFunc registers a new route with a custom matcher function. +// See Route.MatcherFunc(). +func (r *Router) MatcherFunc(f MatcherFunc) *Route { + return r.NewRoute().MatcherFunc(f) +} + +// Methods registers a new route with a matcher for HTTP methods. +// See Route.Methods(). +func (r *Router) Methods(methods ...string) *Route { + return r.NewRoute().Methods(methods...) +} + +// Path registers a new route with a matcher for the URL path. +// See Route.Path(). +func (r *Router) Path(tpl string) *Route { + return r.NewRoute().Path(tpl) +} + +// PathPrefix registers a new route with a matcher for the URL path prefix. +// See Route.PathPrefix(). +func (r *Router) PathPrefix(tpl string) *Route { + return r.NewRoute().PathPrefix(tpl) +} + +// Queries registers a new route with a matcher for URL query values. +// See Route.Queries(). +func (r *Router) Queries(pairs ...string) *Route { + return r.NewRoute().Queries(pairs...) +} + +// Schemes registers a new route with a matcher for URL schemes. +// See Route.Schemes(). +func (r *Router) Schemes(schemes ...string) *Route { + return r.NewRoute().Schemes(schemes...) +} + +// ---------------------------------------------------------------------------- +// Context +// ---------------------------------------------------------------------------- + +// RouteMatch stores information about a matched route. +type RouteMatch struct { + Route *Route + Handler http.Handler + Vars map[string]string +} + +type contextKey int + +const ( + varsKey contextKey = iota + routeKey +) + +// Vars returns the route variables for the current request, if any. +func Vars(r *http.Request) map[string]string { + if rv := context.Get(r, varsKey); rv != nil { + return rv.(map[string]string) + } + return nil +} + +// CurrentRoute returns the matched route for the current request, if any. +func CurrentRoute(r *http.Request) *Route { + if rv := context.Get(r, routeKey); rv != nil { + return rv.(*Route) + } + return nil +} + +func setVars(r *http.Request, val interface{}) { + context.Set(r, varsKey, val) +} + +func setCurrentRoute(r *http.Request, val interface{}) { + context.Set(r, routeKey, val) +} + +// ---------------------------------------------------------------------------- +// Helpers +// ---------------------------------------------------------------------------- + +// cleanPath returns the canonical path for p, eliminating . and .. elements. +// Borrowed from the net/http package. +func cleanPath(p string) string { + if p == "" { + return "/" + } + if p[0] != '/' { + p = "/" + p + } + np := path.Clean(p) + // path.Clean removes trailing slash except for root; + // put the trailing slash back if necessary. + if p[len(p)-1] == '/' && np != "/" { + np += "/" + } + return np +} + +// uniqueVars returns an error if two slices contain duplicated strings. +func uniqueVars(s1, s2 []string) error { + for _, v1 := range s1 { + for _, v2 := range s2 { + if v1 == v2 { + return fmt.Errorf("mux: duplicated route variable %q", v2) + } + } + } + return nil +} + +// mapFromPairs converts variadic string parameters to a string map. +func mapFromPairs(pairs ...string) (map[string]string, error) { + length := len(pairs) + if length%2 != 0 { + return nil, fmt.Errorf( + "mux: number of parameters must be multiple of 2, got %v", pairs) + } + m := make(map[string]string, length/2) + for i := 0; i < length; i += 2 { + m[pairs[i]] = pairs[i+1] + } + return m, nil +} + +// matchInArray returns true if the given string value is in the array. +func matchInArray(arr []string, value string) bool { + for _, v := range arr { + if v == value { + return true + } + } + return false +} + +// matchMap returns true if the given key/value pairs exist in a given map. +func matchMap(toCheck map[string]string, toMatch map[string][]string, + canonicalKey bool) bool { + for k, v := range toCheck { + // Check if key exists. + if canonicalKey { + k = http.CanonicalHeaderKey(k) + } + if values := toMatch[k]; values == nil { + return false + } else if v != "" { + // If value was defined as an empty string we only check that the + // key exists. Otherwise we also check for equality. + valueExists := false + for _, value := range values { + if v == value { + valueExists = true + break + } + } + if !valueExists { + return false + } + } + } + return true +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/mux_test.go b/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/mux_test.go new file mode 100644 index 000000000..e455bce8f --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/mux_test.go @@ -0,0 +1,943 @@ +// Copyright 2012 The Gorilla Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mux + +import ( + "fmt" + "net/http" + "testing" + + "github.com/gorilla/context" +) + +type routeTest struct { + title string // title of the test + route *Route // the route being tested + request *http.Request // a request to test the route + vars map[string]string // the expected vars of the match + host string // the expected host of the match + path string // the expected path of the match + shouldMatch bool // whether the request is expected to match the route at all + shouldRedirect bool // whether the request should result in a redirect +} + +func TestHost(t *testing.T) { + // newRequestHost a new request with a method, url, and host header + newRequestHost := func(method, url, host string) *http.Request { + req, err := http.NewRequest(method, url, nil) + if err != nil { + panic(err) + } + req.Host = host + return req + } + + tests := []routeTest{ + { + title: "Host route match", + route: new(Route).Host("aaa.bbb.ccc"), + request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), + vars: map[string]string{}, + host: "aaa.bbb.ccc", + path: "", + shouldMatch: true, + }, + { + title: "Host route, wrong host in request URL", + route: new(Route).Host("aaa.bbb.ccc"), + request: newRequest("GET", "http://aaa.222.ccc/111/222/333"), + vars: map[string]string{}, + host: "aaa.bbb.ccc", + path: "", + shouldMatch: false, + }, + { + title: "Host route with port, match", + route: new(Route).Host("aaa.bbb.ccc:1234"), + request: newRequest("GET", "http://aaa.bbb.ccc:1234/111/222/333"), + vars: map[string]string{}, + host: "aaa.bbb.ccc:1234", + path: "", + shouldMatch: true, + }, + { + title: "Host route with port, wrong port in request URL", + route: new(Route).Host("aaa.bbb.ccc:1234"), + request: newRequest("GET", "http://aaa.bbb.ccc:9999/111/222/333"), + vars: map[string]string{}, + host: "aaa.bbb.ccc:1234", + path: "", + shouldMatch: false, + }, + { + title: "Host route, match with host in request header", + route: new(Route).Host("aaa.bbb.ccc"), + request: newRequestHost("GET", "/111/222/333", "aaa.bbb.ccc"), + vars: map[string]string{}, + host: "aaa.bbb.ccc", + path: "", + shouldMatch: true, + }, + { + title: "Host route, wrong host in request header", + route: new(Route).Host("aaa.bbb.ccc"), + request: newRequestHost("GET", "/111/222/333", "aaa.222.ccc"), + vars: map[string]string{}, + host: "aaa.bbb.ccc", + path: "", + shouldMatch: false, + }, + // BUG {new(Route).Host("aaa.bbb.ccc:1234"), newRequestHost("GET", "/111/222/333", "aaa.bbb.ccc:1234"), map[string]string{}, "aaa.bbb.ccc:1234", "", true}, + { + title: "Host route with port, wrong host in request header", + route: new(Route).Host("aaa.bbb.ccc:1234"), + request: newRequestHost("GET", "/111/222/333", "aaa.bbb.ccc:9999"), + vars: map[string]string{}, + host: "aaa.bbb.ccc:1234", + path: "", + shouldMatch: false, + }, + { + title: "Host route with pattern, match", + route: new(Route).Host("aaa.{v1:[a-z]{3}}.ccc"), + request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), + vars: map[string]string{"v1": "bbb"}, + host: "aaa.bbb.ccc", + path: "", + shouldMatch: true, + }, + { + title: "Host route with pattern, wrong host in request URL", + route: new(Route).Host("aaa.{v1:[a-z]{3}}.ccc"), + request: newRequest("GET", "http://aaa.222.ccc/111/222/333"), + vars: map[string]string{"v1": "bbb"}, + host: "aaa.bbb.ccc", + path: "", + shouldMatch: false, + }, + { + title: "Host route with multiple patterns, match", + route: new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}"), + request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), + vars: map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc"}, + host: "aaa.bbb.ccc", + path: "", + shouldMatch: true, + }, + { + title: "Host route with multiple patterns, wrong host in request URL", + route: new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}"), + request: newRequest("GET", "http://aaa.222.ccc/111/222/333"), + vars: map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc"}, + host: "aaa.bbb.ccc", + path: "", + shouldMatch: false, + }, + } + for _, test := range tests { + testRoute(t, test) + } +} + +func TestPath(t *testing.T) { + tests := []routeTest{ + { + title: "Path route, match", + route: new(Route).Path("/111/222/333"), + request: newRequest("GET", "http://localhost/111/222/333"), + vars: map[string]string{}, + host: "", + path: "/111/222/333", + shouldMatch: true, + }, + { + title: "Path route, match with trailing slash in request and path", + route: new(Route).Path("/111/"), + request: newRequest("GET", "http://localhost/111/"), + vars: map[string]string{}, + host: "", + path: "/111/", + shouldMatch: true, + }, + { + title: "Path route, do not match with trailing slash in path", + route: new(Route).Path("/111/"), + request: newRequest("GET", "http://localhost/111"), + vars: map[string]string{}, + host: "", + path: "/111", + shouldMatch: false, + }, + { + title: "Path route, do not match with trailing slash in request", + route: new(Route).Path("/111"), + request: newRequest("GET", "http://localhost/111/"), + vars: map[string]string{}, + host: "", + path: "/111/", + shouldMatch: false, + }, + { + title: "Path route, wrong path in request in request URL", + route: new(Route).Path("/111/222/333"), + request: newRequest("GET", "http://localhost/1/2/3"), + vars: map[string]string{}, + host: "", + path: "/111/222/333", + shouldMatch: false, + }, + { + title: "Path route with pattern, match", + route: new(Route).Path("/111/{v1:[0-9]{3}}/333"), + request: newRequest("GET", "http://localhost/111/222/333"), + vars: map[string]string{"v1": "222"}, + host: "", + path: "/111/222/333", + shouldMatch: true, + }, + { + title: "Path route with pattern, URL in request does not match", + route: new(Route).Path("/111/{v1:[0-9]{3}}/333"), + request: newRequest("GET", "http://localhost/111/aaa/333"), + vars: map[string]string{"v1": "222"}, + host: "", + path: "/111/222/333", + shouldMatch: false, + }, + { + title: "Path route with multiple patterns, match", + route: new(Route).Path("/{v1:[0-9]{3}}/{v2:[0-9]{3}}/{v3:[0-9]{3}}"), + request: newRequest("GET", "http://localhost/111/222/333"), + vars: map[string]string{"v1": "111", "v2": "222", "v3": "333"}, + host: "", + path: "/111/222/333", + shouldMatch: true, + }, + { + title: "Path route with multiple patterns, URL in request does not match", + route: new(Route).Path("/{v1:[0-9]{3}}/{v2:[0-9]{3}}/{v3:[0-9]{3}}"), + request: newRequest("GET", "http://localhost/111/aaa/333"), + vars: map[string]string{"v1": "111", "v2": "222", "v3": "333"}, + host: "", + path: "/111/222/333", + shouldMatch: false, + }, + } + + for _, test := range tests { + testRoute(t, test) + } +} + +func TestPathPrefix(t *testing.T) { + tests := []routeTest{ + { + title: "PathPrefix route, match", + route: new(Route).PathPrefix("/111"), + request: newRequest("GET", "http://localhost/111/222/333"), + vars: map[string]string{}, + host: "", + path: "/111", + shouldMatch: true, + }, + { + title: "PathPrefix route, match substring", + route: new(Route).PathPrefix("/1"), + request: newRequest("GET", "http://localhost/111/222/333"), + vars: map[string]string{}, + host: "", + path: "/1", + shouldMatch: true, + }, + { + title: "PathPrefix route, URL prefix in request does not match", + route: new(Route).PathPrefix("/111"), + request: newRequest("GET", "http://localhost/1/2/3"), + vars: map[string]string{}, + host: "", + path: "/111", + shouldMatch: false, + }, + { + title: "PathPrefix route with pattern, match", + route: new(Route).PathPrefix("/111/{v1:[0-9]{3}}"), + request: newRequest("GET", "http://localhost/111/222/333"), + vars: map[string]string{"v1": "222"}, + host: "", + path: "/111/222", + shouldMatch: true, + }, + { + title: "PathPrefix route with pattern, URL prefix in request does not match", + route: new(Route).PathPrefix("/111/{v1:[0-9]{3}}"), + request: newRequest("GET", "http://localhost/111/aaa/333"), + vars: map[string]string{"v1": "222"}, + host: "", + path: "/111/222", + shouldMatch: false, + }, + { + title: "PathPrefix route with multiple patterns, match", + route: new(Route).PathPrefix("/{v1:[0-9]{3}}/{v2:[0-9]{3}}"), + request: newRequest("GET", "http://localhost/111/222/333"), + vars: map[string]string{"v1": "111", "v2": "222"}, + host: "", + path: "/111/222", + shouldMatch: true, + }, + { + title: "PathPrefix route with multiple patterns, URL prefix in request does not match", + route: new(Route).PathPrefix("/{v1:[0-9]{3}}/{v2:[0-9]{3}}"), + request: newRequest("GET", "http://localhost/111/aaa/333"), + vars: map[string]string{"v1": "111", "v2": "222"}, + host: "", + path: "/111/222", + shouldMatch: false, + }, + } + + for _, test := range tests { + testRoute(t, test) + } +} + +func TestHostPath(t *testing.T) { + tests := []routeTest{ + { + title: "Host and Path route, match", + route: new(Route).Host("aaa.bbb.ccc").Path("/111/222/333"), + request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), + vars: map[string]string{}, + host: "", + path: "", + shouldMatch: true, + }, + { + title: "Host and Path route, wrong host in request URL", + route: new(Route).Host("aaa.bbb.ccc").Path("/111/222/333"), + request: newRequest("GET", "http://aaa.222.ccc/111/222/333"), + vars: map[string]string{}, + host: "", + path: "", + shouldMatch: false, + }, + { + title: "Host and Path route with pattern, match", + route: new(Route).Host("aaa.{v1:[a-z]{3}}.ccc").Path("/111/{v2:[0-9]{3}}/333"), + request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), + vars: map[string]string{"v1": "bbb", "v2": "222"}, + host: "aaa.bbb.ccc", + path: "/111/222/333", + shouldMatch: true, + }, + { + title: "Host and Path route with pattern, URL in request does not match", + route: new(Route).Host("aaa.{v1:[a-z]{3}}.ccc").Path("/111/{v2:[0-9]{3}}/333"), + request: newRequest("GET", "http://aaa.222.ccc/111/222/333"), + vars: map[string]string{"v1": "bbb", "v2": "222"}, + host: "aaa.bbb.ccc", + path: "/111/222/333", + shouldMatch: false, + }, + { + title: "Host and Path route with multiple patterns, match", + route: new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}").Path("/{v4:[0-9]{3}}/{v5:[0-9]{3}}/{v6:[0-9]{3}}"), + request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"), + vars: map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc", "v4": "111", "v5": "222", "v6": "333"}, + host: "aaa.bbb.ccc", + path: "/111/222/333", + shouldMatch: true, + }, + { + title: "Host and Path route with multiple patterns, URL in request does not match", + route: new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}").Path("/{v4:[0-9]{3}}/{v5:[0-9]{3}}/{v6:[0-9]{3}}"), + request: newRequest("GET", "http://aaa.222.ccc/111/222/333"), + vars: map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc", "v4": "111", "v5": "222", "v6": "333"}, + host: "aaa.bbb.ccc", + path: "/111/222/333", + shouldMatch: false, + }, + } + + for _, test := range tests { + testRoute(t, test) + } +} + +func TestHeaders(t *testing.T) { + // newRequestHeaders creates a new request with a method, url, and headers + newRequestHeaders := func(method, url string, headers map[string]string) *http.Request { + req, err := http.NewRequest(method, url, nil) + if err != nil { + panic(err) + } + for k, v := range headers { + req.Header.Add(k, v) + } + return req + } + + tests := []routeTest{ + { + title: "Headers route, match", + route: new(Route).Headers("foo", "bar", "baz", "ding"), + request: newRequestHeaders("GET", "http://localhost", map[string]string{"foo": "bar", "baz": "ding"}), + vars: map[string]string{}, + host: "", + path: "", + shouldMatch: true, + }, + { + title: "Headers route, bad header values", + route: new(Route).Headers("foo", "bar", "baz", "ding"), + request: newRequestHeaders("GET", "http://localhost", map[string]string{"foo": "bar", "baz": "dong"}), + vars: map[string]string{}, + host: "", + path: "", + shouldMatch: false, + }, + } + + for _, test := range tests { + testRoute(t, test) + } + +} + +func TestMethods(t *testing.T) { + tests := []routeTest{ + { + title: "Methods route, match GET", + route: new(Route).Methods("GET", "POST"), + request: newRequest("GET", "http://localhost"), + vars: map[string]string{}, + host: "", + path: "", + shouldMatch: true, + }, + { + title: "Methods route, match POST", + route: new(Route).Methods("GET", "POST"), + request: newRequest("POST", "http://localhost"), + vars: map[string]string{}, + host: "", + path: "", + shouldMatch: true, + }, + { + title: "Methods route, bad method", + route: new(Route).Methods("GET", "POST"), + request: newRequest("PUT", "http://localhost"), + vars: map[string]string{}, + host: "", + path: "", + shouldMatch: false, + }, + } + + for _, test := range tests { + testRoute(t, test) + } +} + +func TestQueries(t *testing.T) { + tests := []routeTest{ + { + title: "Queries route, match", + route: new(Route).Queries("foo", "bar", "baz", "ding"), + request: newRequest("GET", "http://localhost?foo=bar&baz=ding"), + vars: map[string]string{}, + host: "", + path: "", + shouldMatch: true, + }, + { + title: "Queries route, match with a query string", + route: new(Route).Host("www.example.com").Path("/api").Queries("foo", "bar", "baz", "ding"), + request: newRequest("GET", "http://www.example.com/api?foo=bar&baz=ding"), + vars: map[string]string{}, + host: "", + path: "", + shouldMatch: true, + }, + { + title: "Queries route, match with a query string out of order", + route: new(Route).Host("www.example.com").Path("/api").Queries("foo", "bar", "baz", "ding"), + request: newRequest("GET", "http://www.example.com/api?baz=ding&foo=bar"), + vars: map[string]string{}, + host: "", + path: "", + shouldMatch: true, + }, + { + title: "Queries route, bad query", + route: new(Route).Queries("foo", "bar", "baz", "ding"), + request: newRequest("GET", "http://localhost?foo=bar&baz=dong"), + vars: map[string]string{}, + host: "", + path: "", + shouldMatch: false, + }, + { + title: "Queries route with pattern, match", + route: new(Route).Queries("foo", "{v1}"), + request: newRequest("GET", "http://localhost?foo=bar"), + vars: map[string]string{"v1": "bar"}, + host: "", + path: "", + shouldMatch: true, + }, + { + title: "Queries route with multiple patterns, match", + route: new(Route).Queries("foo", "{v1}", "baz", "{v2}"), + request: newRequest("GET", "http://localhost?foo=bar&baz=ding"), + vars: map[string]string{"v1": "bar", "v2": "ding"}, + host: "", + path: "", + shouldMatch: true, + }, + { + title: "Queries route with regexp pattern, match", + route: new(Route).Queries("foo", "{v1:[0-9]+}"), + request: newRequest("GET", "http://localhost?foo=10"), + vars: map[string]string{"v1": "10"}, + host: "", + path: "", + shouldMatch: true, + }, + { + title: "Queries route with regexp pattern, regexp does not match", + route: new(Route).Queries("foo", "{v1:[0-9]+}"), + request: newRequest("GET", "http://localhost?foo=a"), + vars: map[string]string{}, + host: "", + path: "", + shouldMatch: false, + }, + } + + for _, test := range tests { + testRoute(t, test) + } +} + +func TestSchemes(t *testing.T) { + tests := []routeTest{ + // Schemes + { + title: "Schemes route, match https", + route: new(Route).Schemes("https", "ftp"), + request: newRequest("GET", "https://localhost"), + vars: map[string]string{}, + host: "", + path: "", + shouldMatch: true, + }, + { + title: "Schemes route, match ftp", + route: new(Route).Schemes("https", "ftp"), + request: newRequest("GET", "ftp://localhost"), + vars: map[string]string{}, + host: "", + path: "", + shouldMatch: true, + }, + { + title: "Schemes route, bad scheme", + route: new(Route).Schemes("https", "ftp"), + request: newRequest("GET", "http://localhost"), + vars: map[string]string{}, + host: "", + path: "", + shouldMatch: false, + }, + } + for _, test := range tests { + testRoute(t, test) + } +} + +func TestMatcherFunc(t *testing.T) { + m := func(r *http.Request, m *RouteMatch) bool { + if r.URL.Host == "aaa.bbb.ccc" { + return true + } + return false + } + + tests := []routeTest{ + { + title: "MatchFunc route, match", + route: new(Route).MatcherFunc(m), + request: newRequest("GET", "http://aaa.bbb.ccc"), + vars: map[string]string{}, + host: "", + path: "", + shouldMatch: true, + }, + { + title: "MatchFunc route, non-match", + route: new(Route).MatcherFunc(m), + request: newRequest("GET", "http://aaa.222.ccc"), + vars: map[string]string{}, + host: "", + path: "", + shouldMatch: false, + }, + } + + for _, test := range tests { + testRoute(t, test) + } +} + +func TestSubRouter(t *testing.T) { + subrouter1 := new(Route).Host("{v1:[a-z]+}.google.com").Subrouter() + subrouter2 := new(Route).PathPrefix("/foo/{v1}").Subrouter() + + tests := []routeTest{ + { + route: subrouter1.Path("/{v2:[a-z]+}"), + request: newRequest("GET", "http://aaa.google.com/bbb"), + vars: map[string]string{"v1": "aaa", "v2": "bbb"}, + host: "aaa.google.com", + path: "/bbb", + shouldMatch: true, + }, + { + route: subrouter1.Path("/{v2:[a-z]+}"), + request: newRequest("GET", "http://111.google.com/111"), + vars: map[string]string{"v1": "aaa", "v2": "bbb"}, + host: "aaa.google.com", + path: "/bbb", + shouldMatch: false, + }, + { + route: subrouter2.Path("/baz/{v2}"), + request: newRequest("GET", "http://localhost/foo/bar/baz/ding"), + vars: map[string]string{"v1": "bar", "v2": "ding"}, + host: "", + path: "/foo/bar/baz/ding", + shouldMatch: true, + }, + { + route: subrouter2.Path("/baz/{v2}"), + request: newRequest("GET", "http://localhost/foo/bar"), + vars: map[string]string{"v1": "bar", "v2": "ding"}, + host: "", + path: "/foo/bar/baz/ding", + shouldMatch: false, + }, + } + + for _, test := range tests { + testRoute(t, test) + } +} + +func TestNamedRoutes(t *testing.T) { + r1 := NewRouter() + r1.NewRoute().Name("a") + r1.NewRoute().Name("b") + r1.NewRoute().Name("c") + + r2 := r1.NewRoute().Subrouter() + r2.NewRoute().Name("d") + r2.NewRoute().Name("e") + r2.NewRoute().Name("f") + + r3 := r2.NewRoute().Subrouter() + r3.NewRoute().Name("g") + r3.NewRoute().Name("h") + r3.NewRoute().Name("i") + + if r1.namedRoutes == nil || len(r1.namedRoutes) != 9 { + t.Errorf("Expected 9 named routes, got %v", r1.namedRoutes) + } else if r1.Get("i") == nil { + t.Errorf("Subroute name not registered") + } +} + +func TestStrictSlash(t *testing.T) { + r := NewRouter() + r.StrictSlash(true) + + tests := []routeTest{ + { + title: "Redirect path without slash", + route: r.NewRoute().Path("/111/"), + request: newRequest("GET", "http://localhost/111"), + vars: map[string]string{}, + host: "", + path: "/111/", + shouldMatch: true, + shouldRedirect: true, + }, + { + title: "Do not redirect path with slash", + route: r.NewRoute().Path("/111/"), + request: newRequest("GET", "http://localhost/111/"), + vars: map[string]string{}, + host: "", + path: "/111/", + shouldMatch: true, + shouldRedirect: false, + }, + { + title: "Redirect path with slash", + route: r.NewRoute().Path("/111"), + request: newRequest("GET", "http://localhost/111/"), + vars: map[string]string{}, + host: "", + path: "/111", + shouldMatch: true, + shouldRedirect: true, + }, + { + title: "Do not redirect path without slash", + route: r.NewRoute().Path("/111"), + request: newRequest("GET", "http://localhost/111"), + vars: map[string]string{}, + host: "", + path: "/111", + shouldMatch: true, + shouldRedirect: false, + }, + { + title: "Propagate StrictSlash to subrouters", + route: r.NewRoute().PathPrefix("/static/").Subrouter().Path("/images/"), + request: newRequest("GET", "http://localhost/static/images"), + vars: map[string]string{}, + host: "", + path: "/static/images/", + shouldMatch: true, + shouldRedirect: true, + }, + { + title: "Ignore StrictSlash for path prefix", + route: r.NewRoute().PathPrefix("/static/"), + request: newRequest("GET", "http://localhost/static/logo.png"), + vars: map[string]string{}, + host: "", + path: "/static/", + shouldMatch: true, + shouldRedirect: false, + }, + } + + for _, test := range tests { + testRoute(t, test) + } +} + +// ---------------------------------------------------------------------------- +// Helpers +// ---------------------------------------------------------------------------- + +func getRouteTemplate(route *Route) string { + host, path := "none", "none" + if route.regexp != nil { + if route.regexp.host != nil { + host = route.regexp.host.template + } + if route.regexp.path != nil { + path = route.regexp.path.template + } + } + return fmt.Sprintf("Host: %v, Path: %v", host, path) +} + +func testRoute(t *testing.T, test routeTest) { + request := test.request + route := test.route + vars := test.vars + shouldMatch := test.shouldMatch + host := test.host + path := test.path + url := test.host + test.path + shouldRedirect := test.shouldRedirect + + var match RouteMatch + ok := route.Match(request, &match) + if ok != shouldMatch { + msg := "Should match" + if !shouldMatch { + msg = "Should not match" + } + t.Errorf("(%v) %v:\nRoute: %#v\nRequest: %#v\nVars: %v\n", test.title, msg, route, request, vars) + return + } + if shouldMatch { + if test.vars != nil && !stringMapEqual(test.vars, match.Vars) { + t.Errorf("(%v) Vars not equal: expected %v, got %v", test.title, vars, match.Vars) + return + } + if host != "" { + u, _ := test.route.URLHost(mapToPairs(match.Vars)...) + if host != u.Host { + t.Errorf("(%v) URLHost not equal: expected %v, got %v -- %v", test.title, host, u.Host, getRouteTemplate(route)) + return + } + } + if path != "" { + u, _ := route.URLPath(mapToPairs(match.Vars)...) + if path != u.Path { + t.Errorf("(%v) URLPath not equal: expected %v, got %v -- %v", test.title, path, u.Path, getRouteTemplate(route)) + return + } + } + if url != "" { + u, _ := route.URL(mapToPairs(match.Vars)...) + if url != u.Host+u.Path { + t.Errorf("(%v) URL not equal: expected %v, got %v -- %v", test.title, url, u.Host+u.Path, getRouteTemplate(route)) + return + } + } + if shouldRedirect && match.Handler == nil { + t.Errorf("(%v) Did not redirect", test.title) + return + } + if !shouldRedirect && match.Handler != nil { + t.Errorf("(%v) Unexpected redirect", test.title) + return + } + } +} + +// Tests that the context is cleared or not cleared properly depending on +// the configuration of the router +func TestKeepContext(t *testing.T) { + func1 := func(w http.ResponseWriter, r *http.Request) {} + + r := NewRouter() + r.HandleFunc("/", func1).Name("func1") + + req, _ := http.NewRequest("GET", "http://localhost/", nil) + context.Set(req, "t", 1) + + res := new(http.ResponseWriter) + r.ServeHTTP(*res, req) + + if _, ok := context.GetOk(req, "t"); ok { + t.Error("Context should have been cleared at end of request") + } + + r.KeepContext = true + + req, _ = http.NewRequest("GET", "http://localhost/", nil) + context.Set(req, "t", 1) + + r.ServeHTTP(*res, req) + if _, ok := context.GetOk(req, "t"); !ok { + t.Error("Context should NOT have been cleared at end of request") + } + +} + +type TestA301ResponseWriter struct { + hh http.Header + status int +} + +func (ho TestA301ResponseWriter) Header() http.Header { + return http.Header(ho.hh) +} + +func (ho TestA301ResponseWriter) Write(b []byte) (int, error) { + return 0, nil +} + +func (ho TestA301ResponseWriter) WriteHeader(code int) { + ho.status = code +} + +func Test301Redirect(t *testing.T) { + m := make(http.Header) + + func1 := func(w http.ResponseWriter, r *http.Request) {} + func2 := func(w http.ResponseWriter, r *http.Request) {} + + r := NewRouter() + r.HandleFunc("/api/", func2).Name("func2") + r.HandleFunc("/", func1).Name("func1") + + req, _ := http.NewRequest("GET", "http://localhost//api/?abc=def", nil) + + res := TestA301ResponseWriter{ + hh: m, + status: 0, + } + r.ServeHTTP(&res, req) + + if "http://localhost/api/?abc=def" != res.hh["Location"][0] { + t.Errorf("Should have complete URL with query string") + } +} + +// https://plus.google.com/101022900381697718949/posts/eWy6DjFJ6uW +func TestSubrouterHeader(t *testing.T) { + expected := "func1 response" + func1 := func(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, expected) + } + func2 := func(http.ResponseWriter, *http.Request) {} + + r := NewRouter() + s := r.Headers("SomeSpecialHeader", "").Subrouter() + s.HandleFunc("/", func1).Name("func1") + r.HandleFunc("/", func2).Name("func2") + + req, _ := http.NewRequest("GET", "http://localhost/", nil) + req.Header.Add("SomeSpecialHeader", "foo") + match := new(RouteMatch) + matched := r.Match(req, match) + if !matched { + t.Errorf("Should match request") + } + if match.Route.GetName() != "func1" { + t.Errorf("Expecting func1 handler, got %s", match.Route.GetName()) + } + resp := NewRecorder() + match.Handler.ServeHTTP(resp, req) + if resp.Body.String() != expected { + t.Errorf("Expecting %q", expected) + } +} + +// mapToPairs converts a string map to a slice of string pairs +func mapToPairs(m map[string]string) []string { + var i int + p := make([]string, len(m)*2) + for k, v := range m { + p[i] = k + p[i+1] = v + i += 2 + } + return p +} + +// stringMapEqual checks the equality of two string maps +func stringMapEqual(m1, m2 map[string]string) bool { + nil1 := m1 == nil + nil2 := m2 == nil + if nil1 != nil2 || len(m1) != len(m2) { + return false + } + for k, v := range m1 { + if v != m2[k] { + return false + } + } + return true +} + +// newRequest is a helper function to create a new request with a method and url +func newRequest(method, url string) *http.Request { + req, err := http.NewRequest(method, url, nil) + if err != nil { + panic(err) + } + return req +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/old_test.go b/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/old_test.go new file mode 100644 index 000000000..1f7c190c0 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/old_test.go @@ -0,0 +1,714 @@ +// Old tests ported to Go1. This is a mess. Want to drop it one day. + +// Copyright 2011 Gorilla Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mux + +import ( + "bytes" + "net/http" + "testing" +) + +// ---------------------------------------------------------------------------- +// ResponseRecorder +// ---------------------------------------------------------------------------- +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// ResponseRecorder is an implementation of http.ResponseWriter that +// records its mutations for later inspection in tests. +type ResponseRecorder struct { + Code int // the HTTP response code from WriteHeader + HeaderMap http.Header // the HTTP response headers + Body *bytes.Buffer // if non-nil, the bytes.Buffer to append written data to + Flushed bool +} + +// NewRecorder returns an initialized ResponseRecorder. +func NewRecorder() *ResponseRecorder { + return &ResponseRecorder{ + HeaderMap: make(http.Header), + Body: new(bytes.Buffer), + } +} + +// DefaultRemoteAddr is the default remote address to return in RemoteAddr if +// an explicit DefaultRemoteAddr isn't set on ResponseRecorder. +const DefaultRemoteAddr = "1.2.3.4" + +// Header returns the response headers. +func (rw *ResponseRecorder) Header() http.Header { + return rw.HeaderMap +} + +// Write always succeeds and writes to rw.Body, if not nil. +func (rw *ResponseRecorder) Write(buf []byte) (int, error) { + if rw.Body != nil { + rw.Body.Write(buf) + } + if rw.Code == 0 { + rw.Code = http.StatusOK + } + return len(buf), nil +} + +// WriteHeader sets rw.Code. +func (rw *ResponseRecorder) WriteHeader(code int) { + rw.Code = code +} + +// Flush sets rw.Flushed to true. +func (rw *ResponseRecorder) Flush() { + rw.Flushed = true +} + +// ---------------------------------------------------------------------------- + +func TestRouteMatchers(t *testing.T) { + var scheme, host, path, query, method string + var headers map[string]string + var resultVars map[bool]map[string]string + + router := NewRouter() + router.NewRoute().Host("{var1}.google.com"). + Path("/{var2:[a-z]+}/{var3:[0-9]+}"). + Queries("foo", "bar"). + Methods("GET"). + Schemes("https"). + Headers("x-requested-with", "XMLHttpRequest") + router.NewRoute().Host("www.{var4}.com"). + PathPrefix("/foo/{var5:[a-z]+}/{var6:[0-9]+}"). + Queries("baz", "ding"). + Methods("POST"). + Schemes("http"). + Headers("Content-Type", "application/json") + + reset := func() { + // Everything match. + scheme = "https" + host = "www.google.com" + path = "/product/42" + query = "?foo=bar" + method = "GET" + headers = map[string]string{"X-Requested-With": "XMLHttpRequest"} + resultVars = map[bool]map[string]string{ + true: {"var1": "www", "var2": "product", "var3": "42"}, + false: {}, + } + } + + reset2 := func() { + // Everything match. + scheme = "http" + host = "www.google.com" + path = "/foo/product/42/path/that/is/ignored" + query = "?baz=ding" + method = "POST" + headers = map[string]string{"Content-Type": "application/json"} + resultVars = map[bool]map[string]string{ + true: {"var4": "google", "var5": "product", "var6": "42"}, + false: {}, + } + } + + match := func(shouldMatch bool) { + url := scheme + "://" + host + path + query + request, _ := http.NewRequest(method, url, nil) + for key, value := range headers { + request.Header.Add(key, value) + } + + var routeMatch RouteMatch + matched := router.Match(request, &routeMatch) + if matched != shouldMatch { + // Need better messages. :) + if matched { + t.Errorf("Should match.") + } else { + t.Errorf("Should not match.") + } + } + + if matched { + currentRoute := routeMatch.Route + if currentRoute == nil { + t.Errorf("Expected a current route.") + } + vars := routeMatch.Vars + expectedVars := resultVars[shouldMatch] + if len(vars) != len(expectedVars) { + t.Errorf("Expected vars: %v Got: %v.", expectedVars, vars) + } + for name, value := range vars { + if expectedVars[name] != value { + t.Errorf("Expected vars: %v Got: %v.", expectedVars, vars) + } + } + } + } + + // 1st route -------------------------------------------------------------- + + // Everything match. + reset() + match(true) + + // Scheme doesn't match. + reset() + scheme = "http" + match(false) + + // Host doesn't match. + reset() + host = "www.mygoogle.com" + match(false) + + // Path doesn't match. + reset() + path = "/product/notdigits" + match(false) + + // Query doesn't match. + reset() + query = "?foo=baz" + match(false) + + // Method doesn't match. + reset() + method = "POST" + match(false) + + // Header doesn't match. + reset() + headers = map[string]string{} + match(false) + + // Everything match, again. + reset() + match(true) + + // 2nd route -------------------------------------------------------------- + + // Everything match. + reset2() + match(true) + + // Scheme doesn't match. + reset2() + scheme = "https" + match(false) + + // Host doesn't match. + reset2() + host = "sub.google.com" + match(false) + + // Path doesn't match. + reset2() + path = "/bar/product/42" + match(false) + + // Query doesn't match. + reset2() + query = "?foo=baz" + match(false) + + // Method doesn't match. + reset2() + method = "GET" + match(false) + + // Header doesn't match. + reset2() + headers = map[string]string{} + match(false) + + // Everything match, again. + reset2() + match(true) +} + +type headerMatcherTest struct { + matcher headerMatcher + headers map[string]string + result bool +} + +var headerMatcherTests = []headerMatcherTest{ + { + matcher: headerMatcher(map[string]string{"x-requested-with": "XMLHttpRequest"}), + headers: map[string]string{"X-Requested-With": "XMLHttpRequest"}, + result: true, + }, + { + matcher: headerMatcher(map[string]string{"x-requested-with": ""}), + headers: map[string]string{"X-Requested-With": "anything"}, + result: true, + }, + { + matcher: headerMatcher(map[string]string{"x-requested-with": "XMLHttpRequest"}), + headers: map[string]string{}, + result: false, + }, +} + +type hostMatcherTest struct { + matcher *Route + url string + vars map[string]string + result bool +} + +var hostMatcherTests = []hostMatcherTest{ + { + matcher: NewRouter().NewRoute().Host("{foo:[a-z][a-z][a-z]}.{bar:[a-z][a-z][a-z]}.{baz:[a-z][a-z][a-z]}"), + url: "http://abc.def.ghi/", + vars: map[string]string{"foo": "abc", "bar": "def", "baz": "ghi"}, + result: true, + }, + { + matcher: NewRouter().NewRoute().Host("{foo:[a-z][a-z][a-z]}.{bar:[a-z][a-z][a-z]}.{baz:[a-z][a-z][a-z]}"), + url: "http://a.b.c/", + vars: map[string]string{"foo": "abc", "bar": "def", "baz": "ghi"}, + result: false, + }, +} + +type methodMatcherTest struct { + matcher methodMatcher + method string + result bool +} + +var methodMatcherTests = []methodMatcherTest{ + { + matcher: methodMatcher([]string{"GET", "POST", "PUT"}), + method: "GET", + result: true, + }, + { + matcher: methodMatcher([]string{"GET", "POST", "PUT"}), + method: "POST", + result: true, + }, + { + matcher: methodMatcher([]string{"GET", "POST", "PUT"}), + method: "PUT", + result: true, + }, + { + matcher: methodMatcher([]string{"GET", "POST", "PUT"}), + method: "DELETE", + result: false, + }, +} + +type pathMatcherTest struct { + matcher *Route + url string + vars map[string]string + result bool +} + +var pathMatcherTests = []pathMatcherTest{ + { + matcher: NewRouter().NewRoute().Path("/{foo:[0-9][0-9][0-9]}/{bar:[0-9][0-9][0-9]}/{baz:[0-9][0-9][0-9]}"), + url: "http://localhost:8080/123/456/789", + vars: map[string]string{"foo": "123", "bar": "456", "baz": "789"}, + result: true, + }, + { + matcher: NewRouter().NewRoute().Path("/{foo:[0-9][0-9][0-9]}/{bar:[0-9][0-9][0-9]}/{baz:[0-9][0-9][0-9]}"), + url: "http://localhost:8080/1/2/3", + vars: map[string]string{"foo": "123", "bar": "456", "baz": "789"}, + result: false, + }, +} + +type schemeMatcherTest struct { + matcher schemeMatcher + url string + result bool +} + +var schemeMatcherTests = []schemeMatcherTest{ + { + matcher: schemeMatcher([]string{"http", "https"}), + url: "http://localhost:8080/", + result: true, + }, + { + matcher: schemeMatcher([]string{"http", "https"}), + url: "https://localhost:8080/", + result: true, + }, + { + matcher: schemeMatcher([]string{"https"}), + url: "http://localhost:8080/", + result: false, + }, + { + matcher: schemeMatcher([]string{"http"}), + url: "https://localhost:8080/", + result: false, + }, +} + +type urlBuildingTest struct { + route *Route + vars []string + url string +} + +var urlBuildingTests = []urlBuildingTest{ + { + route: new(Route).Host("foo.domain.com"), + vars: []string{}, + url: "http://foo.domain.com", + }, + { + route: new(Route).Host("{subdomain}.domain.com"), + vars: []string{"subdomain", "bar"}, + url: "http://bar.domain.com", + }, + { + route: new(Route).Host("foo.domain.com").Path("/articles"), + vars: []string{}, + url: "http://foo.domain.com/articles", + }, + { + route: new(Route).Path("/articles"), + vars: []string{}, + url: "/articles", + }, + { + route: new(Route).Path("/articles/{category}/{id:[0-9]+}"), + vars: []string{"category", "technology", "id", "42"}, + url: "/articles/technology/42", + }, + { + route: new(Route).Host("{subdomain}.domain.com").Path("/articles/{category}/{id:[0-9]+}"), + vars: []string{"subdomain", "foo", "category", "technology", "id", "42"}, + url: "http://foo.domain.com/articles/technology/42", + }, +} + +func TestHeaderMatcher(t *testing.T) { + for _, v := range headerMatcherTests { + request, _ := http.NewRequest("GET", "http://localhost:8080/", nil) + for key, value := range v.headers { + request.Header.Add(key, value) + } + var routeMatch RouteMatch + result := v.matcher.Match(request, &routeMatch) + if result != v.result { + if v.result { + t.Errorf("%#v: should match %v.", v.matcher, request.Header) + } else { + t.Errorf("%#v: should not match %v.", v.matcher, request.Header) + } + } + } +} + +func TestHostMatcher(t *testing.T) { + for _, v := range hostMatcherTests { + request, _ := http.NewRequest("GET", v.url, nil) + var routeMatch RouteMatch + result := v.matcher.Match(request, &routeMatch) + vars := routeMatch.Vars + if result != v.result { + if v.result { + t.Errorf("%#v: should match %v.", v.matcher, v.url) + } else { + t.Errorf("%#v: should not match %v.", v.matcher, v.url) + } + } + if result { + if len(vars) != len(v.vars) { + t.Errorf("%#v: vars length should be %v, got %v.", v.matcher, len(v.vars), len(vars)) + } + for name, value := range vars { + if v.vars[name] != value { + t.Errorf("%#v: expected value %v for key %v, got %v.", v.matcher, v.vars[name], name, value) + } + } + } else { + if len(vars) != 0 { + t.Errorf("%#v: vars length should be 0, got %v.", v.matcher, len(vars)) + } + } + } +} + +func TestMethodMatcher(t *testing.T) { + for _, v := range methodMatcherTests { + request, _ := http.NewRequest(v.method, "http://localhost:8080/", nil) + var routeMatch RouteMatch + result := v.matcher.Match(request, &routeMatch) + if result != v.result { + if v.result { + t.Errorf("%#v: should match %v.", v.matcher, v.method) + } else { + t.Errorf("%#v: should not match %v.", v.matcher, v.method) + } + } + } +} + +func TestPathMatcher(t *testing.T) { + for _, v := range pathMatcherTests { + request, _ := http.NewRequest("GET", v.url, nil) + var routeMatch RouteMatch + result := v.matcher.Match(request, &routeMatch) + vars := routeMatch.Vars + if result != v.result { + if v.result { + t.Errorf("%#v: should match %v.", v.matcher, v.url) + } else { + t.Errorf("%#v: should not match %v.", v.matcher, v.url) + } + } + if result { + if len(vars) != len(v.vars) { + t.Errorf("%#v: vars length should be %v, got %v.", v.matcher, len(v.vars), len(vars)) + } + for name, value := range vars { + if v.vars[name] != value { + t.Errorf("%#v: expected value %v for key %v, got %v.", v.matcher, v.vars[name], name, value) + } + } + } else { + if len(vars) != 0 { + t.Errorf("%#v: vars length should be 0, got %v.", v.matcher, len(vars)) + } + } + } +} + +func TestSchemeMatcher(t *testing.T) { + for _, v := range schemeMatcherTests { + request, _ := http.NewRequest("GET", v.url, nil) + var routeMatch RouteMatch + result := v.matcher.Match(request, &routeMatch) + if result != v.result { + if v.result { + t.Errorf("%#v: should match %v.", v.matcher, v.url) + } else { + t.Errorf("%#v: should not match %v.", v.matcher, v.url) + } + } + } +} + +func TestUrlBuilding(t *testing.T) { + + for _, v := range urlBuildingTests { + u, _ := v.route.URL(v.vars...) + url := u.String() + if url != v.url { + t.Errorf("expected %v, got %v", v.url, url) + /* + reversePath := "" + reverseHost := "" + if v.route.pathTemplate != nil { + reversePath = v.route.pathTemplate.Reverse + } + if v.route.hostTemplate != nil { + reverseHost = v.route.hostTemplate.Reverse + } + + t.Errorf("%#v:\nexpected: %q\ngot: %q\nreverse path: %q\nreverse host: %q", v.route, v.url, url, reversePath, reverseHost) + */ + } + } + + ArticleHandler := func(w http.ResponseWriter, r *http.Request) { + } + + router := NewRouter() + router.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler).Name("article") + + url, _ := router.Get("article").URL("category", "technology", "id", "42") + expected := "/articles/technology/42" + if url.String() != expected { + t.Errorf("Expected %v, got %v", expected, url.String()) + } +} + +func TestMatchedRouteName(t *testing.T) { + routeName := "stock" + router := NewRouter() + route := router.NewRoute().Path("/products/").Name(routeName) + + url := "http://www.domain.com/products/" + request, _ := http.NewRequest("GET", url, nil) + var rv RouteMatch + ok := router.Match(request, &rv) + + if !ok || rv.Route != route { + t.Errorf("Expected same route, got %+v.", rv.Route) + } + + retName := rv.Route.GetName() + if retName != routeName { + t.Errorf("Expected %q, got %q.", routeName, retName) + } +} + +func TestSubRouting(t *testing.T) { + // Example from docs. + router := NewRouter() + subrouter := router.NewRoute().Host("www.domain.com").Subrouter() + route := subrouter.NewRoute().Path("/products/").Name("products") + + url := "http://www.domain.com/products/" + request, _ := http.NewRequest("GET", url, nil) + var rv RouteMatch + ok := router.Match(request, &rv) + + if !ok || rv.Route != route { + t.Errorf("Expected same route, got %+v.", rv.Route) + } + + u, _ := router.Get("products").URL() + builtUrl := u.String() + // Yay, subroute aware of the domain when building! + if builtUrl != url { + t.Errorf("Expected %q, got %q.", url, builtUrl) + } +} + +func TestVariableNames(t *testing.T) { + route := new(Route).Host("{arg1}.domain.com").Path("/{arg1}/{arg2:[0-9]+}") + if route.err == nil { + t.Errorf("Expected error for duplicated variable names") + } +} + +func TestRedirectSlash(t *testing.T) { + var route *Route + var routeMatch RouteMatch + r := NewRouter() + + r.StrictSlash(false) + route = r.NewRoute() + if route.strictSlash != false { + t.Errorf("Expected false redirectSlash.") + } + + r.StrictSlash(true) + route = r.NewRoute() + if route.strictSlash != true { + t.Errorf("Expected true redirectSlash.") + } + + route = new(Route) + route.strictSlash = true + route.Path("/{arg1}/{arg2:[0-9]+}/") + request, _ := http.NewRequest("GET", "http://localhost/foo/123", nil) + routeMatch = RouteMatch{} + _ = route.Match(request, &routeMatch) + vars := routeMatch.Vars + if vars["arg1"] != "foo" { + t.Errorf("Expected foo.") + } + if vars["arg2"] != "123" { + t.Errorf("Expected 123.") + } + rsp := NewRecorder() + routeMatch.Handler.ServeHTTP(rsp, request) + if rsp.HeaderMap.Get("Location") != "http://localhost/foo/123/" { + t.Errorf("Expected redirect header.") + } + + route = new(Route) + route.strictSlash = true + route.Path("/{arg1}/{arg2:[0-9]+}") + request, _ = http.NewRequest("GET", "http://localhost/foo/123/", nil) + routeMatch = RouteMatch{} + _ = route.Match(request, &routeMatch) + vars = routeMatch.Vars + if vars["arg1"] != "foo" { + t.Errorf("Expected foo.") + } + if vars["arg2"] != "123" { + t.Errorf("Expected 123.") + } + rsp = NewRecorder() + routeMatch.Handler.ServeHTTP(rsp, request) + if rsp.HeaderMap.Get("Location") != "http://localhost/foo/123" { + t.Errorf("Expected redirect header.") + } +} + +// Test for the new regexp library, still not available in stable Go. +func TestNewRegexp(t *testing.T) { + var p *routeRegexp + var matches []string + + tests := map[string]map[string][]string{ + "/{foo:a{2}}": { + "/a": nil, + "/aa": {"aa"}, + "/aaa": nil, + "/aaaa": nil, + }, + "/{foo:a{2,}}": { + "/a": nil, + "/aa": {"aa"}, + "/aaa": {"aaa"}, + "/aaaa": {"aaaa"}, + }, + "/{foo:a{2,3}}": { + "/a": nil, + "/aa": {"aa"}, + "/aaa": {"aaa"}, + "/aaaa": nil, + }, + "/{foo:[a-z]{3}}/{bar:[a-z]{2}}": { + "/a": nil, + "/ab": nil, + "/abc": nil, + "/abcd": nil, + "/abc/ab": {"abc", "ab"}, + "/abc/abc": nil, + "/abcd/ab": nil, + }, + `/{foo:\w{3,}}/{bar:\d{2,}}`: { + "/a": nil, + "/ab": nil, + "/abc": nil, + "/abc/1": nil, + "/abc/12": {"abc", "12"}, + "/abcd/12": {"abcd", "12"}, + "/abcd/123": {"abcd", "123"}, + }, + } + + for pattern, paths := range tests { + p, _ = newRouteRegexp(pattern, false, false, false, false) + for path, result := range paths { + matches = p.regexp.FindStringSubmatch(path) + if result == nil { + if matches != nil { + t.Errorf("%v should not match %v.", pattern, path) + } + } else { + if len(matches) != len(result)+1 { + t.Errorf("Expected %v matches, got %v.", len(result)+1, len(matches)) + } else { + for k, v := range result { + if matches[k+1] != v { + t.Errorf("Expected %v, got %v.", v, matches[k+1]) + } + } + } + } + } + } +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/regexp.go b/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/regexp.go new file mode 100644 index 000000000..a6305483d --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/regexp.go @@ -0,0 +1,276 @@ +// Copyright 2012 The Gorilla Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mux + +import ( + "bytes" + "fmt" + "net/http" + "net/url" + "regexp" + "strings" +) + +// newRouteRegexp parses a route template and returns a routeRegexp, +// used to match a host, a path or a query string. +// +// It will extract named variables, assemble a regexp to be matched, create +// a "reverse" template to build URLs and compile regexps to validate variable +// values used in URL building. +// +// Previously we accepted only Python-like identifiers for variable +// names ([a-zA-Z_][a-zA-Z0-9_]*), but currently the only restriction is that +// name and pattern can't be empty, and names can't contain a colon. +func newRouteRegexp(tpl string, matchHost, matchPrefix, matchQuery, strictSlash bool) (*routeRegexp, error) { + // Check if it is well-formed. + idxs, errBraces := braceIndices(tpl) + if errBraces != nil { + return nil, errBraces + } + // Backup the original. + template := tpl + // Now let's parse it. + defaultPattern := "[^/]+" + if matchQuery { + defaultPattern = "[^?&]+" + matchPrefix = true + } else if matchHost { + defaultPattern = "[^.]+" + matchPrefix = false + } + // Only match strict slash if not matching + if matchPrefix || matchHost || matchQuery { + strictSlash = false + } + // Set a flag for strictSlash. + endSlash := false + if strictSlash && strings.HasSuffix(tpl, "/") { + tpl = tpl[:len(tpl)-1] + endSlash = true + } + varsN := make([]string, len(idxs)/2) + varsR := make([]*regexp.Regexp, len(idxs)/2) + pattern := bytes.NewBufferString("") + if !matchQuery { + pattern.WriteByte('^') + } + reverse := bytes.NewBufferString("") + var end int + var err error + for i := 0; i < len(idxs); i += 2 { + // Set all values we are interested in. + raw := tpl[end:idxs[i]] + end = idxs[i+1] + parts := strings.SplitN(tpl[idxs[i]+1:end-1], ":", 2) + name := parts[0] + patt := defaultPattern + if len(parts) == 2 { + patt = parts[1] + } + // Name or pattern can't be empty. + if name == "" || patt == "" { + return nil, fmt.Errorf("mux: missing name or pattern in %q", + tpl[idxs[i]:end]) + } + // Build the regexp pattern. + fmt.Fprintf(pattern, "%s(%s)", regexp.QuoteMeta(raw), patt) + // Build the reverse template. + fmt.Fprintf(reverse, "%s%%s", raw) + // Append variable name and compiled pattern. + varsN[i/2] = name + varsR[i/2], err = regexp.Compile(fmt.Sprintf("^%s$", patt)) + if err != nil { + return nil, err + } + } + // Add the remaining. + raw := tpl[end:] + pattern.WriteString(regexp.QuoteMeta(raw)) + if strictSlash { + pattern.WriteString("[/]?") + } + if !matchPrefix { + pattern.WriteByte('$') + } + reverse.WriteString(raw) + if endSlash { + reverse.WriteByte('/') + } + // Compile full regexp. + reg, errCompile := regexp.Compile(pattern.String()) + if errCompile != nil { + return nil, errCompile + } + // Done! + return &routeRegexp{ + template: template, + matchHost: matchHost, + matchQuery: matchQuery, + strictSlash: strictSlash, + regexp: reg, + reverse: reverse.String(), + varsN: varsN, + varsR: varsR, + }, nil +} + +// routeRegexp stores a regexp to match a host or path and information to +// collect and validate route variables. +type routeRegexp struct { + // The unmodified template. + template string + // True for host match, false for path or query string match. + matchHost bool + // True for query string match, false for path and host match. + matchQuery bool + // The strictSlash value defined on the route, but disabled if PathPrefix was used. + strictSlash bool + // Expanded regexp. + regexp *regexp.Regexp + // Reverse template. + reverse string + // Variable names. + varsN []string + // Variable regexps (validators). + varsR []*regexp.Regexp +} + +// Match matches the regexp against the URL host or path. +func (r *routeRegexp) Match(req *http.Request, match *RouteMatch) bool { + if !r.matchHost { + if r.matchQuery { + return r.regexp.MatchString(req.URL.RawQuery) + } else { + return r.regexp.MatchString(req.URL.Path) + } + } + return r.regexp.MatchString(getHost(req)) +} + +// url builds a URL part using the given values. +func (r *routeRegexp) url(pairs ...string) (string, error) { + values, err := mapFromPairs(pairs...) + if err != nil { + return "", err + } + urlValues := make([]interface{}, len(r.varsN)) + for k, v := range r.varsN { + value, ok := values[v] + if !ok { + return "", fmt.Errorf("mux: missing route variable %q", v) + } + urlValues[k] = value + } + rv := fmt.Sprintf(r.reverse, urlValues...) + if !r.regexp.MatchString(rv) { + // The URL is checked against the full regexp, instead of checking + // individual variables. This is faster but to provide a good error + // message, we check individual regexps if the URL doesn't match. + for k, v := range r.varsN { + if !r.varsR[k].MatchString(values[v]) { + return "", fmt.Errorf( + "mux: variable %q doesn't match, expected %q", values[v], + r.varsR[k].String()) + } + } + } + return rv, nil +} + +// braceIndices returns the first level curly brace indices from a string. +// It returns an error in case of unbalanced braces. +func braceIndices(s string) ([]int, error) { + var level, idx int + idxs := make([]int, 0) + for i := 0; i < len(s); i++ { + switch s[i] { + case '{': + if level++; level == 1 { + idx = i + } + case '}': + if level--; level == 0 { + idxs = append(idxs, idx, i+1) + } else if level < 0 { + return nil, fmt.Errorf("mux: unbalanced braces in %q", s) + } + } + } + if level != 0 { + return nil, fmt.Errorf("mux: unbalanced braces in %q", s) + } + return idxs, nil +} + +// ---------------------------------------------------------------------------- +// routeRegexpGroup +// ---------------------------------------------------------------------------- + +// routeRegexpGroup groups the route matchers that carry variables. +type routeRegexpGroup struct { + host *routeRegexp + path *routeRegexp + queries []*routeRegexp +} + +// setMatch extracts the variables from the URL once a route matches. +func (v *routeRegexpGroup) setMatch(req *http.Request, m *RouteMatch, r *Route) { + // Store host variables. + if v.host != nil { + hostVars := v.host.regexp.FindStringSubmatch(getHost(req)) + if hostVars != nil { + for k, v := range v.host.varsN { + m.Vars[v] = hostVars[k+1] + } + } + } + // Store path variables. + if v.path != nil { + pathVars := v.path.regexp.FindStringSubmatch(req.URL.Path) + if pathVars != nil { + for k, v := range v.path.varsN { + m.Vars[v] = pathVars[k+1] + } + // Check if we should redirect. + if v.path.strictSlash { + p1 := strings.HasSuffix(req.URL.Path, "/") + p2 := strings.HasSuffix(v.path.template, "/") + if p1 != p2 { + u, _ := url.Parse(req.URL.String()) + if p1 { + u.Path = u.Path[:len(u.Path)-1] + } else { + u.Path += "/" + } + m.Handler = http.RedirectHandler(u.String(), 301) + } + } + } + } + // Store query string variables. + rawQuery := req.URL.RawQuery + for _, q := range v.queries { + queryVars := q.regexp.FindStringSubmatch(rawQuery) + if queryVars != nil { + for k, v := range q.varsN { + m.Vars[v] = queryVars[k+1] + } + } + } +} + +// getHost tries its best to return the request host. +func getHost(r *http.Request) string { + if r.URL.IsAbs() { + return r.URL.Host + } + host := r.Host + // Slice off any port information. + if i := strings.Index(host, ":"); i != -1 { + host = host[:i] + } + return host + +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/route.go b/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/route.go new file mode 100644 index 000000000..c310e66bc --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/gorilla/mux/route.go @@ -0,0 +1,524 @@ +// Copyright 2012 The Gorilla Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mux + +import ( + "errors" + "fmt" + "net/http" + "net/url" + "strings" +) + +// Route stores information to match a request and build URLs. +type Route struct { + // Parent where the route was registered (a Router). + parent parentRoute + // Request handler for the route. + handler http.Handler + // List of matchers. + matchers []matcher + // Manager for the variables from host and path. + regexp *routeRegexpGroup + // If true, when the path pattern is "/path/", accessing "/path" will + // redirect to the former and vice versa. + strictSlash bool + // If true, this route never matches: it is only used to build URLs. + buildOnly bool + // The name used to build URLs. + name string + // Error resulted from building a route. + err error +} + +// Match matches the route against the request. +func (r *Route) Match(req *http.Request, match *RouteMatch) bool { + if r.buildOnly || r.err != nil { + return false + } + // Match everything. + for _, m := range r.matchers { + if matched := m.Match(req, match); !matched { + return false + } + } + // Yay, we have a match. Let's collect some info about it. + if match.Route == nil { + match.Route = r + } + if match.Handler == nil { + match.Handler = r.handler + } + if match.Vars == nil { + match.Vars = make(map[string]string) + } + // Set variables. + if r.regexp != nil { + r.regexp.setMatch(req, match, r) + } + return true +} + +// ---------------------------------------------------------------------------- +// Route attributes +// ---------------------------------------------------------------------------- + +// GetError returns an error resulted from building the route, if any. +func (r *Route) GetError() error { + return r.err +} + +// BuildOnly sets the route to never match: it is only used to build URLs. +func (r *Route) BuildOnly() *Route { + r.buildOnly = true + return r +} + +// Handler -------------------------------------------------------------------- + +// Handler sets a handler for the route. +func (r *Route) Handler(handler http.Handler) *Route { + if r.err == nil { + r.handler = handler + } + return r +} + +// HandlerFunc sets a handler function for the route. +func (r *Route) HandlerFunc(f func(http.ResponseWriter, *http.Request)) *Route { + return r.Handler(http.HandlerFunc(f)) +} + +// GetHandler returns the handler for the route, if any. +func (r *Route) GetHandler() http.Handler { + return r.handler +} + +// Name ----------------------------------------------------------------------- + +// Name sets the name for the route, used to build URLs. +// If the name was registered already it will be overwritten. +func (r *Route) Name(name string) *Route { + if r.name != "" { + r.err = fmt.Errorf("mux: route already has name %q, can't set %q", + r.name, name) + } + if r.err == nil { + r.name = name + r.getNamedRoutes()[name] = r + } + return r +} + +// GetName returns the name for the route, if any. +func (r *Route) GetName() string { + return r.name +} + +// ---------------------------------------------------------------------------- +// Matchers +// ---------------------------------------------------------------------------- + +// matcher types try to match a request. +type matcher interface { + Match(*http.Request, *RouteMatch) bool +} + +// addMatcher adds a matcher to the route. +func (r *Route) addMatcher(m matcher) *Route { + if r.err == nil { + r.matchers = append(r.matchers, m) + } + return r +} + +// addRegexpMatcher adds a host or path matcher and builder to a route. +func (r *Route) addRegexpMatcher(tpl string, matchHost, matchPrefix, matchQuery bool) error { + if r.err != nil { + return r.err + } + r.regexp = r.getRegexpGroup() + if !matchHost && !matchQuery { + if len(tpl) == 0 || tpl[0] != '/' { + return fmt.Errorf("mux: path must start with a slash, got %q", tpl) + } + if r.regexp.path != nil { + tpl = strings.TrimRight(r.regexp.path.template, "/") + tpl + } + } + rr, err := newRouteRegexp(tpl, matchHost, matchPrefix, matchQuery, r.strictSlash) + if err != nil { + return err + } + for _, q := range r.regexp.queries { + if err = uniqueVars(rr.varsN, q.varsN); err != nil { + return err + } + } + if matchHost { + if r.regexp.path != nil { + if err = uniqueVars(rr.varsN, r.regexp.path.varsN); err != nil { + return err + } + } + r.regexp.host = rr + } else { + if r.regexp.host != nil { + if err = uniqueVars(rr.varsN, r.regexp.host.varsN); err != nil { + return err + } + } + if matchQuery { + r.regexp.queries = append(r.regexp.queries, rr) + } else { + r.regexp.path = rr + } + } + r.addMatcher(rr) + return nil +} + +// Headers -------------------------------------------------------------------- + +// headerMatcher matches the request against header values. +type headerMatcher map[string]string + +func (m headerMatcher) Match(r *http.Request, match *RouteMatch) bool { + return matchMap(m, r.Header, true) +} + +// Headers adds a matcher for request header values. +// It accepts a sequence of key/value pairs to be matched. For example: +// +// r := mux.NewRouter() +// r.Headers("Content-Type", "application/json", +// "X-Requested-With", "XMLHttpRequest") +// +// The above route will only match if both request header values match. +// +// It the value is an empty string, it will match any value if the key is set. +func (r *Route) Headers(pairs ...string) *Route { + if r.err == nil { + var headers map[string]string + headers, r.err = mapFromPairs(pairs...) + return r.addMatcher(headerMatcher(headers)) + } + return r +} + +// Host ----------------------------------------------------------------------- + +// Host adds a matcher for the URL host. +// It accepts a template with zero or more URL variables enclosed by {}. +// Variables can define an optional regexp pattern to me matched: +// +// - {name} matches anything until the next dot. +// +// - {name:pattern} matches the given regexp pattern. +// +// For example: +// +// r := mux.NewRouter() +// r.Host("www.domain.com") +// r.Host("{subdomain}.domain.com") +// r.Host("{subdomain:[a-z]+}.domain.com") +// +// Variable names must be unique in a given route. They can be retrieved +// calling mux.Vars(request). +func (r *Route) Host(tpl string) *Route { + r.err = r.addRegexpMatcher(tpl, true, false, false) + return r +} + +// MatcherFunc ---------------------------------------------------------------- + +// MatcherFunc is the function signature used by custom matchers. +type MatcherFunc func(*http.Request, *RouteMatch) bool + +func (m MatcherFunc) Match(r *http.Request, match *RouteMatch) bool { + return m(r, match) +} + +// MatcherFunc adds a custom function to be used as request matcher. +func (r *Route) MatcherFunc(f MatcherFunc) *Route { + return r.addMatcher(f) +} + +// Methods -------------------------------------------------------------------- + +// methodMatcher matches the request against HTTP methods. +type methodMatcher []string + +func (m methodMatcher) Match(r *http.Request, match *RouteMatch) bool { + return matchInArray(m, r.Method) +} + +// Methods adds a matcher for HTTP methods. +// It accepts a sequence of one or more methods to be matched, e.g.: +// "GET", "POST", "PUT". +func (r *Route) Methods(methods ...string) *Route { + for k, v := range methods { + methods[k] = strings.ToUpper(v) + } + return r.addMatcher(methodMatcher(methods)) +} + +// Path ----------------------------------------------------------------------- + +// Path adds a matcher for the URL path. +// It accepts a template with zero or more URL variables enclosed by {}. The +// template must start with a "/". +// Variables can define an optional regexp pattern to me matched: +// +// - {name} matches anything until the next slash. +// +// - {name:pattern} matches the given regexp pattern. +// +// For example: +// +// r := mux.NewRouter() +// r.Path("/products/").Handler(ProductsHandler) +// r.Path("/products/{key}").Handler(ProductsHandler) +// r.Path("/articles/{category}/{id:[0-9]+}"). +// Handler(ArticleHandler) +// +// Variable names must be unique in a given route. They can be retrieved +// calling mux.Vars(request). +func (r *Route) Path(tpl string) *Route { + r.err = r.addRegexpMatcher(tpl, false, false, false) + return r +} + +// PathPrefix ----------------------------------------------------------------- + +// PathPrefix adds a matcher for the URL path prefix. This matches if the given +// template is a prefix of the full URL path. See Route.Path() for details on +// the tpl argument. +// +// Note that it does not treat slashes specially ("/foobar/" will be matched by +// the prefix "/foo") so you may want to use a trailing slash here. +// +// Also note that the setting of Router.StrictSlash() has no effect on routes +// with a PathPrefix matcher. +func (r *Route) PathPrefix(tpl string) *Route { + r.err = r.addRegexpMatcher(tpl, false, true, false) + return r +} + +// Query ---------------------------------------------------------------------- + +// Queries adds a matcher for URL query values. +// It accepts a sequence of key/value pairs. Values may define variables. +// For example: +// +// r := mux.NewRouter() +// r.Queries("foo", "bar", "id", "{id:[0-9]+}") +// +// The above route will only match if the URL contains the defined queries +// values, e.g.: ?foo=bar&id=42. +// +// It the value is an empty string, it will match any value if the key is set. +// +// Variables can define an optional regexp pattern to me matched: +// +// - {name} matches anything until the next slash. +// +// - {name:pattern} matches the given regexp pattern. +func (r *Route) Queries(pairs ...string) *Route { + length := len(pairs) + if length%2 != 0 { + r.err = fmt.Errorf( + "mux: number of parameters must be multiple of 2, got %v", pairs) + return nil + } + for i := 0; i < length; i += 2 { + if r.err = r.addRegexpMatcher(pairs[i]+"="+pairs[i+1], false, true, true); r.err != nil { + return r + } + } + + return r +} + +// Schemes -------------------------------------------------------------------- + +// schemeMatcher matches the request against URL schemes. +type schemeMatcher []string + +func (m schemeMatcher) Match(r *http.Request, match *RouteMatch) bool { + return matchInArray(m, r.URL.Scheme) +} + +// Schemes adds a matcher for URL schemes. +// It accepts a sequence of schemes to be matched, e.g.: "http", "https". +func (r *Route) Schemes(schemes ...string) *Route { + for k, v := range schemes { + schemes[k] = strings.ToLower(v) + } + return r.addMatcher(schemeMatcher(schemes)) +} + +// Subrouter ------------------------------------------------------------------ + +// Subrouter creates a subrouter for the route. +// +// It will test the inner routes only if the parent route matched. For example: +// +// r := mux.NewRouter() +// s := r.Host("www.domain.com").Subrouter() +// s.HandleFunc("/products/", ProductsHandler) +// s.HandleFunc("/products/{key}", ProductHandler) +// s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler) +// +// Here, the routes registered in the subrouter won't be tested if the host +// doesn't match. +func (r *Route) Subrouter() *Router { + router := &Router{parent: r, strictSlash: r.strictSlash} + r.addMatcher(router) + return router +} + +// ---------------------------------------------------------------------------- +// URL building +// ---------------------------------------------------------------------------- + +// URL builds a URL for the route. +// +// It accepts a sequence of key/value pairs for the route variables. For +// example, given this route: +// +// r := mux.NewRouter() +// r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). +// Name("article") +// +// ...a URL for it can be built using: +// +// url, err := r.Get("article").URL("category", "technology", "id", "42") +// +// ...which will return an url.URL with the following path: +// +// "/articles/technology/42" +// +// This also works for host variables: +// +// r := mux.NewRouter() +// r.Host("{subdomain}.domain.com"). +// HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). +// Name("article") +// +// // url.String() will be "http://news.domain.com/articles/technology/42" +// url, err := r.Get("article").URL("subdomain", "news", +// "category", "technology", +// "id", "42") +// +// All variables defined in the route are required, and their values must +// conform to the corresponding patterns. +func (r *Route) URL(pairs ...string) (*url.URL, error) { + if r.err != nil { + return nil, r.err + } + if r.regexp == nil { + return nil, errors.New("mux: route doesn't have a host or path") + } + var scheme, host, path string + var err error + if r.regexp.host != nil { + // Set a default scheme. + scheme = "http" + if host, err = r.regexp.host.url(pairs...); err != nil { + return nil, err + } + } + if r.regexp.path != nil { + if path, err = r.regexp.path.url(pairs...); err != nil { + return nil, err + } + } + return &url.URL{ + Scheme: scheme, + Host: host, + Path: path, + }, nil +} + +// URLHost builds the host part of the URL for a route. See Route.URL(). +// +// The route must have a host defined. +func (r *Route) URLHost(pairs ...string) (*url.URL, error) { + if r.err != nil { + return nil, r.err + } + if r.regexp == nil || r.regexp.host == nil { + return nil, errors.New("mux: route doesn't have a host") + } + host, err := r.regexp.host.url(pairs...) + if err != nil { + return nil, err + } + return &url.URL{ + Scheme: "http", + Host: host, + }, nil +} + +// URLPath builds the path part of the URL for a route. See Route.URL(). +// +// The route must have a path defined. +func (r *Route) URLPath(pairs ...string) (*url.URL, error) { + if r.err != nil { + return nil, r.err + } + if r.regexp == nil || r.regexp.path == nil { + return nil, errors.New("mux: route doesn't have a path") + } + path, err := r.regexp.path.url(pairs...) + if err != nil { + return nil, err + } + return &url.URL{ + Path: path, + }, nil +} + +// ---------------------------------------------------------------------------- +// parentRoute +// ---------------------------------------------------------------------------- + +// parentRoute allows routes to know about parent host and path definitions. +type parentRoute interface { + getNamedRoutes() map[string]*Route + getRegexpGroup() *routeRegexpGroup +} + +// getNamedRoutes returns the map where named routes are registered. +func (r *Route) getNamedRoutes() map[string]*Route { + if r.parent == nil { + // During tests router is not always set. + r.parent = NewRouter() + } + return r.parent.getNamedRoutes() +} + +// getRegexpGroup returns regexp definitions from this route. +func (r *Route) getRegexpGroup() *routeRegexpGroup { + if r.regexp == nil { + if r.parent == nil { + // During tests router is not always set. + r.parent = NewRouter() + } + regexp := r.parent.getRegexpGroup() + if regexp == nil { + r.regexp = new(routeRegexpGroup) + } else { + // Copy. + r.regexp = &routeRegexpGroup{ + host: regexp.host, + path: regexp.path, + queries: regexp.queries, + } + } + } + return r.regexp +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/.gitignore b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/.gitignore new file mode 100644 index 000000000..ea9f6bc3c --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/.gitignore @@ -0,0 +1,6 @@ +*.o +*.a +*.so +*~ +*.dSYM +*.syso \ No newline at end of file diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/BUILDDEPS.md b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/BUILDDEPS.md new file mode 100644 index 000000000..df3770b29 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/BUILDDEPS.md @@ -0,0 +1,80 @@ +## Ubuntu (Kylin) 14.04 +### Build Dependencies +This installation document assumes Ubuntu 14.04 or later on x86-64 platform. + +##### Install YASM + +Erasure depends on Intel ISAL library, ISAL uses Intel AVX2 processor instructions, to compile these files one needs to install ``yasm`` which supports AVX2 instructions. AVX2 support only ended in ``yasm`` from version ``1.2.0``, any version below ``1.2.0`` will throw a build error. + +```sh +$ sudo apt-get install yasm +``` + +##### Install Go 1.4+ +Download Go 1.4+ from [https://golang.org/dl/](https://golang.org/dl/) and extract it into ``${HOME}/local`` and setup ``${HOME}/mygo`` as your project workspace folder. +For example: +```sh +.... Extract and install golang .... + +$ wget https://storage.googleapis.com/golang/go1.4.linux-amd64.tar.gz +$ mkdir -p ${HOME}/local +$ mkdir -p $HOME/mygo +$ tar -C ${HOME}/local -xzf go1.4.linux-amd64.tar.gz + +.... Export necessary environment variables .... + +$ export PATH=$PATH:${HOME}/local/go/bin +$ export GOROOT=${HOME}/local/go +$ export GOPATH=$HOME/mygo +$ export PATH=$PATH:$GOPATH/bin + +.... Add paths to your bashrc .... + +$ echo "export PATH=$PATH:${HOME}/local/go/bin" >> ${HOME}/.bashrc +$ echo "export GOROOT=${HOME}/local/go" >> ${HOME}/.bashrc +$ echo "export GOPATH=$HOME/mygo" >> ${HOME}/.bashrc +$ echo "export PATH=$PATH:$GOPATH/bin" >> ${HOME}/.bashrc +``` + +## Mac OSX (Yosemite) 10.10 +### Build Dependencies +This installation document assumes Mac OSX Yosemite 10.10 or later on x86-64 platform. + +##### Install brew +```sh +$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" +``` + +##### Install Git +```sh +$ brew install git +``` + +##### Install YASM + +Erasure depends on Intel ISAL library, ISAL uses Intel AVX2 processor instructions, to compile these files one needs to install ``yasm`` which supports AVX2 instructions. AVX2 support only ended in ``yasm`` from version ``1.2.0``, any version below ``1.2.0`` will throw a build error. + +```sh +$ brew install yasm +``` + +##### Install Go 1.4+ +On MacOSX ``brew.sh`` is the best way to install golang + +For example: +```sh +.... Install golang using `brew` .... + +$ brew install go +$ mkdir -p $HOME/mygo + +.... Export necessary environment variables .... + +$ export GOPATH=$HOME/mygo +$ export PATH=$PATH:$GOPATH/bin + +.... Add paths to your bashrc .... + +$ echo "export GOPATH=$HOME/mygo" >> ${HOME}/.bashrc +$ echo "export PATH=$PATH:$GOPATH/bin" >> ${HOME}/.bashrc +``` diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/CONTRIBUTING.md b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/CONTRIBUTING.md new file mode 100644 index 000000000..1dfc6a0cb --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/CONTRIBUTING.md @@ -0,0 +1,30 @@ +### Setup your Erasure Github Repository +Fork [Erasure upstream](https://github.com/minio-io/erasure/fork) source repository to your own personal repository. Copy the URL and pass it to ``go get`` command. Go uses git to clone a copy into your project workspace folder. +```sh +$ git clone https://github.com/$USER_ID/erasure +$ cd erasure +$ mkdir -p ${GOPATH}/src/github.com/minio-io +$ ln -s ${PWD} $GOPATH/src/github.com/minio-io/ +``` + +### Compiling Erasure from source +```sh +$ go generate +$ go build +``` +### Developer Guidelines +To make the process as seamless as possible, we ask for the following: +* Go ahead and fork the project and make your changes. We encourage pull requests to discuss code changes. + - Fork it + - Create your feature branch (git checkout -b my-new-feature) + - Commit your changes (git commit -am 'Add some feature') + - Push to the branch (git push origin my-new-feature) + - Create new Pull Request +* When you're ready to create a pull request, be sure to: + - Have test cases for the new code. If you have questions about how to do it, please ask in your pull request. + - Run `go fmt` + - Squash your commits into a single commit. `git rebase -i`. It's okay to force update your pull request. + - Make sure `go test -race ./...` and `go build` completes. +* Read [Effective Go](https://github.com/golang/go/wiki/CodeReviewComments) article from Golang project + - `Erasure` project is strictly conformant with Golang style + - if you happen to observe offending code, please feel free to send a pull request diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/LICENSE.INTEL b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/LICENSE.INTEL new file mode 100644 index 000000000..667056695 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/LICENSE.INTEL @@ -0,0 +1,26 @@ + Copyright(c) 2011-2014 Intel Corporation All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/LICENSE.MINIO b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/LICENSE.MINIO new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/LICENSE.MINIO @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/README.md b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/README.md new file mode 100644 index 000000000..cafa80eb3 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/README.md @@ -0,0 +1,25 @@ +## Introduction + +Erasure is an open source Golang library written on top of ISAL (Intel Intelligent Storage Library) released under [Apache license v2](./LICENSE) + +### Developers +* [Get Source](./CONTRIBUTING.md) +* [Build Dependencies](./BUILDDEPS.md) +* [Development Workflow](./CONTRIBUTING.md#developer-guidelines) +* [Developer discussions and bugs](https://github.com/Minio-io/erasure/issues) + +### Supported platforms + +| Name | Supported | +| ------------- | ------------- | +| Linux | Yes | +| Windows | Not yet | +| Mac OSX | Yes | + +### Supported architectures + +| Arch | Supported | +| ------------- | ------------- | +| x86-64 | Yes | +| arm64 | Not yet| +| i386 | Never | diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/RELEASE-NOTES.INTEL b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/RELEASE-NOTES.INTEL new file mode 100644 index 000000000..b4b601824 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/RELEASE-NOTES.INTEL @@ -0,0 +1,49 @@ +================================================================================ +v2.10 Intel Intelligent Storage Acceleration Library Release Notes + Open Source Version +================================================================================ + +================================================================================ +RELEASE NOTE CONTENTS +================================================================================ +1. KNOWN ISSUES +2. FIXED ISSUES +3. CHANGE LOG & FEATURES ADDED + +================================================================================ +1. KNOWN ISSUES +================================================================================ + +* Only erasure code unit included in open source version at this time. + +* Perf tests do not run in Windows environment. + +* Leaving /bin directories from builds in unit directories will cause the + top-level make build to fail. Build only in top-level or ensure unit + directories are clean of objects and /bin. + +* 32-bit lib is not supported in Windows. + +================================================================================ +2. FIXED ISSUES +================================================================================ +v2.10 + +* Fix for windows register save overlap in gf_{3-6}vect_dot_prod_sse.asm. Only + affects windows versions of erasure code. GP register saves/restore were + pushed to same stack area as XMM. + +================================================================================ +3. CHANGE LOG & FEATURES ADDED +================================================================================ +v2.10 + +* Erasure code updates + - New AVX and AVX2 support functions. + - Changes min len requirement on gf_vect_dot_prod() to 32 from 16. + - Tests include both source and parity recovery with ec_encode_data(). + - New encoding examples with Vandermonde or Cauchy matrix. + +v2.8 + +* First open release of erasure code unit that is part of ISA-L. diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/RELEASE-NOTES.MINIO b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/RELEASE-NOTES.MINIO new file mode 100644 index 000000000..bf3ed1ece --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/RELEASE-NOTES.MINIO @@ -0,0 +1,3 @@ +v1.0 - Erasure Golang Package +============================ +- First release, supports only amd64 or x86-64 architecture \ No newline at end of file diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/cauchy_test.go b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/cauchy_test.go new file mode 100644 index 000000000..37f28c74c --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/cauchy_test.go @@ -0,0 +1,71 @@ +/* + * Minimalist Object Storage, (C) 2014 Minio, 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 erasure + +import ( + "bytes" + "testing" + + . "gopkg.in/check.v1" +) + +type MySuite struct{} + +var _ = Suite(&MySuite{}) + +func Test(t *testing.T) { TestingT(t) } + +const ( + k = 10 + m = 5 +) + +func (s *MySuite) TestCauchyEncodeDecodeFailure(c *C) { + ep, _ := ValidateParams(k, m, Cauchy) + + data := []byte("Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.") + + e := NewErasure(ep) + chunks, err := e.Encode(data) + c.Assert(err, IsNil) + + errorIndex := []int{0, 3, 5, 9, 11, 13} + chunks = corruptChunks(chunks, errorIndex) + + _, err = e.Decode(chunks, len(data)) + c.Assert(err, Not(IsNil)) +} + +func (s *MySuite) TestCauchyEncodeDecodeSuccess(c *C) { + ep, _ := ValidateParams(k, m, Cauchy) + + data := []byte("Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.") + + e := NewErasure(ep) + chunks, err := e.Encode(data) + c.Assert(err, IsNil) + + errorIndex := []int{0, 3, 5, 9, 13} + chunks = corruptChunks(chunks, errorIndex) + + recoveredData, err := e.Decode(chunks, len(data)) + c.Assert(err, IsNil) + + if !bytes.Equal(data, recoveredData) { + c.Fatalf("Recovered data mismatches with original data") + } +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ctypes.go b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ctypes.go new file mode 100644 index 000000000..da04076fc --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ctypes.go @@ -0,0 +1,59 @@ +/* + * Minimalist Object Storage, (C) 2014 Minio, 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 erasure + +// #include +import "C" +import ( + "fmt" + "unsafe" +) + +// intSlice2CIntArray converts Go int slice to C int array +func intSlice2CIntArray(srcErrList []int) *C.int32_t { + var sizeErrInt = int(unsafe.Sizeof(srcErrList[0])) + switch sizeInt { + case sizeErrInt: + return (*C.int32_t)(unsafe.Pointer(&srcErrList[0])) + case sizeInt8: + int8Array := make([]int8, len(srcErrList)) + for i, v := range srcErrList { + int8Array[i] = int8(v) + } + return (*C.int32_t)(unsafe.Pointer(&int8Array[0])) + case sizeInt16: + int16Array := make([]int16, len(srcErrList)) + for i, v := range srcErrList { + int16Array[i] = int16(v) + } + return (*C.int32_t)(unsafe.Pointer(&int16Array[0])) + case sizeInt32: + int32Array := make([]int32, len(srcErrList)) + for i, v := range srcErrList { + int32Array[i] = int32(v) + } + return (*C.int32_t)(unsafe.Pointer(&int32Array[0])) + case sizeInt64: + int64Array := make([]int64, len(srcErrList)) + for i, v := range srcErrList { + int64Array[i] = int64(v) + } + return (*C.int32_t)(unsafe.Pointer(&int64Array[0])) + default: + panic(fmt.Sprintf("Unsupported: %d", sizeInt)) + } +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/doc.go b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/doc.go new file mode 100644 index 000000000..ce47fb64d --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/doc.go @@ -0,0 +1,67 @@ +// Package erasure is a Go wrapper for the Intel Intelligent Storage +// Acceleration Library (Intel ISA-L). Intel ISA-L is a CPU optimized +// implementation of erasure coding algorithms. +// +// For more information on Intel ISA-L, please visit: +// https://01.org/intel%C2%AE-storage-acceleration-library-open-source-version +// +// Usage: +// +// Encode encodes a block of data. The input is the original data. The output +// is a 2 tuple containing (k + m) chunks of erasure encoded data and the +// length of the original object. +// +// Decode decodes 2 tuple data containing (k + m) chunks back into its original form. +// Additionally original block length should also be provided as input. +// +// Decoded data is exactly similar in length and content as the original data. +// +// Encoding data may be performed in 3 steps. +// +// 1. Create a parse set of encoder parameters +// 2. Create a new encoder +// 3. Encode data +// +// Decoding data is also performed in 3 steps. +// +// 1. Create a parse set of encoder parameters for validation +// 2. Create a new encoder +// 3. Decode data +// +// Erasure parameters contain three configurable elements: +// ValidateParams(k, m, technique int) (ErasureParams, error) +// k - Number of rows in matrix +// m - Number of colums in matrix +// technique - Matrix type, can be either Cauchy (recommended) or Vandermonde +// constraints: k + m < Galois Field (2^8) +// +// Choosing right parity and matrix technique is left for application to decide. +// +// But here are the few points to keep in mind +// +// Techniques: +// - Vandermonde is most commonly used method for choosing coefficients in erasure +// encoding but does not guarantee invertable for every sub matrix. +// Users may want to adjust for k > 5. (k is data blocks) +// - Whereas Cauchy is our recommended method for choosing coefficients in erasure coding. +// Since any sub-matrix of a Cauchy matrix is invertable. +// +// Total blocks: +// - Data blocks and Parity blocks should not be greater than 'Galois Field' (2^8) +// +// Example +// +// Creating and using an encoder +// var bytes []byte +// params := erasure.ValidateParams(10, 5, erasure.Cauchy) +// encoder := erasure.NewErasure(params) +// encodedData, length := encoder.Encode(bytes) +// +// Creating and using a decoder +// var encodedData [][]byte +// var length int +// params := erasure.ValidateParams(10, 5, erasure.Cauchy) +// encoder := erasure.NewErasure(params) +// originalData, err := encoder.Decode(encodedData, length) +// +package erasure diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/docs/isa-l_open_src_2.10.pdf b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/docs/isa-l_open_src_2.10.pdf new file mode 100644 index 000000000..b2d6e1447 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/docs/isa-l_open_src_2.10.pdf @@ -0,0 +1,5429 @@ +%PDF-1.4 +%ÐÔÅØ +5 0 obj +<< /S /GoTo /D (chapter.1) >> +endobj +8 0 obj +(\376\377\000S\000t\000o\000r\000a\000g\000e\000\040\000L\000i\000b\000r\000a\000r\000y) +endobj +9 0 obj +<< /S /GoTo /D (section.1.1) >> +endobj +12 0 obj +(\376\377\000A\000b\000o\000u\000t\000\040\000T\000h\000i\000s\000\040\000D\000o\000c\000u\000m\000e\000n\000t) +endobj +13 0 obj +<< /S /GoTo /D (section.1.2) >> +endobj +16 0 obj +(\376\377\000O\000v\000e\000r\000v\000i\000e\000w) +endobj +17 0 obj +<< /S /GoTo /D (section.1.3) >> +endobj +20 0 obj +(\376\377\000E\000r\000a\000s\000u\000r\000e\000\040\000C\000o\000d\000e\000\040\000F\000u\000n\000c\000t\000i\000o\000n\000s) +endobj +21 0 obj +<< /S /GoTo /D (section.1.4) >> +endobj +24 0 obj +(\376\377\000S\000y\000s\000t\000e\000m\000\040\000R\000e\000q\000u\000i\000r\000e\000m\000e\000n\000t\000s) +endobj +25 0 obj +<< /S /GoTo /D (chapter.2) >> +endobj +28 0 obj +(\376\377\000F\000u\000n\000c\000t\000i\000o\000n\000\040\000V\000e\000r\000s\000i\000o\000n\000\040\000N\000u\000m\000b\000e\000r\000s) +endobj +29 0 obj +<< /S /GoTo /D (section.2.1) >> +endobj +32 0 obj +(\376\377\000F\000u\000n\000c\000t\000i\000o\000n\000\040\000V\000e\000r\000s\000i\000o\000n\000\040\000N\000u\000m\000b\000e\000r\000s) +endobj +33 0 obj +<< /S /GoTo /D (section.2.2) >> +endobj +36 0 obj +(\376\377\000F\000u\000n\000c\000t\000i\000o\000n\000\040\000V\000e\000r\000s\000i\000o\000n\000\040\000N\000u\000m\000b\000e\000r\000s\000\040\000T\000a\000b\000l\000e\000s) +endobj +37 0 obj +<< /S /GoTo /D (chapter.3) >> +endobj +40 0 obj +(\376\377\000I\000n\000s\000t\000r\000u\000c\000t\000i\000o\000n\000\040\000S\000e\000t\000\040\000R\000e\000q\000u\000i\000r\000e\000m\000e\000n\000t\000s) +endobj +41 0 obj +<< /S /GoTo /D (chapter.4) >> +endobj +44 0 obj +(\376\377\000F\000i\000l\000e\000\040\000I\000n\000d\000e\000x) +endobj +45 0 obj +<< /S /GoTo /D (section.4.1) >> +endobj +48 0 obj +(\376\377\000F\000i\000l\000e\000\040\000L\000i\000s\000t) +endobj +49 0 obj +<< /S /GoTo /D (chapter.5) >> +endobj +52 0 obj +(\376\377\000F\000i\000l\000e\000\040\000D\000o\000c\000u\000m\000e\000n\000t\000a\000t\000i\000o\000n) +endobj +53 0 obj +<< /S /GoTo /D (section.5.1) >> +endobj +56 0 obj +(\376\377\000e\000r\000a\000s\000u\000r\000e\000\137\000c\000o\000d\000e\000.\000h\000\040\000F\000i\000l\000e\000\040\000R\000e\000f\000e\000r\000e\000n\000c\000e) +endobj +57 0 obj +<< /S /GoTo /D (subsection.5.1.1) >> +endobj +60 0 obj +(\376\377\000D\000e\000t\000a\000i\000l\000e\000d\000\040\000D\000e\000s\000c\000r\000i\000p\000t\000i\000o\000n) +endobj +61 0 obj +<< /S /GoTo /D (subsection.5.1.2) >> +endobj +64 0 obj +(\376\377\000F\000u\000n\000c\000t\000i\000o\000n\000\040\000D\000o\000c\000u\000m\000e\000n\000t\000a\000t\000i\000o\000n) +endobj +65 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.1) >> +endobj +68 0 obj +(\376\377\000e\000c\000\137\000e\000n\000c\000o\000d\000e\000\137\000d\000a\000t\000a) +endobj +69 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.2) >> +endobj +72 0 obj +(\376\377\000e\000c\000\137\000e\000n\000c\000o\000d\000e\000\137\000d\000a\000t\000a\000\137\000b\000a\000s\000e) +endobj +73 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.3) >> +endobj +76 0 obj +(\376\377\000e\000c\000\137\000e\000n\000c\000o\000d\000e\000\137\000d\000a\000t\000a\000\137\000s\000s\000e) +endobj +77 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.4) >> +endobj +80 0 obj +(\376\377\000e\000c\000\137\000i\000n\000i\000t\000\137\000t\000a\000b\000l\000e\000s) +endobj +81 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.5) >> +endobj +84 0 obj +(\376\377\000g\000f\000\137\0002\000v\000e\000c\000t\000\137\000d\000o\000t\000\137\000p\000r\000o\000d\000\137\000a\000v\000x) +endobj +85 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.6) >> +endobj +88 0 obj +(\376\377\000g\000f\000\137\0002\000v\000e\000c\000t\000\137\000d\000o\000t\000\137\000p\000r\000o\000d\000\137\000a\000v\000x\0002) +endobj +89 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.7) >> +endobj +92 0 obj +(\376\377\000g\000f\000\137\0002\000v\000e\000c\000t\000\137\000d\000o\000t\000\137\000p\000r\000o\000d\000\137\000s\000s\000e) +endobj +93 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.8) >> +endobj +96 0 obj +(\376\377\000g\000f\000\137\0003\000v\000e\000c\000t\000\137\000d\000o\000t\000\137\000p\000r\000o\000d\000\137\000a\000v\000x) +endobj +97 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.9) >> +endobj +100 0 obj +(\376\377\000g\000f\000\137\0003\000v\000e\000c\000t\000\137\000d\000o\000t\000\137\000p\000r\000o\000d\000\137\000a\000v\000x\0002) +endobj +101 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.10) >> +endobj +104 0 obj +(\376\377\000g\000f\000\137\0003\000v\000e\000c\000t\000\137\000d\000o\000t\000\137\000p\000r\000o\000d\000\137\000s\000s\000e) +endobj +105 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.11) >> +endobj +108 0 obj +(\376\377\000g\000f\000\137\0004\000v\000e\000c\000t\000\137\000d\000o\000t\000\137\000p\000r\000o\000d\000\137\000a\000v\000x) +endobj +109 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.12) >> +endobj +112 0 obj +(\376\377\000g\000f\000\137\0004\000v\000e\000c\000t\000\137\000d\000o\000t\000\137\000p\000r\000o\000d\000\137\000a\000v\000x\0002) +endobj +113 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.13) >> +endobj +116 0 obj +(\376\377\000g\000f\000\137\0004\000v\000e\000c\000t\000\137\000d\000o\000t\000\137\000p\000r\000o\000d\000\137\000s\000s\000e) +endobj +117 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.14) >> +endobj +120 0 obj +(\376\377\000g\000f\000\137\0005\000v\000e\000c\000t\000\137\000d\000o\000t\000\137\000p\000r\000o\000d\000\137\000a\000v\000x) +endobj +121 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.15) >> +endobj +124 0 obj +(\376\377\000g\000f\000\137\0005\000v\000e\000c\000t\000\137\000d\000o\000t\000\137\000p\000r\000o\000d\000\137\000a\000v\000x\0002) +endobj +125 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.16) >> +endobj +128 0 obj +(\376\377\000g\000f\000\137\0005\000v\000e\000c\000t\000\137\000d\000o\000t\000\137\000p\000r\000o\000d\000\137\000s\000s\000e) +endobj +129 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.17) >> +endobj +132 0 obj +(\376\377\000g\000f\000\137\0006\000v\000e\000c\000t\000\137\000d\000o\000t\000\137\000p\000r\000o\000d\000\137\000a\000v\000x) +endobj +133 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.18) >> +endobj +136 0 obj +(\376\377\000g\000f\000\137\0006\000v\000e\000c\000t\000\137\000d\000o\000t\000\137\000p\000r\000o\000d\000\137\000a\000v\000x\0002) +endobj +137 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.19) >> +endobj +140 0 obj +(\376\377\000g\000f\000\137\0006\000v\000e\000c\000t\000\137\000d\000o\000t\000\137\000p\000r\000o\000d\000\137\000s\000s\000e) +endobj +141 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.20) >> +endobj +144 0 obj +(\376\377\000g\000f\000\137\000g\000e\000n\000\137\000c\000a\000u\000c\000h\000y\0001\000\137\000m\000a\000t\000r\000i\000x) +endobj +145 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.21) >> +endobj +148 0 obj +(\376\377\000g\000f\000\137\000g\000e\000n\000\137\000r\000s\000\137\000m\000a\000t\000r\000i\000x) +endobj +149 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.22) >> +endobj +152 0 obj +(\376\377\000g\000f\000\137\000i\000n\000v) +endobj +153 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.23) >> +endobj +156 0 obj +(\376\377\000g\000f\000\137\000i\000n\000v\000e\000r\000t\000\137\000m\000a\000t\000r\000i\000x) +endobj +157 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.24) >> +endobj +160 0 obj +(\376\377\000g\000f\000\137\000m\000u\000l) +endobj +161 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.25) >> +endobj +164 0 obj +(\376\377\000g\000f\000\137\000v\000e\000c\000t\000\137\000d\000o\000t\000\137\000p\000r\000o\000d) +endobj +165 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.26) >> +endobj +168 0 obj +(\376\377\000g\000f\000\137\000v\000e\000c\000t\000\137\000d\000o\000t\000\137\000p\000r\000o\000d\000\137\000a\000v\000x) +endobj +169 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.27) >> +endobj +172 0 obj +(\376\377\000g\000f\000\137\000v\000e\000c\000t\000\137\000d\000o\000t\000\137\000p\000r\000o\000d\000\137\000a\000v\000x\0002) +endobj +173 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.28) >> +endobj +176 0 obj +(\376\377\000g\000f\000\137\000v\000e\000c\000t\000\137\000d\000o\000t\000\137\000p\000r\000o\000d\000\137\000b\000a\000s\000e) +endobj +177 0 obj +<< /S /GoTo /D (subsubsection.5.1.2.29) >> +endobj +180 0 obj +(\376\377\000g\000f\000\137\000v\000e\000c\000t\000\137\000d\000o\000t\000\137\000p\000r\000o\000d\000\137\000s\000s\000e) +endobj +181 0 obj +<< /S /GoTo /D (section.5.2) >> +endobj +184 0 obj +(\376\377\000g\000f\000\137\000v\000e\000c\000t\000\137\000m\000u\000l\000.\000h\000\040\000F\000i\000l\000e\000\040\000R\000e\000f\000e\000r\000e\000n\000c\000e) +endobj +185 0 obj +<< /S /GoTo /D (subsection.5.2.1) >> +endobj +188 0 obj +(\376\377\000D\000e\000t\000a\000i\000l\000e\000d\000\040\000D\000e\000s\000c\000r\000i\000p\000t\000i\000o\000n) +endobj +189 0 obj +<< /S /GoTo /D (subsection.5.2.2) >> +endobj +192 0 obj +(\376\377\000F\000u\000n\000c\000t\000i\000o\000n\000\040\000D\000o\000c\000u\000m\000e\000n\000t\000a\000t\000i\000o\000n) +endobj +193 0 obj +<< /S /GoTo /D (subsubsection.5.2.2.1) >> +endobj +196 0 obj +(\376\377\000g\000f\000\137\000v\000e\000c\000t\000\137\000m\000u\000l) +endobj +197 0 obj +<< /S /GoTo /D (subsubsection.5.2.2.2) >> +endobj +200 0 obj +(\376\377\000g\000f\000\137\000v\000e\000c\000t\000\137\000m\000u\000l\000\137\000a\000v\000x) +endobj +201 0 obj +<< /S /GoTo /D (subsubsection.5.2.2.3) >> +endobj +204 0 obj +(\376\377\000g\000f\000\137\000v\000e\000c\000t\000\137\000m\000u\000l\000\137\000b\000a\000s\000e) +endobj +205 0 obj +<< /S /GoTo /D (subsubsection.5.2.2.4) >> +endobj +208 0 obj +(\376\377\000g\000f\000\137\000v\000e\000c\000t\000\137\000m\000u\000l\000\137\000i\000n\000i\000t) +endobj +209 0 obj +<< /S /GoTo /D (subsubsection.5.2.2.5) >> +endobj +212 0 obj +(\376\377\000g\000f\000\137\000v\000e\000c\000t\000\137\000m\000u\000l\000\137\000s\000s\000e) +endobj +213 0 obj +<< /S /GoTo /D (section.5.3) >> +endobj +216 0 obj +(\376\377\000t\000y\000p\000e\000s\000.\000h\000\040\000F\000i\000l\000e\000\040\000R\000e\000f\000e\000r\000e\000n\000c\000e) +endobj +217 0 obj +<< /S /GoTo /D (subsection.5.3.1) >> +endobj +220 0 obj +(\376\377\000D\000e\000t\000a\000i\000l\000e\000d\000\040\000D\000e\000s\000c\000r\000i\000p\000t\000i\000o\000n) +endobj +221 0 obj +<< /S /GoTo /D [222 0 R /Fit ] >> +endobj +225 0 obj << +/Length 384 +/Filter /FlateDecode +>> +stream +xÚSËNÃ0¼ç+ö˜HØxýö±ˆ‡Š@@q)=„6E•ÒLâﱓ"Ô^P$¯2žÌŒ7k/Àà*a*†•‚”CŠÜÀj—¼ýlÄõp:Ý!œ7ÉCxe…F…ÑR‡ª•µ>xÙšýZ“èMFægyrz)8ð@Ö\A¾ÃA¡¢‘™¯a‘N붬²e~ÝQR!5DÉ©´ •ÎõÔ'®ôs$‰šZT@FÔNµÚ¾dYZÖmF¸±é¼m|‘dÀ{t²Z•Ué‹vÛÔ=r³}ö…ï8_Ñ0ž‰rg€pA•C¦ØñôŽ +ýïôó ¹ òØÇ¹{-‡`óæÃgœ¥«!úc¦Â1|†*}é÷òŽ:ÍuT'ZS41y¨|èùä~Ú?+7±¥/ë½ämQG裨úwrØ©9E=“‹|4VáËÐ/-â,– Ö¾Žsã,|v¤HmC­`†®Ÿ5J%$RËÌøÕo‡<ödðf(;ovä>„Lßì;·— +endstream +endobj +222 0 obj << +/Type /Page +/Contents 225 0 R +/Resources 224 0 R +/MediaBox [0 0 612 792] +/Parent 229 0 R +>> endobj +223 0 obj << +/Type /XObject +/Subtype /Form +/FormType 1 +/PTEX.FileName (./intel_4c_100.pdf) +/PTEX.PageNumber 1 +/PTEX.InfoDict 230 0 R +/BBox [0 0 102 77] +/Resources << +/ProcSet [ /PDF ] +/ExtGState << +/R7 231 0 R +>>>> +/Length 232 0 R +/Filter /FlateDecode +>> +stream +xœmWI²5Ü×)t!½AÃ1à +`"h/€ÎO¦¦*÷wxQ?³%½9%ÿRÌ!ñßú¾¾_¿üV÷/਽÷$ㇿ.k-z+!÷‹yø~©•¨ÉCn]ðC‹)µ Écî k¢4cY«áuåRcª`jÆŠŽÜ‚I*D&Mׂ„ÞA" \oùÆ´«ÜŒ£Á=Ã-( õó`¨‡'Îèf F©^!~øEúRrŽal 7G§Ù½•)¸iÿ©µÅÑÂe«Øgb"ŠíÆvte¦9ÛÙ7áT]  e Ük˜ØIÁ|vçàãƒõ¹ I4A!ÔŽÝÃ1Ù1§Î$±¼c6'X*÷:•µãè->|¤Êh[s°ú£û—Áf,Í„ÒqVó`ØÀ$p–ÃΓ1;fPTåW†»J±'#e”ÚpéÀå1\è^˜}#H¸P£í1{›¹m(T—÷ÔWæžÆÏx9%•­Â³™açí]QÖ)ÛÌÖsê3‹xp÷qYߊïT|d|Ÿ°UuÛØ;Po-·îVˆ!'ðÃÆf¶ë„ãåG¼:]è¿CSòÊa*e‰wÈ2Ÿ?ìn¦1FÆ6O è6¼+n»cGí+kEóÑË焱Mæx±N8^~Ä1cí_f>8ˆ r0†|1ïÁTm‡!æÍKÌËŠxÜÀ¥–Ọ¿¬ëе÷`óE&3ïÀbsÄc2æó~¿WÌGÏÆÿaEÂý›+ÐýRÀ¦?9‰Uû÷“ »„B¹ÙB„[º1Ë8å⑲«=öÊó9ò†}<ÿÁMc¾‹5Îë|ŽáÆGBh‘ºNLiã ¢˜ÃËc'†¸ÌÌ*žh ¾NAÏï¨xªsFr9ØzÍΛÌ4ô~0e¨d­{vm¼ÅhbLQ×õ,®-­§@¯7¸þAa˜:zñÆ|ÏÌ#6ã}®g¦?Zw¶3žéUN0ßã¼G¸>Bàð)±[uãÙ¼3{EÂïaß;ÒÑç +Ó fùØ@†ù¤’¾Ï›ÙN œ=Ü51ϘÜ+vèó?7žU|}Iu;…oׯ×ÿ^§ +endstream +endobj +230 0 obj +<< +/Producer (GPL Ghostscript 8.71) +/CreationDate (D:20100929095736-07'00') +/ModDate (D:20100929095736-07'00') +/Creator (Adobe Illustrator\(R\) 8.0) +/Author (\(L.P Thebault\) \(L.P. Thebault Company\)) +/Title (\(intel_4c_100.eps\)) +>> +endobj +231 0 obj +<< +/Type /ExtGState +/OPM 1 +>> +endobj +232 0 obj +1336 +endobj +226 0 obj << +/D [222 0 R /XYZ 72 668.127 null] +>> endobj +224 0 obj << +/Font << /F32 227 0 R /F35 228 0 R >> +/XObject << /Im1 223 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +236 0 obj << +/Length 1840 +/Filter /FlateDecode +>> +stream +xÚ¥XQs£F ~ϯ`“À€í¾ù0‰¹:¶ ¸éMÛŒ71= >Àͤ¿¾ÒJkÇw3>í®¤•¾Õ'-^›Ú³fj÷W¦aö­þ@3þÀs<=w8´´ÔßPE°ëíþ˜\ÝÞhdŒ<ÛÓ’'Íí»†i4o82–£%íwÝêý™|:† +’«¯WLMÍÒ6˜ºÆÈjÙîê÷?MmòOl4Ô^¤ÕNs¼!Œ…_ýrtC±ÚÀ L cƒ/×´ 6ʰáün=Œ{–eéI¸˜÷núÞ¤4&Ó0¦ÙdᯂyÂz–.£žcꋞk꿆“`ÒÝ=ÒýÅ|ø'¯a2UI0{ãb²ò“Ø Ñ|Aã,ôƒy\Ó*øm1^D"|èYú ¦Î{32Ó¹œ…ÁvÚÎ@ÿø™Æ Nzì].18JÐC2 ¢žëLÓvàüÒžlÆsv#ÁÏà`+Ü5fW|Ž%øðÀÛFáý4‰y÷Ñ +¦ôw2½ ‹Wþ”D]š®»n¥vÇ€™ÁHúd”ñÇpb*Pü8å*‹Á¯AÄNÆóÉöصÝ7õIû³qøÓ’X°G§r@©äÆðAòN‹ÇžeÆÓýæ#ýšQ0S?¿'Ñ‘h˜ÇãY@1Ü­r½Â|ÉXw넱›¥ôg« `é÷xë¦Æ&ø}Ûzƒ8”é´ß¡E;…Õwa2§¶‡>h½DÖÇT‘¡¿šY½\EËuX=‘?…½0ɸ8]]tpUD!À–ÃRyO›L«H‚ Å'ô\ÒפñËϲ9h)³Œã±åòB«¹æ¥V)y“MÃÈ,×°ú m5ŸQ–,ç}·“øØZSû8úcrêañQV³KÈ®I®Ôîç¬$¤ûˆ­æŸ“ ïç*äœ<Í'J|§Ä˜Ø÷i/¡êýînL ߆+òqb£HEÙæiÎVˆ 5’9PÅàTÝ ë…tþb5›ÎE/éÆ$C¦ì Ô#d1}1ˆû.ñ*c~Z¥®þ™AEZg¢N‰vüv™´ëÇ÷WÑÅËV`4ìë»ôUM¾Àf]àÊѳmZ>‹†TmEc³Yþ‡iÚYÚæUÉÚ´ÜÐd_W›CÖ’ƒh²:ßwíZe߃šá¨m¾ØÐ/y»­lTVmž ¸òÀ4Mþ\ŠšíÍÉŠ&µ(^)nU²ã­àpëF”/ªšF8^f—¾•­¨óbc¬«WO8:Ð |i{¨…2©É$/›¶†óó‰A³KkÊé†Ö`¨ÿFObóvÑnÐÊÀÜ–bc| ™¢ Ì:;Ù9°ŒGAx: .²·ñ„ˆ³f›ɶin5rL’²¢"îñ$–ž¯ó"o_/ÔßË6m›Jôl—] ·Ï€\[ϪPôó¬mH£y™U»=”‘ô V§ü¼|&›§ºÚ±?u.ty¬L—+„Œþ`‚OA"‰]^ŒàO9 ÛŠZiÚÙÖ Y´wƒd§²ű,1Ò¤: +/’Ì~ZäÿêÆ”†¬eš£kšµ[Âc2j ùbëÊãõ‡–ê¶W6·Û+ •yIbò‹’M•v¢lI.»Å@P›*k…MÚ‹'qôެ¡PÔuU³ì  +ðþÂö)‹Á$mS’½lól{0=4B{{–V +€,«> endobj +233 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [135.019 309.334 337.859 318.456] +/Subtype/Link/A<> +>> endobj +234 0 obj << +/Font << /F46 237 0 R /F47 238 0 R /F48 239 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +275 0 obj << +/Length 824 +/Filter /FlateDecode +>> +stream +xÚíšKo›@…÷ù³„tÞ3,Û¼”*j¥Äê&ª†I‚C +8Mþ}ÇfŒM° ÔQ"Vƶ†çœ{/Q ¸œAóúmrôåŒr€©+¤@`r ̃.L"pc§I¡’"·O¾ëu -/.®ÎËåžëqÌ«!p8r÷ÊÅÈv„к.Ò,¸S¶ƒ´.ãid/æ†åAåÄ…ÈÓoÌÂÛ‰íJ¥ B®Ç˜Yì.÷Õ[}¦ó¢ÜurçåÕIÎgú'Õp£¿ã–k;LŸ÷°^¨ç½û=‘Àb§J ÔÁFŸO6b–Êžbecfý}­ðÄajðI2ýŸZĨušù<3±=N#su6OÂ"N“üµz„ŽÒ¼»Ôˆqý’jV*p¥þÌãLÍ6 +s%ecLúi»õ6Q×£8Xëƒd©6n•‰RŸ_¶þP—¹¼úäÇ|6Õï[›Ù§éáªé5Ž‚ÐÛG¹q¸ £EvY„tŒ+®:]WÊáÄ–Ð +¦ª¡Š$b°,ÉÓ=ÂIL8/’¼Èær\«b³ÚHZÛ‹)ÁDR‹µ¨¿¹]ƒøÁ´Ê‹$RÏ­¡û„ž®C_myçÑ–I9رꃦ+±‡OYÃ7«g”`éÙ6ÿÈ}üÃ*ÿ¨rÔóC=å¹÷fΫŽs¥nU¦’P5Êâ£3Ö&Ø%ÀX«Mð—ø±¾Á‰*M;2ê«<ÌâǦöºK{#ð:w¼˜¦á[ý™¯™cüޡ[§ë'–#çVιR¢¦Á˱”,*Lèë +¢Ë‹EÐxðçô {Ä;X¸Fo¥êOƒ¼Q£ÅŸJõ¢H¶SÌ›Ńsd?–tÍ2NâÂ/¶?ÏP6„‘ðm¸¸\fàÞÝú¸üjXøQZøYù¡õôܘAÖ[¿Ë»€Ä ×JtÈI//ŠV„[j§$d>ìQ®!’1Ð5´H¯ È¡ºB=z:r'ÂÁšõj,zZZA¤c k y?7â ‡èžIÂÁZôƒH+ˆl ô> YC ´ì‡·!l ½~ZTùè­ ëÿx:9ú^Vý× +endstream +endobj +274 0 obj << +/Type /Page +/Contents 275 0 R +/Resources 273 0 R +/MediaBox [0 0 612 792] +/Parent 229 0 R +/Annots [ 240 0 R 241 0 R 242 0 R 243 0 R 244 0 R 245 0 R 246 0 R 247 0 R 248 0 R 249 0 R 250 0 R 251 0 R 252 0 R 253 0 R 254 0 R 255 0 R 256 0 R 257 0 R 258 0 R 259 0 R 260 0 R 261 0 R 262 0 R 263 0 R 264 0 R 265 0 R 266 0 R 267 0 R 268 0 R 269 0 R 270 0 R 271 0 R ] +>> endobj +240 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [71.004 525.49 156.841 536.369] +/Subtype /Link +/A << /S /GoTo /D (chapter.1) >> +>> endobj +241 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [85.948 515.457 199.959 524.304] +/Subtype /Link +/A << /S /GoTo /D (section.1.1) >> +>> endobj +242 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [85.948 503.502 149.738 512.349] +/Subtype /Link +/A << /S /GoTo /D (section.1.2) >> +>> endobj +243 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [85.948 491.547 206.594 500.394] +/Subtype /Link +/A << /S /GoTo /D (section.1.3) >> +>> endobj +244 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [85.948 477.535 198.026 488.439] +/Subtype /Link +/A << /S /GoTo /D (section.1.4) >> +>> endobj +245 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [71.004 457.654 202.619 466.63] +/Subtype /Link +/A << /S /GoTo /D (chapter.2) >> +>> endobj +246 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [85.948 445.719 218.221 454.566] +/Subtype /Link +/A << /S /GoTo /D (section.2.1) >> +>> endobj +247 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [85.948 433.764 246.474 442.61] +/Subtype /Link +/A << /S /GoTo /D (section.2.2) >> +>> endobj +248 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [71.004 409.923 213.388 420.802] +/Subtype /Link +/A << /S /GoTo /D (chapter.3) >> +>> endobj +249 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [71.004 389.908 130.839 398.884] +/Subtype /Link +/A << /S /GoTo /D (chapter.4) >> +>> endobj +250 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [85.948 377.973 144.348 386.82] +/Subtype /Link +/A << /S /GoTo /D (section.4.1) >> +>> endobj +251 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [71.004 356.035 171.785 365.011] +/Subtype /Link +/A << /S /GoTo /D (chapter.5) >> +>> endobj +252 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [85.948 343.019 231.74 352.947] +/Subtype /Link +/A << /S /GoTo /D (section.5.1) >> +>> endobj +253 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 330.087 225.463 340.991] +/Subtype /Link +/A << /S /GoTo /D (subsection.5.1.1) >> +>> endobj +254 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 320.19 242.081 329.036] +/Subtype /Link +/A << /S /GoTo /D (subsection.5.1.2) >> +>> endobj +255 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 307.153 247.203 317.081] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.1) >> +>> endobj +256 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 295.198 269.887 305.126] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.2) >> +>> endobj +257 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 283.243 264.358 293.171] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.3) >> +>> endobj +258 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 271.288 238.923 281.216] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.4) >> +>> endobj +259 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 258.356 278.416 269.26] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.5) >> +>> endobj +260 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 246.401 283.397 257.305] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.6) >> +>> endobj +261 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 234.446 276.403 245.35] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.7) >> +>> endobj +262 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 222.491 278.416 233.395] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.8) >> +>> endobj +263 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 210.536 283.397 221.44] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.9) >> +>> endobj +264 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 198.581 276.403 209.485] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.10) >> +>> endobj +265 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 186.625 278.416 197.529] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.11) >> +>> endobj +266 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 174.67 283.397 185.574] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.12) >> +>> endobj +267 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 162.715 276.403 173.619] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.13) >> +>> endobj +268 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 150.76 278.416 161.664] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.14) >> +>> endobj +269 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 138.805 283.397 149.709] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.15) >> +>> endobj +270 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 126.85 276.403 137.754] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.16) >> +>> endobj +271 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 114.894 278.416 125.798] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.17) >> +>> endobj +273 0 obj << +/Font << /F46 237 0 R /F47 238 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +299 0 obj << +/Length 690 +/Filter /FlateDecode +>> +stream +xÚíÙMs¢0ð;Ÿ"G8˜Í“÷\wû2ÓCw¶åÖé8.Ò–™Š.b·ýö°µ+•¾¨<…ŒÉÇøt‹:õ& ˜B3%¹´­ZÊìå†K§Þ÷ÐûvbOl$•(¼AŠ"© VÀQ8DWþŸçáñyx\‡gy×›!.)æle×I²ÔéqèýñŠ‹Á|ªQ4ò®® ÚógE·F£¿å]#Û¡¶í=ºô~½Ž­|}1’ò`1Iõß$VÌ ;4 òy¦¦tÐÓ‚ø·7}ù€ðã(ïÇy’‡ýA@‰ÿðH—Ž®zv†>z‚Ïj¸1Ÿüµ Pª|Jžç[•µm!–Í*Âé4vôÛÎl¾¢½ýñ6NûÑ`Ý‚þhgÉcÕ3ÑChgK†Ù´ÁN²‹)íHò= tš¤·K¡óQ¦»œÓþj/¡ÓvèÌA/ÖÔ,oZ ¨î,ó†¾rÉ—/|G³ûª¦8ô´X€;ñÀYOˆèj³v¨²õ%¶Vq™†.¨¾‰S­çtv’A y;H½ò÷ÀÝ (¥ˆÕ¯(³±fC%4ëÎ[4QöÇʈjUÚ ¤‚i¿øñ]УöôIrÏ.â›8‹ÓÈáed_3ÁŽÙšA)6À瀡x¥íá(ÎV}8g?ЧQ–Lòdœ: ¬‘x^n¼"Ó²ú ó“Y•Äsóq4Åi>¨S;ÝPìÅb´Æ™.~ãt±Ëgîbã6öo®è²¦k›b¯a²«®jãØQ¸²׺ضíȱGDµ*VÞ€š¤I^E¥Jv|!hg+lk"2Ó]ÿ•L·ÌÍì97çO“xÚ"-M¾|hÛV’Óí"4;D膯ÿ+ÁÒ¼–Eÿƒc1¡ +endstream +endobj +298 0 obj << +/Type /Page +/Contents 299 0 R +/Resources 297 0 R +/MediaBox [0 0 612 792] +/Parent 229 0 R +/Annots [ 272 0 R 276 0 R 277 0 R 278 0 R 279 0 R 280 0 R 281 0 R 282 0 R 283 0 R 284 0 R 285 0 R 286 0 R 287 0 R 288 0 R 289 0 R 290 0 R 291 0 R 292 0 R 293 0 R 294 0 R 295 0 R 296 0 R ] +>> endobj +272 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 655.011 283.397 665.915] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.18) >> +>> endobj +276 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 643.056 276.403 653.96] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.19) >> +>> endobj +277 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 631.101 280.368 642.005] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.20) >> +>> endobj +278 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 619.146 254.415 630.05] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.21) >> +>> endobj +279 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 607.191 209.196 618.095] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.22) >> +>> endobj +280 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 595.235 250.55 606.139] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.23) >> +>> endobj +281 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 583.28 212.364 594.184] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.24) >> +>> endobj +282 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 571.325 254.266 582.229] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.25) >> +>> endobj +283 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 559.37 273.435 570.274] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.26) >> +>> endobj +284 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 547.415 278.416 558.319] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.27) >> +>> endobj +285 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 535.46 276.951 546.364] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.28) >> +>> endobj +286 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 523.504 271.422 534.408] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.1.2.29) >> +>> endobj +287 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [85.948 511.549 229.399 522.453] +/Subtype /Link +/A << /S /GoTo /D (section.5.2) >> +>> endobj +288 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 499.594 225.463 510.498] +/Subtype /Link +/A << /S /GoTo /D (subsection.5.2.1) >> +>> endobj +289 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 489.696 242.081 498.543] +/Subtype /Link +/A << /S /GoTo /D (subsection.5.2.2) >> +>> endobj +290 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 475.684 233.793 486.588] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.2.2.1) >> +>> endobj +291 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 463.729 252.961 474.633] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.2.2.2) >> +>> endobj +292 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 451.773 256.478 462.677] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.2.2.3) >> +>> endobj +293 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 439.818 252.064 450.722] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.2.2.4) >> +>> endobj +294 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [140.742 427.863 250.949 438.767] +/Subtype /Link +/A << /S /GoTo /D (subsubsection.5.2.2.5) >> +>> endobj +295 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [85.948 415.908 200.218 426.812] +/Subtype /Link +/A << /S /GoTo /D (section.5.3) >> +>> endobj +296 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.862 403.953 225.463 414.857] +/Subtype /Link +/A << /S /GoTo /D (subsection.5.3.1) >> +>> endobj +297 0 obj << +/Font << /F46 237 0 R /F47 238 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +304 0 obj << +/Length 2318 +/Filter /FlateDecode +>> +stream +xÚ­XÝsܶ×_ÁGÞÔGüÉvò $’êŒgìHšN;všÁ‘8cy%y–Õ¿>»Ø<1‰œö‰Äbì绽/ôn.Bû ÂXÄ™q& _™æ¹ðz˜þ©Û›‹oï/^_§¹'² iâÝo½$‰ƒ8Ï=™¦A"Sï¾ò>øßýýòýýÕíje¹/V?Ýÿà­eiê­a­Œâ»»_%¡ÿîör‡þÍñ¿}óííåí* ýáÊ‹«û‹ÿ\:ô„—EžŒQ²Ü+÷~ +½ +è? °Eî=®½—Ⱦwwñ££q”â/~¬&…'’ Nd„šÀÖi‘€p '±Z‹0 ýËMwA¸(÷ïwõ@ßwåq¯ÛÑÈhy}d^2’¸eèFAKÚ‘ÇQáWv1ôPöõFóä¸Óô3tÛñq%B_õL9ôÝC¯öûº} BÝŽz%ü~kØJfSmE?ÝA÷j¬»–‡[únm‰ÔÁnrvpSozÕ?­dê«ušdþ>[€>õ„0^5êd›L:êEYFÒ#ù¡ïŽ]Ñ`óD³æP$8B™awl+bAùT·U½ŠRÿs]UCs;­*ÝÓüÇ0ŒÍëÇâó+­¶ô³óˆ ,;vãÓA qœþÝq³^Òr˜,AˆÖmÙ+MgGxJº^Ü|8q7ážL‡a‚¤nÄDÑ̤`^oa_š;¢‘b@§·ô×ëF«AÓüç•H}XEÇ#ßöláÜíqù—Ä1hTfÔ¨H,üÝBX5V”é é—ªiŒƒ#khàx1Ú|ŒRIt3lêÎsûÞ]¯Ø¢—e ÛÛFÊ[–Ñ >†ièî¤7w—ë·@ìö“j†ŽÿVQ¶¹TݨM£Ï|Qví¨jë_ÅÇj4Þ—Q·•f¾AôcÌèxfxs6 t\Q[¬‰kÞ}ÆhÎ!ÆáHá?¾^¦`1‘=7x67¸™?™fÏL Ó'›œš›·wL ï(ÜpßîØ—,Ã?@zq +7ÌÞf ËB¥*éÍYþáˆ]¤®^ÙÛ*’0?êb`0=œmÿ+…%±©Ÿ½•ö%aÃüÜÊ"£­Šæ˜8UÃNÝTi—ã7.¯Å*.~çïJ¬ô¥yÈËý¶3ØuzÌí#`î«M‡Ž´å›ûlù +{;‡u(wPÐ5ørþ;Žu«§·Îé,úÑ-h<=UŽPø•|b É’ÝìM27ï2ü +Çš–Ðh¸N“ÔÛjñÕŒfŸzi£¤€}”…ùiKš±0¿Ñ“ÉÙk0¹á‹Ìiû±P†‹v×kUÙG?¿ukhXé¼RØ-~K²Ý21–ÊÞIÜÂZÓØkÅ΢etÞ+ìc‘p à_U›tÛ>™×g $/ ÔDä¥à†Tﱋ±ŒÑȯµÕX™܆ãÿ†×Ný¢®æç(ú4úÔ)4DÚÕ;PFÌ–kÐK/C6æ„}’ Ò‚œÔ›IC=§ Lt耧ÉáʾöÑ èépŠÅóÀ™eôTK˜ƒ®'÷öÖ«h¼`V–ÚïÕýůC½„ +endstream +endobj +303 0 obj << +/Type /Page +/Contents 304 0 R +/Resources 302 0 R +/MediaBox [0 0 612 792] +/Parent 229 0 R +/Annots [ 300 0 R ] +>> endobj +300 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [176.401 286.23 248.649 297.188] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a590b5c35075aeea1243a9e4ef73a49d4) >> +>> endobj +305 0 obj << +/D [303 0 R /XYZ 72 686.127 null] +>> endobj +6 0 obj << +/D [303 0 R /XYZ 72 668.127 null] +>> endobj +307 0 obj << +/D [303 0 R /XYZ 74.491 618.224 null] +>> endobj +308 0 obj << +/D [303 0 R /XYZ 74.491 618.224 null] +>> endobj +10 0 obj << +/D [303 0 R /XYZ 72 618.224 null] +>> endobj +310 0 obj << +/D [303 0 R /XYZ 485.963 513.196 null] +>> endobj +14 0 obj << +/D [303 0 R /XYZ 72 495.348 null] +>> endobj +311 0 obj << +/D [303 0 R /XYZ 84.453 398.147 null] +>> endobj +18 0 obj << +/D [303 0 R /XYZ 72 382.356 null] +>> endobj +319 0 obj << +/D [303 0 R /XYZ 482.188 135.988 null] +>> endobj +302 0 obj << +/Font << /F58 306 0 R /F59 309 0 R /F47 238 0 R /F13 312 0 R /F11 313 0 R /F7 314 0 R /F8 315 0 R /F10 316 0 R /F1 317 0 R /F14 318 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +324 0 obj << +/Length 1196 +/Filter /FlateDecode +>> +stream +xÚ¥VÛnÜ6}߯Уˆh’’(ÉElÀq6MêÝ¢.â ÐJ\¯]6$åËßwx³¥íÚEÑAÃË gΜw.á˜ÄY€Qœ±„ÁŸ¥yN˯,]_.Î׋“÷0U ‚Q¬·AF–(#I°®ƒ/!AÉ2¢)WORñÎÊ×üû؈%ÉCÞñ^Éå×õ‡þ_ž ‹&˜0çҙ͋õâû‚€ˆb]LQAó ê_¾â †ùÚj‘fWörø·ÁjñÛÄ5šjQÿ\ðiÅ £>ú4CI‘M¢'O§¹ ÿHè€e6ÁÍP3k쪯›%MÃû¦ËvÅ1 ·c_©fè¥Ò°+Ÿìü®\RÞ/Ir»t¯UKÑ £´[ÄØGªéܲ˜údÖåXí¬T:ëjÇíD×ôM7vÞ°>DHð®[»°Z]LõIXsY‰fÃk»Þô.x]#è\Bà„ "M}àR‰ÑÄé¸ÄÕ”HG-§^òž —Þ?RÏ”‚[¡m Aµ•7¼4\K–‚0|Àrí`†u^ójèÀhí üTŠZÃòPZ–Ÿ¾•fÂPç륅+›[JÓƒ€¢hÄ;–¨SÙ™=KN +kSJï‚ÇÊ$M W½âí-M™Þð¡íÅPq)a‡ÚÕb‰‡­Ú5ŠWjÍÕØ@p›×"¹:‹)B þ±ãÚY +L±¬ÕLm–$lËMËíÊÖ¸BL£M£Ü¤gÿ0‚ÙégD@öˆ€8¸C," LcƒáMÑÊî/Çœ³(6½&ÈQ +G\W±S”þ‘ —Òã$‹h‚ +œÍ‰±¶Ê³êx3=u¦²#|uF>Ü'žö=„’4‘Úf#Jñd£äË,±ÉÐ2ï ²MèQÙ;á÷¾y´’T0© Þ¬ÕBU¶mÓß¹$)ñ«7o¹c›÷·ÀK?ë*Ê'!ÆYŒË|ÿß)µ?=9|+÷¼’(29Šü®Yšàøñq;Œà> âî„·Û“Çœý–›&°íë-z«)ƒ[ÇÞKkƄֆÓï u˜>sYï™´QywUóªEºVðá%`‚òçΚæ$³³>÷ ¥¸oƒox®—(@@'äÉ7ÅþÛZçìK_(…r¿oAÃàf¼9 ÚùØ´µI¯Þý‹§“¼÷λã¼þKù¼'¤ëgR [.\‹œÝMÆ]wq´¼”N¼'ˆ"lŽõâye·o¹‡µwȬ—À$]ù¢0Qb±Sbp¡rãLÉa·³Û¡õ×]k´®]Ó÷ŒSuv¸•>Z]ÝØ¾ÊÏ’»alâÆYÛB¹ ³† FE£öd·tÐ* Ü)Ñsx“º‰À/àAÙ;L?­ÐÁ›núp2¯¦IŸƒâ*˜Á¼ ¹µøë øÜÂ+wgŽ2¬»nOCju?ëä:B÷ÚŽ»}îŸoÄvÊÆRʱói%ϭ𣿃7œþ\¹<)¿³éýËBƒùÜÛ¹€þ™ªÜQ·Ó;¸$zó] +dF ´ÿñ]ú7Š´ ++ +endstream +endobj +323 0 obj << +/Type /Page +/Contents 324 0 R +/Resources 322 0 R +/MediaBox [0 0 612 792] +/Parent 229 0 R +/Annots [ 301 0 R 321 0 R 326 0 R ] +>> endobj +301 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [71.004 614.453 189.219 625.357] +/Subtype /Link +/A << /S /GoTo /D (requires) >> +>> endobj +321 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [444.171 496.134 540.996 507.038] +/Subtype/Link/A<> +>> endobj +326 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[0 1 1] +/Rect [71.004 484.802 336.01 495.083] +/Subtype/Link/A<> +>> endobj +325 0 obj << +/D [323 0 R /XYZ 72 686.127 null] +>> endobj +22 0 obj << +/D [323 0 R /XYZ 72 668.127 null] +>> endobj +322 0 obj << +/Font << /F46 237 0 R /F59 309 0 R /F47 238 0 R /F48 239 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +359 0 obj << +/Length 570 +/Filter /FlateDecode +>> +stream +xÚ…TK“š@¾ó+æÆ™af€Ãâ–îjÕšDÙä°µÔ©âa1æ×§qÐ8Ö®áÒúëþúmAO9KL<êùˆ`Ï—\‚”"(ªàõ'¯æOÖ0²c êcFGÑqîa/s)P” 7ûñùË·h4w\æ6sÞ£)r©„!Añ±d\Ž_gÑäëLGþÍcöú2»[£ÈúeQ NE>CÒëÈh•[oï%àŸv|ÃNQ9â2™¡…õýªi&:µçfBD9ö¸d]3Z„è1Ma긔b÷ŪQeÜu8±ÓʡԮ/ÎÙ>_ö¾ésÕÁ˜û(Ä¡d²«A´‡COê“"Qv«’}œA&Aìu_¬Öf\¥ZÙèH‡ +;-´KUÏʼnE<¨f«µfÛçX—U7ZÏs·mÝ|ÚP£‡¢ß¢{ŽÒòA‹È ±C‰]jd¿µ‘¨júê +Z[Å*67vU¹J뺬úþÌ®{ê]…¸ÏTî•«?iréÁÂÆÆ˜¯Æ\»opV{iLÂN ÑòA‹Yº³4Lãz{<ùÆe•ÖÍàeŸ5j©Š¸:ƒ’f>jäû È<…Ý}<Ú‚ˆE\$Çe¥’Í]g€&íQ+Ãÿ¹|ŽëCše÷¤§²6­ò²h:ÌÍY»Æ Í j[ã‚ÌErÁw²;Ø; ë´Rç/é_®›ÿã_ügþ °BS +endstream +endobj +358 0 obj << +/Type /Page +/Contents 359 0 R +/Resources 357 0 R +/MediaBox [0 0 612 792] +/Parent 364 0 R +>> endobj +360 0 obj << +/D [358 0 R /XYZ 72 686.127 null] +>> endobj +26 0 obj << +/D [358 0 R /XYZ 72 668.127 null] +>> endobj +361 0 obj << +/D [358 0 R /XYZ 74.491 618.224 null] +>> endobj +362 0 obj << +/D [358 0 R /XYZ 76.981 618.224 null] +>> endobj +30 0 obj << +/D [358 0 R /XYZ 72 618.224 null] +>> endobj +363 0 obj << +/D [358 0 R /XYZ 196.601 431.811 null] +>> endobj +34 0 obj << +/D [358 0 R /XYZ 72 416.02 null] +>> endobj +357 0 obj << +/Font << /F58 306 0 R /F59 309 0 R /F47 238 0 R /F48 239 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +367 0 obj << +/Length 1462 +/Filter /FlateDecode +>> +stream +xÚµ™MoÛF†ïú W~ýz÷‘Ï'ÛM¦õÕÇÛÝÓæÃöÝB‘Ýû ‹.Úµ«öËvõ÷ÊðOìÌA¶‡L©»¾[½ÿ€Ý _×?.§îŸý]w ‰·Ý«ßVX•q_Ÿ;ãÀº@/•ðB6T‚ߺ*%.…ë+±1fý4\âðÄò+H=†.X1¿„á­{ñ•h‹áÉj ¿AŒuZþÒ¸ŠÇ/íUjo3$43Ò×5§9¥ù57ÈZEúCxÿáï ^y…Åò´(¥ù†±1‚¡ÜˆKBˆ&ŒoÍŒ¬_êE +€JMÇõK“…½3}òÏ’òü­<Ënå› #mÍLZ¾Ô‹ø”šŽ{g& {gúä5ž/å¸À@Þ™VòßÑKÛ3Ó©E +€JM aÿLŸ¼Äá vh¬3@¡•œƒä¥ÌixÔ<…¤Ž0¹Ñç®ép8†ãÊ`±•},AÊ^ZÜÆG-RàSj }ò‡9\d"°"„ì&ô?cµHP¡i3}¿À@è÷7·áƒ ršÒÿŒR«•¢BÂÄGŸ¼&Äá}¥ç¢lÁ¹F¢í„h^äy@¥¦°­Ï]ñéÃÉÍw%.5r%Ý„.h Z¥¨5º©“ׄ8œÒd½Ô z†AÛk=õŒÿì Ä8 +endstream +endobj +366 0 obj << +/Type /Page +/Contents 367 0 R +/Resources 365 0 R +/MediaBox [0 0 612 792] +/Parent 364 0 R +/Annots [ 328 0 R 329 0 R 330 0 R 331 0 R 332 0 R 333 0 R 334 0 R 335 0 R 336 0 R 337 0 R 338 0 R 339 0 R 340 0 R 341 0 R 342 0 R 343 0 R 344 0 R 345 0 R 346 0 R 347 0 R 348 0 R 349 0 R 350 0 R 351 0 R 352 0 R 353 0 R 354 0 R 355 0 R 356 0 R ] +>> endobj +328 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 615.236 146.739 629.184] +/Subtype /Link +/A << /S /GoTo /D (gf__vect__mul_8h_a15d42d058c64dec106d9e3e9fc2e1136) >> +>> endobj +329 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 603.281 147.855 617.229] +/Subtype /Link +/A << /S /GoTo /D (gf__vect__mul_8h_a84eb9ca31c934f05a8e3fa7a02fa71dc) >> +>> endobj +330 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 591.326 148.752 605.274] +/Subtype /Link +/A << /S /GoTo /D (gf__vect__mul_8h_a7a1f65b032f03494dbc68411f5614bb1) >> +>> endobj +331 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 579.371 167.212 593.318] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a1ff835062a19d6516f2d59d9c37ddb48) >> +>> endobj +332 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 567.416 169.225 581.363] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a4f880c4b9fe6700e040b9f4ef4e45918) >> +>> endobj +333 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 555.46 172.194 569.408] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a17c6ccf6470796b756841e160dc8697c) >> +>> endobj +334 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 543.505 172.194 557.453] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_abb7a991b4c0fb9ced373680ef36bae08) >> +>> endobj +335 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 531.55 179.188 545.498] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a26c2200ad3bf04b1c858eb239b7ff940) >> +>> endobj +336 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 519.595 174.206 533.543] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_ae1e4c9eb9a26a3a7852166d54d2a27f8) >> +>> endobj +337 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 507.64 172.194 521.587] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_af88a7da05f46e1a0fe17d032a2cf78bf) >> +>> endobj +338 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 495.685 172.194 509.632] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a06a563b718c6269c8df0fe7647e5bb49) >> +>> endobj +339 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 483.729 172.194 497.677] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a12f59be6d348fea6ad2464a20af22fd3) >> +>> endobj +340 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 471.774 134.714 485.722] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a22b53cd4103da9ed88c351e7045ff313) >> +>> endobj +341 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 459.819 160.149 473.767] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a21d5e25b4ac64062996149fea71aede8) >> +>> endobj +342 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 447.864 142.993 461.812] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a590b5c35075aeea1243a9e4ef73a49d4) >> +>> endobj +343 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 435.909 129.584 449.856] +/Subtype /Link +/A << /S /GoTo /D (gf__vect__mul_8h_aa7a737b69a0a77dc29aa28d0f17421a1) >> +>> endobj +344 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 423.954 165.678 437.901] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_aa486278c409735df8001096ac2b487dd) >> +>> endobj +345 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 411.998 152.268 425.946] +/Subtype /Link +/A << /S /GoTo /D (gf__vect__mul_8h_a8f3e57729c3382514325612c54e20eaa) >> +>> endobj +346 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 400.043 172.742 413.991] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a17799d49d9b83861322ebf314a55f77f) >> +>> endobj +347 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 388.088 150.057 402.036] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a6ce05684e168d73773847a3c2c13c175) >> +>> endobj +348 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 376.133 174.206 390.081] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a1fb1d6d463ac00ae196501c75d2036d2) >> +>> endobj +349 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 364.178 174.206 378.125] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_aacd489f45babdbfe6a41f1bac2885ab6) >> +>> endobj +350 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 352.223 174.206 366.17] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_ad0eca329291d751df6ffb3aa3eb83610) >> +>> endobj +351 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 340.267 174.206 354.215] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_afeefb3612c92a0bc87182f6e11030b11) >> +>> endobj +352 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 328.312 174.206 342.26] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_ac64153e1aef3cdc4b69d375ec762fa33) >> +>> endobj +353 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 316.357 179.188 330.305] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a2688b38c18e93c95c525c0d5bf9e221a) >> +>> endobj +354 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 304.402 179.188 318.35] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a2fb7662ba4e1df4bb72659c57efeaad6) >> +>> endobj +355 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 292.447 179.188 306.394] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_af88c501e0c5138ec9c88f58c182945e8) >> +>> endobj +356 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [77.38 280.492 179.188 294.439] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_ac6468d7eb3c28116439abb4a7c5eca05) >> +>> endobj +368 0 obj << +/D [366 0 R /XYZ 72 686.127 null] +>> endobj +365 0 obj << +/Font << /F46 237 0 R /F59 309 0 R /F47 238 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +433 0 obj << +/Length 621 +/Filter /FlateDecode +>> +stream +xÚí–[o›0€ßù~iq}9¾=víRiÙØ4)­Ph-%[`í~þ Œ´IÛ)tQ”&<Çs|üÁG#‚ÎRGL8å +Ì•i£ZS4·—Ÿ¹Ô?sÞ†ÎѩЈ*̨^#޹ÖH +A +Æhàž¼;þú}¯Ã”v¹wž£#BQÇ.– ªÄn/û÷ÓIØýЫ~X úþ…Gíµnßï÷ ¸‘ã‡ÎO‡Ú&¢H1$y±QF7ÎàŠ ØÎŸ{7Ý•Y7¤¶qŠçâþ±¸OÑv9¨›… 6’É¢G E’¬l,wžŒ¢$Íâ$Їù0ʲ¤Ü]}[4è0AÜK"È$ͽòÇ4IßT£ÅÔ÷Õ‰ùÌc½ËþÎÿJ³É8Mâê×èÛp^T9:¥ð`{Œ6Ü‚ªvvI¯²–š°9šÕ9ãëüë´Q-°Rêagê#^çgÓ¤Š2¸dÕ¨ˆ¥0IÇö¨é2‚P†5hûÈ1Líú2;|ÀË™Ÿr n£Á‚B}j»õ¨°ðó(žåÑù,ކ#îíï—࿽Ÿ[4L„^ƒ4ýOÒëBX> endobj +398 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.494 597.638 156.263 608.542] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a21d5e25b4ac64062996149fea71aede8) >> +>> endobj +400 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.494 565.977 170.321 576.881] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_aacd489f45babdbfe6a41f1bac2885ab6) >> +>> endobj +402 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.494 534.316 175.302 545.22] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a2688b38c18e93c95c525c0d5bf9e221a) >> +>> endobj +404 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.494 502.655 168.308 513.559] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a17c6ccf6470796b756841e160dc8697c) >> +>> endobj +406 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.494 470.994 170.321 481.898] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_ad0eca329291d751df6ffb3aa3eb83610) >> +>> endobj +408 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.494 439.332 175.302 450.236] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a2fb7662ba4e1df4bb72659c57efeaad6) >> +>> endobj +410 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.494 407.671 168.308 418.575] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_abb7a991b4c0fb9ced373680ef36bae08) >> +>> endobj +412 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.494 376.01 170.321 386.914] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_ae1e4c9eb9a26a3a7852166d54d2a27f8) >> +>> endobj +414 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.494 344.349 175.302 355.253] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a26c2200ad3bf04b1c858eb239b7ff940) >> +>> endobj +416 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.494 312.688 168.308 323.592] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_af88a7da05f46e1a0fe17d032a2cf78bf) >> +>> endobj +418 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.494 281.027 170.321 291.931] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_afeefb3612c92a0bc87182f6e11030b11) >> +>> endobj +420 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.494 249.366 175.302 260.27] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_af88c501e0c5138ec9c88f58c182945e8) >> +>> endobj +422 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.494 217.705 168.308 228.608] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a06a563b718c6269c8df0fe7647e5bb49) >> +>> endobj +424 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.494 186.043 170.321 196.947] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_ac64153e1aef3cdc4b69d375ec762fa33) >> +>> endobj +426 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.494 154.382 175.302 165.286] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_ac6468d7eb3c28116439abb4a7c5eca05) >> +>> endobj +428 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.494 122.721 168.308 133.625] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a12f59be6d348fea6ad2464a20af22fd3) >> +>> endobj +434 0 obj << +/D [432 0 R /XYZ 72 686.127 null] +>> endobj +38 0 obj << +/D [432 0 R /XYZ 72 668.127 null] +>> endobj +327 0 obj << +/D [432 0 R /XYZ 74.491 618.224 null] +>> endobj +435 0 obj << +/D [432 0 R /XYZ 72 607.546 null] +>> endobj +436 0 obj << +/D [432 0 R /XYZ 72 575.885 null] +>> endobj +437 0 obj << +/D [432 0 R /XYZ 72 544.224 null] +>> endobj +438 0 obj << +/D [432 0 R /XYZ 72 512.562 null] +>> endobj +439 0 obj << +/D [432 0 R /XYZ 72 480.901 null] +>> endobj +440 0 obj << +/D [432 0 R /XYZ 72 449.24 null] +>> endobj +441 0 obj << +/D [432 0 R /XYZ 72 417.579 null] +>> endobj +442 0 obj << +/D [432 0 R /XYZ 72 385.918 null] +>> endobj +443 0 obj << +/D [432 0 R /XYZ 72 354.257 null] +>> endobj +444 0 obj << +/D [432 0 R /XYZ 72 322.596 null] +>> endobj +445 0 obj << +/D [432 0 R /XYZ 72 290.934 null] +>> endobj +446 0 obj << +/D [432 0 R /XYZ 72 259.273 null] +>> endobj +447 0 obj << +/D [432 0 R /XYZ 72 227.612 null] +>> endobj +448 0 obj << +/D [432 0 R /XYZ 72 195.951 null] +>> endobj +449 0 obj << +/D [432 0 R /XYZ 72 164.29 null] +>> endobj +450 0 obj << +/D [432 0 R /XYZ 72 132.629 null] +>> endobj +431 0 obj << +/Font << /F58 306 0 R /F47 238 0 R /F14 318 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +461 0 obj << +/Length 489 +/Filter /FlateDecode +>> +stream +xÚí–MoÚ@†ïþs)Lf¿w©”DʭŪ*‘¥ØP$>ìÐþüŽí‚ë&RN9ízýîÎëyvÖK0‚눔P•³Úrk÷VüzÇ«/<ë¨ÙŸâèüЇ+-Äc0Ê ‰ÖtBCœÀ c»wñÍ6Ôe=F‚»œd©Á =ŒæÑàŽ áñ›"Xðð³TÍA[Ïí úÑçÚñ¶-Ö)|–­+÷—+§Q앱•©Éx¸î +ÓIGù0YæÃ‡Õ2Þw%uÖ¿~aГ†:·dhºÈ»åÃ,]œU½íк{ZdÓÉ"Mª§ÑûU±àùç£ö$E@rœÖÊÎ-‘ªT çƒÍdœŸem‚pj]3ÆŽ8EOmtÙjÔ&g׆pÀ‡È&I³œó)šyî)ïXÞÏ.µ_¿5dÏy—zm·¼é”ÚÏWž°ÔHÆŸ°?°|;àVûtÞ ‘È=Ã+ÛñÕ¯ðͲô4µËÕê´uåǾj¢í÷/5Š£‹wþ4{ù|Ð× «8¶mÍñOŒuáj9M^XY+ôdÚœ‰5¸W–U-Éw&µå_¡>ò¨Õ/ÓjW…’¨µú_¤Zm÷%%÷’Ò¨´Ü[Zÿ^«ñEM·¼Výysì +endstream +endobj +460 0 obj << +/Type /Page +/Contents 461 0 R +/Resources 459 0 R +/MediaBox [0 0 612 792] +/Parent 364 0 R +/Annots [ 430 0 R 452 0 R 454 0 R 456 0 R 458 0 R ] +>> endobj +430 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.494 655.203 165.34 666.107] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a4f880c4b9fe6700e040b9f4ef4e45918) >> +>> endobj +452 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.494 623.323 170.321 634.227] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a1fb1d6d463ac00ae196501c75d2036d2) >> +>> endobj +454 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.494 591.442 163.327 602.346] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a1ff835062a19d6516f2d59d9c37ddb48) >> +>> endobj +456 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.494 559.562 144.866 570.466] +/Subtype /Link +/A << /S /GoTo /D (gf__vect__mul_8h_a7a1f65b032f03494dbc68411f5614bb1) >> +>> endobj +458 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [73.494 527.681 142.854 538.585] +/Subtype /Link +/A << /S /GoTo /D (gf__vect__mul_8h_a15d42d058c64dec106d9e3e9fc2e1136) >> +>> endobj +462 0 obj << +/D [460 0 R /XYZ 72 686.127 null] +>> endobj +463 0 obj << +/D [460 0 R /XYZ 72 665.111 null] +>> endobj +464 0 obj << +/D [460 0 R /XYZ 72 633.23 null] +>> endobj +465 0 obj << +/D [460 0 R /XYZ 72 601.35 null] +>> endobj +466 0 obj << +/D [460 0 R /XYZ 72 569.469 null] +>> endobj +467 0 obj << +/D [460 0 R /XYZ 72 537.589 null] +>> endobj +459 0 obj << +/Font << /F46 237 0 R /F47 238 0 R /F14 318 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +476 0 obj << +/Length 583 +/Filter /FlateDecode +>> +stream +xÚÅU]oÓ0}ϯ¸ÉC]Çæ XÓušŒ> u£ê§‹H“’¤Lû÷Øu¢RA+*1ñt®íûq|®o‚a ¦aFX ±XriQ +¥4öøÄÑÝ4x7ƉP@bD‰à0Ïs†˜R …@\ +˜g°ß_¿ý8ŸÜE#«Gó HÙÀ‘””{¯dv;ñ.³W“/Î-˜Ìƒï±1ˆ)Hæh(H7ÁâCf÷o3­àyïµ.•Å>Ÿ~¹Ît0ÐÖ@8b\RGÛ¦š[.ÔsáˆD#‚1“¢4–UámÑv{RCÖqÂcÐHK*] –<ÒLúצq‡Eëqå¡työV÷eé¬NwSu&óë{Œiiúðç¢{òÖcS˜>43mÚÛ®¨«öÍ»:í\#÷†m›»8‰Ù±ú¦Yµ»Æ,Ó:3èé(°¸ïAZô=Y–MË>íïÙÕó]•î ùe»Ûnë¦+ªµ_÷•ü•뷫ƒ½ª²áz~Sk¢h$lCþ5p­Oy~“o1" +óPû¤ì£?é¸Î—?""B“vËÍ®<+½¼Tú¼n¼1”Ö÷XàDzN¿Yƒø-[¼+¶e‘®\‚þåö8M\uÔÆ a ‘Ž™ržrÜ×€!Izz_½ÛÑl¤¤´¼”¯,_¯±gàtcf!w–j{5,Ž[Û½lMû7³teÜ Wà·}ÿ«&Æ>æ~ŸÐjFÔÐì5áÌ ^Ü?Òó“iÿ)?c˜Œµ +endstream +endobj +475 0 obj << +/Type /Page +/Contents 476 0 R +/Resources 474 0 R +/MediaBox [0 0 612 792] +/Parent 364 0 R +/Annots [ 468 0 R 469 0 R 470 0 R 471 0 R 472 0 R 473 0 R ] +>> endobj +468 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [85.177 546.885 147.194 556.813] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h) >> +>> endobj +469 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [534.022 536.011 540.996 544.858] +/Subtype /Link +/A << /S /GoTo /D (section.5.1) >> +>> endobj +470 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [85.177 521.998 144.853 532.902] +/Subtype /Link +/A << /S /GoTo /D (gf__vect__mul_8h) >> +>> endobj +471 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [529.041 512.101 540.996 520.947] +/Subtype /Link +/A << /S /GoTo /D (section.5.2) >> +>> endobj +472 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [85.177 498.088 115.672 508.992] +/Subtype /Link +/A << /S /GoTo /D (types_8h) >> +>> endobj +473 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [529.041 488.19 540.996 497.037] +/Subtype /Link +/A << /S /GoTo /D (section.5.3) >> +>> endobj +477 0 obj << +/D [475 0 R /XYZ 72 686.127 null] +>> endobj +42 0 obj << +/D [475 0 R /XYZ 72 668.127 null] +>> endobj +46 0 obj << +/D [475 0 R /XYZ 72 618.224 null] +>> endobj +474 0 obj << +/Font << /F58 306 0 R /F59 309 0 R /F47 238 0 R /F13 312 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +495 0 obj << +/Length 1402 +/Filter /FlateDecode +>> +stream +xÚí™KsÛ6ÇïúœôBÎTÞcšÚi2MÒºê)I5´DÙ+¤JRr§Ÿ¾ ”(ÉtH¹Í«¹„ÔⱋÅ.\8x6ÂÍaF˜ +0bJr O)´&AÍMÏF?LFÏ…ˆB”Lç 1­)âR“yð&|úÓ“_&gј*ŠèÝäE06Úy0†±’r×ïüùÏg®Ó¯ŸþþòìÕ$"‡Oê'Ï_¿²CGg“ÑŸ#a《’ÙÐt0{?zós°¿°ÑÜÖ½Þ\jx.ƒßF¿¶–L…}µf)& 1.©] +L- ‡è¨‹N  Æ8LЏ\Éq4„K„Á—§)¹7$Ä0ßu‡{"ì²b˜åó‚!º†DQž§ËĽ]$‹HAhI6s‘5 }|ÎU`‘TÚyÇJ×óBž‘aÒÍû<«’bÆ3;ŸÀa•»çbͪ4ÏJ÷³\¯VyQ¥Ù•ûÝä¢þá«ÍÙî=ÎæîežX#²ÑAPºÞá»4›-×v¼„t?ºZL7ɬš¾_/Ñõ#·¸½Ýs¹#ÈAýtŒ#¢•çj»„v^:òC$âLCz(’ Ào){cƒ7c‘m"3Oç¾Í"`OLýrQ÷ªs1›¦YZM«ør™”‡óØo±ÀiV¹,Ý|ïž[C‘GT„·¥·¯³2½ÊŸÓÙu\¸„ÞZÅ +ilÀ‰[ÆÌ§½½VŽŒ&MŸxÈüR!Õé¯Õ岄•’Ž]P,Ð0TÖ:2¦òxŽáHÎLÓ*—éß £.£ŽÓ¼ð/qéwVDD„–ψÁÑpƧ}µãн§ÈâÁá +Ôчb +k1qMçqOË29œ‹îP‰Hhá°¿—Iûƨq¼Ø‰n -€¬}·Áv‚.€†$†ïðNX— Â[ËG‡Ÿú­égÓ3ĢIŽ8¬eì$b˜7Ø»¾Ürø’}hŸ%Yâ@¬[OÏójº*òù]µ¥-õ¶Ú”±pkÚìl­¢º(†Ë¡9©¢èíBÃ-Mñ¡2í îíDq„ò½î˜cŒ¸`ìžÛÝ Þ 2J¹ ‹A®÷뾸^{³Âu\8~»^ºÈó8«¶G!÷Õ³WãùzVÝ)‡»À¿'½”¨»!íÐÍ_G Âmx* öPÒT0mv¶ÖCC'¨aÊNCµ¯Í‘æê4½ííD1uýŸ¢j(ù2Q}x ÌîG••Ä0`W³†U®y¸5mv¶VaʺY•úôê·¯(?4“§Éjo'PH$Íqið¡³7Yƒˆ¡ÿWi¥ÔòJ{´]­®ê¦ ;]U{NÚ­«Àªæ'±ÚÛ èª1äÄ ¯ÐUCèàëà0m5HØ2€J¤ù Xu†Û´ºö~»õ#Î×Õj]•Ÿ@{iï:á›öž¤½ãZö•0ý`}æ˜ÜÏôqA["m‡{€¹ÿïkj fí+ºxÏ_~§AÝ׉Áh¿,í_ûööL+Ä¿1ýIuÚ×ì[Íñ9Ög“Ñ? ËÔm +endstream +endobj +494 0 obj << +/Type /Page +/Contents 495 0 R +/Resources 493 0 R +/MediaBox [0 0 612 792] +/Parent 364 0 R +/Annots [ 481 0 R 482 0 R 483 0 R 484 0 R 485 0 R 486 0 R 487 0 R 488 0 R 489 0 R 490 0 R 491 0 R ] +>> endobj +481 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [115.915 489.057 173.249 499.961] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a22b53cd4103da9ed88c351e7045ff313) >> +>> endobj +482 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [116.545 461.161 199.314 472.065] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a21d5e25b4ac64062996149fea71aede8) >> +>> endobj +483 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [117.601 421.311 183.215 432.215] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a590b5c35075aeea1243a9e4ef73a49d4) >> +>> endobj +484 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [116.945 381.46 205.243 392.364] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_aa486278c409735df8001096ac2b487dd) >> +>> endobj +485 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [115.7 341.609 205.532 352.513] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a1ff835062a19d6516f2d59d9c37ddb48) >> +>> endobj +486 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [115.583 313.714 207.428 324.618] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a4f880c4b9fe6700e040b9f4ef4e45918) >> +>> endobj +487 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [117.78 285.819 214.606 296.723] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a1fb1d6d463ac00ae196501c75d2036d2) >> +>> endobj +488 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [115.634 245.968 210.448 256.872] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a17c6ccf6470796b756841e160dc8697c) >> +>> endobj +489 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [117.78 206.118 214.606 217.022] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_aacd489f45babdbfe6a41f1bac2885ab6) >> +>> endobj +490 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [117.424 166.267 219.232 177.171] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a2688b38c18e93c95c525c0d5bf9e221a) >> +>> endobj +491 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [115.634 126.416 210.448 137.32] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_abb7a991b4c0fb9ced373680ef36bae08) >> +>> endobj +496 0 obj << +/D [494 0 R /XYZ 72 686.127 null] +>> endobj +50 0 obj << +/D [494 0 R /XYZ 72 668.127 null] +>> endobj +478 0 obj << +/D [494 0 R /XYZ 74.491 618.224 null] +>> endobj +54 0 obj << +/D [494 0 R /XYZ 72 618.224 null] +>> endobj +497 0 obj << +/D [494 0 R /XYZ 72 508.03 null] +>> endobj +493 0 obj << +/Font << /F58 306 0 R /F59 309 0 R /F47 238 0 R /F48 239 0 R /F14 318 0 R /F73 498 0 R /F43 499 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +517 0 obj << +/Length 994 +/Filter /FlateDecode +>> +stream +xÚíšKoÛ8Çïþ> endobj +492 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [117.78 642.06 214.606 652.964] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_ad0eca329291d751df6ffb3aa3eb83610) >> +>> endobj +500 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [117.424 602.209 219.232 613.113] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a2fb7662ba4e1df4bb72659c57efeaad6) >> +>> endobj +501 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [115.634 562.359 210.448 573.263] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_af88a7da05f46e1a0fe17d032a2cf78bf) >> +>> endobj +502 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [117.78 522.508 214.606 533.412] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_ae1e4c9eb9a26a3a7852166d54d2a27f8) >> +>> endobj +503 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [117.424 482.658 219.232 493.562] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a26c2200ad3bf04b1c858eb239b7ff940) >> +>> endobj +504 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [115.634 442.807 210.448 453.711] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a06a563b718c6269c8df0fe7647e5bb49) >> +>> endobj +505 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [117.78 402.957 214.606 413.86] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_afeefb3612c92a0bc87182f6e11030b11) >> +>> endobj +506 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [117.424 363.106 219.232 374.01] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_af88c501e0c5138ec9c88f58c182945e8) >> +>> endobj +507 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [115.634 323.255 210.448 334.159] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a12f59be6d348fea6ad2464a20af22fd3) >> +>> endobj +508 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [117.78 283.405 214.606 294.309] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_ac64153e1aef3cdc4b69d375ec762fa33) >> +>> endobj +509 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [117.424 243.554 219.232 254.458] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_ac6468d7eb3c28116439abb4a7c5eca05) >> +>> endobj +510 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [115.378 203.704 210.74 214.608] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a17799d49d9b83861322ebf314a55f77f) >> +>> endobj +511 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [115.915 175.808 188.592 186.712] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a6ce05684e168d73773847a3c2c13c175) >> +>> endobj +512 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [154.012 147.913 184.786 158.817] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_ac73ea8358bc3155c7f3a6c078a7d6d35) >> +>> endobj +513 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [154.012 120.018 181.618 130.921] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a484460566a8c888fda3d769324461345) >> +>> endobj +518 0 obj << +/D [516 0 R /XYZ 72 686.127 null] +>> endobj +515 0 obj << +/Font << /F46 237 0 R /F73 498 0 R /F43 499 0 R /F47 238 0 R /F14 318 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +527 0 obj << +/Length 2526 +/Filter /FlateDecode +>> +stream +xÚÍZK“Û6¾Ï¯à‘ªŠ<<ÚY{jSNUÖžÝ=8ÉEA3,S¤ÂG&“_¿ÝHJIÞÚ=~£ûkH4xhp{C L$%"‰£ž±TŠ |>òéãíÍÛ»›ïßÃTJÒ˜ÇÁÝ&Hx«”$, +îÖÁçP¶XrICÝdmß,˜ +õ}^¯5y´óï‹RÛÑG½ÑvA•ëůw?ÞЫ„ >/‹¥ õ¨½»»ùý†ÁÌÊ+IÊUoo>ÿJƒ5ÌÿˆôR<™UÛ Š<ËàÓÍ?öB<-(°E¡-c„ª",vöøTTƒÂºÔ[]uöåöý/TRŽ’‚IE2%‰5iD8• Ц–Èov•ÇL’(Iƒåd•‚ÎøEµˆhøš—†­^0Ï&À2™xqÉ('ÆKÆI*™%ø çÒÛ–è.8 ëbí¾¡YÑ3f`ý€2uŽFq(`êTa Ên‹¿ôúP^Põ´Æ´zÚ,"e‹ÏQ~|AñZ/¦2|ç4Ày£¬vŒÉcB¡ÒMý€a"ˆ!`„BÓs™¡8„L̤2ž‡$x=ÁW9x`$Þfƒ8«gË8Ïʼ/3ë!ü`lh„¯;;Ø5õºÏ;_ \†[òX¥¾áÚçíª.MZä&¡¬ž;í^íá'TN!ðÕ… +˜ˆƒç›ºu<3ûhug6“óp…E±ß,¸ ›šÅÂà‰]&ÿÖ}þ‡ (þk0ÌÊ~ÐÕå}î"sv¯ãep_kÝm¹ÑØ7° Š[óÆVSt§ÉïqØ=ï´22ÂÌä %áxŽdøÏÖÅĨ,…Yi·§ãìètœÝêÌhd™¹Y…µäÙ®hõï½õž³ÊÂ÷mæX9ù]¥„™¢ÊËÞTÈ™ó¸?}’ÙÓ‡Cpcf*ÌÖ•j² Ñ‘0µ6̸-fQøS_vÅ®tt]‰lmÎïøÅžìOÄà9œÅ\WVnòáê˜[Ä–±#Úw»¾›ÓÒ +wµ È8¶'žu¥í`—µ&ä¤ +ß‚êvòö½}n­6ÏöÍ3 ÖêþG±v˧‰^óÌ1Y¹ïíN»ýÎ}q$]ÒµqdßxóñöÝýÝ›·Þ}r|;ûòÄ¡'QÇ?wºjµ­¶z[7{µ¦É+Š}Yí¸«vï–®ÚÕyYö¢ÞÍ08Zý ý±ž®Ž ®^r!Àm†¬×‚2Í$8}¨J¢S}(`=•ލé8=I˜P€e¹!'ƒ-méyÉ7NHâ_Ë Xœ2Ÿï:ë2«5&òÅ2Š“‰ž™^€ÔI*Vj@f‘ÏÉ Rœ#`XÐxXóe– #‘RçiLg„ùÔÎQä s<ÂÐ rÍóE΃W¼ˆâ—àÕ$9ä°æaÓ­²”óR¤„îîåR‘LÂÕ¸];+„€bÄÏb) KäAûŠ0{àï:¦—ÒFç{åÀýaG•àÙ‰ü³lúÀ±º´·íïµôÐU¬µköjõWeiý$fÍg†M_¹ÙÊÆ®)Fn“BCÆ™˜=ªÍØf•I`”lx”…ém`d8³­ûÆT_·s ³V6”„§®Îwn‘­%H¡±ÏíX÷;}6ϬíËžIÖZŠP0ò+ðÄÔ‹½ÐcŸ4!yFR˜æïBØk SÐ9¡Ì¯<³( JYøïG´²÷à^0Óëá£í‹.[¤ë 0ÄiØÂÛ ˜èL÷‚K )sƒ°$‡‘-M8ÿT”¥%¶ƒÎ¥n¶vÚ¢q˜µÍLë:_Ž»Ñ‰8o×ByœÝÌ•ÞZ¯—Ÿê²Þ!ìÐãl°û‘éH¸f /6öõÕœ‡]Ý×' McÜvM?Y +¶ÎÅÀOWhZw%à@8., 7,úë‡É­èÆ Ÿ&¯/÷KJÒ4†<];SV㟱ÊgM¶E èûÙ{„yú‡_/¨±Å£ý§.¨ñ‹‹±DËý„¥iÀ£˜(0à Ôa®)JH„‡N$¡HKREr¬ö3ÐDWy)S/0™ +Cé]=t~RÖYþ8IÙ/3öb¼þÚ#ðýû°rÌ´^½îšy©¯Œ”ªè…}GÃöøôöÓrÝ~(µ%€–«%â` ¥ ^ܽõ—ãQrÇù(™²¼²IÕoWºñý¼©ß[ßñMéþ©õoÿÆ,åÒô°zzS8ÞÛ„}*fÎVß÷9lG°{qÌ\·ßÆ GG²ëb†+€m`HË#Xèɰ~jÇÎeœçcgÊùdì¸Þþ Ž~%Èë*ï›PBù<ùq@?Ü{ˆ³•ò=Ê™ùIá∸n¿‰–&DEü´ +ÐmÀQ=Јó$à ¬¢¢}U‡ËØÎGÔíϵ¹qÆ+6a ϬiÌ=Wêð.<‹ÊÆ®B°ÓÚñÍ×öuÓà•Ž4gÇ3—i†æ‰ß~R¼’¸/ª¢»· ±¼½è”@Á" ê['ßjöÞf¬‚Å_.þŸéø°áòœ_n¾ÌPñœ 2¶€c:>ztÎ/òqw]Ô®ÜoOŽ’$RW5žhÃñwYêÝæ=7—1=8×7îŒL’çΞ¥ƒl9…]Ã)B(ç_àŸHšç«à»¶su9ôºr¿u}"`ì+]OÁ¡àÑ$& ç‡7,óÞ¿Œï¼÷§|_íýáâá ¶žáý³Uð½HÅå ê‚ýó­äË«YØF)(Q¢ÔØâw}SµG~êöý™Úü9p±pn©ðrèÔ?ª¥$VìÜTýõ¾<ì +endstream +endobj +526 0 obj << +/Type /Page +/Contents 527 0 R +/Resources 525 0 R +/MediaBox [0 0 612 792] +/Parent 519 0 R +/Annots [ 514 0 R 522 0 R 523 0 R 524 0 R ] +>> endobj +514 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [115.915 642.06 188.741 652.964] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a81be18ea979e8a32f384e1a7856badcf) >> +>> endobj +522 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [115.915 614.164 214.694 625.068] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_afd549f435ee28276b5a9408a3a6256b1) >> +>> endobj +523 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.921 586.269 177.882 597.173] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_ad808efb2e8af3803571c0a6c7c9faf39) >> +>> endobj +524 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [435.802 210.231 499.771 222.749] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a22b53cd4103da9ed88c351e7045ff313) >> +>> endobj +528 0 obj << +/D [526 0 R /XYZ 72 686.127 null] +>> endobj +58 0 obj << +/D [526 0 R /XYZ 72 558.334 null] +>> endobj +62 0 obj << +/D [526 0 R /XYZ 72 427.484 null] +>> endobj +320 0 obj << +/D [526 0 R /XYZ 72 403.078 null] +>> endobj +66 0 obj << +/D [526 0 R /XYZ 72 403.078 null] +>> endobj +530 0 obj << +/D [526 0 R /XYZ 72 271.167 null] +>> endobj +384 0 obj << +/D [526 0 R /XYZ 72 113.727 null] +>> endobj +525 0 obj << +/Font << /F46 237 0 R /F73 498 0 R /F43 499 0 R /F47 238 0 R /F14 318 0 R /F59 309 0 R /F13 312 0 R /F76 529 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +539 0 obj << +/Length 2066 +/Filter /FlateDecode +>> +stream +xÚíZ[Û6~Ÿ_¡G¨Þ/-Ð PìÝd€}H»Ç–g„ØÒT’3›ýõ{(R¶hÓÊHšf7@Ÿ$ÓçFž‡‡Ÿ“‡'·7aF˜J0bJr O)´&I__ùêÝíÍOw7oÞÂAFR™ÜmE© R„'w›äC*Y,©ÀiV­êCµ :Í>®ËM†ÝøÛ|—¹·wÙ6sÅ:[ü~÷Ë ž\òaɈ"%$°öóÝÍ7^qB\¼ª“õþæÃï8ÙÀø/ÖžÑÉs+µO¸ÔðÜ%ïoþÑ Š +ûj~%„9[ ¡‘§•@ÑÅ’`ŒÓÏ ÊÓ2ßÀÔÌxÝFDF˜@B¨Ö#áQd´9x +a Xœ XeHCįTHyá¹~FЉÐïfÕ¬"^5ˆPó*^ A„èÐëýªÎÜZÿ†^,¹i^467oUÁb6 ì·z»¬øÁ …>4Ò’tBqC„"˜»©«Å麎£ IÉFÛdu·‹gŽb‡¢ÎŠÌcl½PéãªrZ°=OZ°N”ñNë7ŒY$…7Ìç…Æit]0Ò˜ÌàJv9[Óh `.âÁdÉ´„"‘, AF'q=6°Äa¾(¶Þ$lŠb "¨?QV&¨¥ª'¼Ô +e’%åíâ·J·Y¥´ñ5³¬Üs“µ›¹Wiý;\{ÙÂ=ïwåúS7¶õú°)p¯¬–„=³Ë oéó‚°]çeڅİ„ +IêwØm¾ ÂKYO”¥+÷Øå°í[ëžuy¨ÖÖ.¥®´£.05éÃiž T¶QX •{î»&Úe}ÍЇ«o÷áädU;‹õS¶Î!•´¹ÿ½_5UþïÐäí[[<¨G K$¤‡é¶h†4dv2ñú— 2* j(@àIJw H–\À¹ ›'f™míºÚH×yV45‚âeHúÏG»ÊŒô!\xF°ƒ}Ô‡¼YÝÛE²ruÖ¸a;;piÖžÁ@ó˜×Nt{(ÖM^zOÏùnçÆŸ²j[V{7Ükl+Ú;öÏ¿=ï.‡RDÕ`w¡”´×ÔGĘD°©C6@Ú¡®wª‚F¿‡[[p> +aާcä(àULuì"Âð8ý[V<4aýÊVëÇ^u»,nîÍn_·QÖMYµ[/<Ö¥ ´¶ÕËÛA—óœ!Upü„ÃDƒºVÊ<}8i$œ›ó€N ÄÍÅòxT3íÏu´LóGKßóÝ£ÏgqØßgU˜ïúù¯CT¥-’Ï~4ïêQg×—¹NúxnÀû¶to;£§æÔ9Yê9¶ý®jr¨m25Ø‚sRÐ^¯{6ÓÜÆaÓw;›òÐ<šsy€4e—ób}¨*8Vw_|‘j;’7®WÃèI…Ùu,åt4ÌÓoáÀmë*ÔðàÞcÈu4p +éHfˆÝÝ;®ašÃ8ú-á>Öæß0—Zx®ªjõ޶€g^8DX)ÛrÕî½ëb7îã¶*÷î­kÜûyÖÙô}ˆ§å:ÚÇlØï³õǼțΡ=Û.n0Û/2“þýPûøî³ ãòæñÌÿã‘Ïhä:Ät{£¿¸++Éá†~¼¥}ŠX ŒÐNæXƒ¯nšÑ0oµ•˜Þ¥ÍÔw{F $ñü.Í’U\AרMpø^ß;ÓG7OàøG¿Oz¥óÉí§³ZÙﻺd{9{¿?´{c :%süÂô:Ç|zúçé»ôK†(Ÿß{Q»RÂuT†TD<÷Ó¼Æsß÷úâÜw·ô³suDîGO!̨c1=õ£Õ_L „Sœº  ¿7‡ªˆßOϳ•(òaÆœzay”VwðŽL ˜–,¹…ˆêÓ×,B_‹ëô5# “>“³ék +–42L½€½†Fú5ÜZöëÐï{ åç5¼H»9›míÈkq$¯ñš]ùuòZþu¾™e>Eͬ}™#µÝòµ¥m˜Ÿãôµh!aÅ0{LbÝÄ9}}ŠãaÛÜ[ªjÂî71?ŠŸxâ–xþ& ´¼F`¸®Ñ?™ÁöêehpÆ0J_LbèË$ùV$vHM‹¿¨é€š–/¢¦åw@MK6þ€ó OÒoJR‹W ©/.ug?¤ƒ/ªÐǃÿCî~ÑéÏí9£»MúþýÏ‘,9´VFs€ƒh þóirÀ=âzz6S¿íÀ)…×aÉ)±7Mõu–|šÏhûøü%ÉGÏ7Ì2hÃg:Jæé·(!ö@SjL·E1ø’¬Ç“D12Ñc$}—ß7>~úAέºRÓ©™ú3úr:³´Ø?wpXèþ(éj.Òòù:?>Ñq:}ÇÿKz|üœÂ|‚:§Ó¹ž™úzhÂgÑãpY²´QJ‰<]lvh˜ä6†¾Û¿Hòï„$ €ùÒþ±nz6Sßí®aò3 ©#°Ý‚Ó:~ÛLòß6}§ßŽ=ƒ0o ­äô®k¦¾Ë;“Hâ™]…îOØ|ÂÓ°sš#žûi~ãÉïûývüøø)„ÙuŽõôì×ï +shc$5û7íÿwÁp +endstream +endobj +538 0 obj << +/Type /Page +/Contents 539 0 R +/Resources 537 0 R +/MediaBox [0 0 612 792] +/Parent 519 0 R +/Annots [ 534 0 R 535 0 R 536 0 R ] +>> endobj +534 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [435.802 500.345 499.771 512.863] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a22b53cd4103da9ed88c351e7045ff313) >> +>> endobj +535 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [71.004 260.492 111.003 271.372] +/Subtype /Link +/A << /S /GoTo /D (requires__requires000001) >> +>> endobj +536 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [435.802 173.703 499.771 186.221] +/Subtype /Link +/A << /S /GoTo /D (erasure__code_8h_a22b53cd4103da9ed88c351e7045ff313) >> +>> endobj +540 0 obj << +/D [538 0 R /XYZ 72 686.127 null] +>> endobj +70 0 obj << +/D [538 0 R /XYZ 72 668.127 null] +>> endobj +541 0 obj << +/D [538 0 R /XYZ 72 561.282 null] +>> endobj +382 0 obj << +/D [538 0 R /XYZ 72 401.032 null] +>> endobj +74 0 obj << +/D [538 0 R /XYZ 72 386.462 null] +>> endobj +542 0 obj << +/D [538 0 R /XYZ 72 234.639 null] +>> endobj +537 0 obj << +/Font << /F46 237 0 R /F59 309 0 R /F76 529 0 R /F14 318 0 R /F47 238 0 R /F13 312 0 R /F73 498 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +546 0 obj << +/Length 2219 +/Filter /FlateDecode +>> +stream +xÚÅÛnãÆõÝ_ÁG +¨fç>ÇHÓØhÐéÆlÒ‚¦(›X™tHÊÞí×÷Ì"µ#Ú7퇣9—9÷s(œÜ'8¹¹Â3ÂT‚S’KxJ¡5IZøùÄOïo®þ|{õî¶2”I*“Ûm¢h"u†áÉí&ù +DVk*pZ¶y·oWD§å¿‹fS¢·]íJ·z_nKw .ÊÕ¯·ß_áEÌ%ÖŒH!RB'ؾ»½úíŠÀ'Äñ+PFuR<^}ø'ØÿÞàËtòbO=&\jxî’¯þy`j`Ž +³4/‘%BÆ<‘£,óRy_öû¶î¦—ôO¨Î’5<1£¼nj/  í#Âk¢@,YsŠˆÐƒ>E|µ&ãôyEyÚTP¹éD>„ Ä%I$6×`sB¢(ÓÙ ¦/A˜F\&Œ4ö‚¨êª1üuˆ +Žh6%Úçw+•îÊÎ]û,ðjÍ…n,3ï®Õؤ¹@ŒøãÜ‘)àW¨p$ކPÐ gÚÅi³""}éb©@‚ñpz_wÕ}]z=ÀýCÞ:(p´”#á$@ý²‹0¢Æ|ä¯_ç÷#~¿íïV§».&‰¤Ê虸ˑ›¬™Q“VÉšrÄxæ þ +æUå»ê?>Ä€æÚa½mZ¿0,ä]ïÞ¾³qÊŸÿ•_u1¬ózã›ÒF2ÃðdüMRoc7e ¯7ʦiÿPšKK£òOO€ÂÔþäy2¿Öe9ì[þÌæ?³1ëpÂñqV†‹˜]ó»§ÑÔnën×ÃÞÖímò>G«µÂ*eôîs`ªn¸#A™^}þŽ›#–yáƒ{U?í½\‹¦Ü®¨0vA‹ª¬{tâç"™ T šxÕþ`BWÞæeo²IãÑ4Žÿø×ã” ˆãS³)⺠l=_‘,KföÀ œxuŒ¢ŸbcG†Ð¯ Rˆ`/¸±xk2Ä¥§éJ(„a9!yûà=§Þ?Þ•ÞJŒÍ™ç³ñˆ²èƒõt;-‚“†Í¶1¶óÒ³òîðzK §ó¾­>Y%¸@Uߣ/o/8ƒÏ/¸þTçØ¡¹Øf–Á[›áADfËl†j pq¤„ 銋´yéNÚÎ…”£¶3¡VlÝ•S›î†¢–ÑX10û²ŸH‰Cï4Ôë#HÌz’¦çüâ\íNÍ ^Sχ?³ÏçÐéÿ_Ÿ¯Æ}¾ˆôù +ü/Öçs„¡beÒHƒ/ëóÁù¤´¨HæÍ—>Cj޹¼FLük• 7¨[&d7MŒ¨âHû“K‰*…4cS¢O­)EšM„r&÷Ç—RÎ2Ä)RÎM#ôüÉ©9Ì5ø‰ˆªÁ½we@ÁòõÉáÌó LàÓ„g±¡‚ze¨@ùëCο*D¹Ð(cj9'81¢ ƒ(:;å)NÈUKñ»ñ±€!¬3ŸC|-½)»>&‚ó EHDµžÎYn®±…<Ä …+Ó7f$a¶±gÿI"„¡’õè”¶|DDãÓvñÔ6›}á_^ªÞú£þfÜ!¸„> endobj +543 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [71.004 239.795 111.003 250.674] +/Subtype /Link +/A << /S /GoTo /D (requires__requires000006) >> +>> endobj +547 0 obj << +/D [545 0 R /XYZ 72 686.127 null] +>> endobj +381 0 obj << +/D [545 0 R /XYZ 72 632.899 null] +>> endobj +78 0 obj << +/D [545 0 R /XYZ 72 618.329 null] +>> endobj +548 0 obj << +/D [545 0 R /XYZ 72 527.832 null] +>> endobj +389 0 obj << +/D [545 0 R /XYZ 72 392.29 null] +>> endobj +82 0 obj << +/D [545 0 R /XYZ 72 377.719 null] +>> endobj +549 0 obj << +/D [545 0 R /XYZ 72 213.941 null] +>> endobj +544 0 obj << +/Font << /F46 237 0 R /F59 309 0 R /F47 238 0 R /F76 529 0 R /F14 318 0 R /F73 498 0 R /F13 312 0 R /F11 313 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +554 0 obj << +/Length 1723 +/Filter /FlateDecode +>> +stream +xÚíZIoÛF¾ëWðHådöåÐiÚ"uŒ @’45²ؤCRvÓ_ß7 iR¦K2‹OŽæ-|ë7ÏÆÉe‚“ÓF˜¦Œ˜’\ÂS +­IRÃÏ[~:;ý|>{u[Ier¾LM¤6Hžœ/’©@džQS[çͺžÚŠjaÑUØ?Y]Û°:³K”…>;ÃG)—|Ì‘B¤„¸½9Ÿ}™Xâ„}2T'ÅÍìãgœ,`ÿ­ãgtrïOÝ$\jx^'ïg>(Õ+G…[ºG´ˆ0C‹„1O¤ÄȘh•3Û®ë²d|‚AÕ€œh¤°I2xbFyY•Ñ@#Ù‚3¢À,É8EDèÞˆ"9ÏÆ8½›SžV«8€ñôr陎ìCG„‹Db÷l—‘(2ÚôfzlpvÀ +#£%è-Ú ±B#IÙ³ˆ•IBÇbÕ”PÅ‘!äY„*…ÌXä-ĶH«Å„\#ÑóXØÄõ†Ü|NHz÷/ >þ„žgÏéªô&xu¢†ùË!¡´žöÚ–?„Cc9“Ru‡¦Š 1»3w[8Q†6Ý©uÙ¬.Kñ˜«ô*¯Ô“*"zªO`µ ȧݙËe{1'8½n&µ0}¼[4SPÓ›¢©ç§Å¤]AXí©GÆ\‰‘ž #Ä“ô<Œb¶i§lBÐÈ2*VE*“ +PT&ž¸`£QcÈedÓ‘7Tí„A^Fmÿ§FLÒdÙà”özøfqç’ JGU‡w—Ð~q[W‹u_îWml3í½s^ªu{»nä„‚Îið¾+—’ƤùICzþГX<ð‡—ê¶]ݬþó>‚×¶ +Ï"¿.Ö×ykãv/Û‘¬è°Î#›<ž[ÝX4Ïæ_+ÛLo7)#.åÍá6øÆNË¢®š¸¶yqV_»Ï«–QÓ+ +]Iˆ¸²«ðÝpPã4¯ëük\–ÎtÊ >v‹ªlÚ¼ŒÇë5•—‡‹Ê.çT¸§ÅÊ–Ýïm¤úÛðU²¨rÇÈ\u]Dd̘ô—¼ Û6P®ïbØYú€Ðž±Â‹Uyé¿Ó° €` )ì?–1)çÐ<’¥'ë²hWUÎÔöËzU;ç»·ÛÚf]0Å#Â+ïÙ…W:Q(Wˆbõ¸BŽ‚º&Ý6ÅÇ­Ø>\\Úc;¼éµÎ÷GroVÿM‘Ê;ÄmôñàvC¸UµìrÖa‰’×…˜À‚6À–k¼?úÅÙé&Ž7R…„V`snñàôI¨»VÝw”×þ¢€vnã ˆ9ä‘@ŠÇôyçZ^ç7¶u ™¤ÓjL ØüusP—µC”õàã9éà–„3P–Ó]<àtðöÿ(6B˜¹ãŦ¦Ç0SøÒaâC…ŽºP¾k„þfËË®õøb#úB4ѼVexºœñ5Bÿ÷ucùÂÆÌ$¨–â¨ý4‘˜€þy‚?^Œ¢ÇÆp :ßþÖGc΢ãèCA×ZEØ·/0…+1(l[Ãè0©Óa4”úÇúæÂÖã0Ú ž¦Z×…mvùuoõÆ~qÀnûõ8zïWfãÝ_w C¶{•ÂÕ—*¸àx’‡kÁu³Õ¯IöêPê» +®LέpAñ˜.J“mœ»þnM”»˜g$ýÚÎ +-»î ¿y[CŒâÛ9üÖµü&é½£*ÃVhô°Ñsd‘#íúx`ôÐdzÐú¡óK)ÆØâ'S`_OŽØ3}püGÂ_CµOÛÝ‹iŽ4ܺË(Sp·Üš‡ žÌ‘à×ñ0(l·!-šxa«†å­ë“ýµm‹›÷Vwì) Çôpt$}p5\¥µ:93€9€'f|ÏŸöóaR§ý<”úd?;õVe¼æø¼Í#r“µ¯K Ûåÿ½?cì? —êpsýžSd¸¡|ï!²zCX›1æz–¹±ˆÂÍäenü27~™¿Ì_æÆ£¹ñû÷o8";ÿy’`Ç=ÿyá¬&åt +endstream +endobj +553 0 obj << +/Type /Page +/Contents 554 0 R +/Resources 552 0 R +/MediaBox [0 0 612 792] +/Parent 519 0 R +/Annots [ 550 0 R 551 0 R ] +>> endobj +550 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [71.004 480.404 111.003 491.284] +/Subtype /Link +/A << /S /GoTo /D (requires__requires000007) >> +>> endobj +551 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [71.004 154.16 111.003 165.04] +/Subtype /Link +/A << /S /GoTo /D (requires__requires000005) >> +>> endobj +555 0 obj << +/D [553 0 R /XYZ 72 686.127 null] +>> endobj +393 0 obj << +/D [553 0 R /XYZ 72 632.899 null] +>> endobj +86 0 obj << +/D [553 0 R /XYZ 72 618.329 null] +>> endobj +556 0 obj << +/D [553 0 R /XYZ 72 454.551 null] +>> endobj +374 0 obj << +/D [553 0 R /XYZ 72 306.655 null] +>> endobj +90 0 obj << +/D [553 0 R /XYZ 72 292.085 null] +>> endobj +552 0 obj << +/Font << /F46 237 0 R /F59 309 0 R /F47 238 0 R /F76 529 0 R /F14 318 0 R /F13 312 0 R /F73 498 0 R /F11 313 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +560 0 obj << +/Length 1933 +/Filter /FlateDecode +>> +stream +xÚíZYoÛF~ׯà#T›½‡HÚ"u @’4EÛlÒ¡¨¤é¯ïìA‰”)Z$å úÄÕîαsìÎ|6Žn"Ï0ÂŒ0aÄ”ä¾RhM¢–,]œÏ¾¿œ½8ƒ)ƒŒ¤2º¼Ž¤6H].£·±@d¾ ÇY™¬7åœè8û+-–ºõóg«»Ì.²ëÌoÈÓlþþòÕ OR.z»`D +ÞâöÓåìÃŒÀGÄë+¡:Jïgoßãh ó¯,?££On×}Ä¥†ï]ôûì·R[娰Cû ¦i‚0æ‘”¬òzNyœ”É}VÙ#“xÝ>o¯ˆýÕGçÂÙ¿ï< ” l{¦SÒ#bL$9CÌÐÃvd„,œákŽ0°ã¥×:ËÝe¹3UëÐD€T1V(WM¡B! ÖП³ü¦ +ñZ\‡xNÒ0óqNDœ¥UQú߫ܯ>WÙÍ!qüËf]…YÚ/ÎiJ•Q,@='ï;¿¥¥˜BŠëz÷ž‘è±1XQ>Âí(°läø šDîcˆY£È‰1‚w2Ž”¡Þz{ƒhœÔî jJýus••í Úu±)S4‡½:X½¶[˜½&¸u½÷+–HÕÊ!‡ÝJá]¡*’”"ÎŒ7ðÍuuu·>ìØQb»ýÚûºXåö‡<§qUØ/‹iHrÞ æ6…ë ~‡1ëÈrŽŒ&õÖÅÅŽØ..ÚrWó‰?Wsg^ˤ,“Ï~ÍF¤z(³EšÜ¥›»¤Ê–~--òu•äÕÚo¹JÖõJ‘û©ê6ó[Ž,p¤p>lªšQv=§ÂªMVïh!’RD ²áºMWëK‚¡®lÇ0PK£ÇçÀ4z—Âp§™ü>ÚÂDó¦[—s¦âô`Œ”Û™M¹/½ß›wۃϋµÿecwÃÕ%DFŸŸ‡kÛr”%g||!4‘Þ;ZÃWO-„àηæ€BU©$Ë *Šƒn'µÛÍM©GûÙª·Ê“jU„jh™TI¨€æÇw@ÁßëÿÁÇhûOÃ’ïþÁä[Á5ÂRyË^dզ̻û€}Ïh¤°;ÈY¨.ò"=SKöžà7rvÁm˜èm‹†(Òð8`lKhMŠ\ð”*xS;b ª¬TĵvßQxˆÌÖ< X@+…´ +–`¡"ê +m õ¬8‰X(·$vKì²èª8Ònçt¡ +„1ÖúPÚ +°XvH6j vÉÆ Ni[rbÛÎ{7¿ÃÏ\p¸“+_P¨fW/ …ŒÀÛì¿©-F#xëMÝŒE”‹fiÒÅ žnÂM½k“¯W7y"2«ø6);*#ˆL; +¬– +äo÷ØŠqÝÙݺS ŒE¦jq@k +º5<Üp+¦쪥x6=à.`kj0Ñ~^ömBàEÜ1¤u_íÝS !Õ:ZPûކrùüÌ[]Ù²H"£˜¼1#C’%þì¨mCE‹Æ.íôèì§lNûGª,–›4üø´ª›ùê¶ÌB1Rlªm5ÛS»ûRÒÚ¼Œ![îFî0Øq‡ÅCµº_ýã<?݃ßmQ¦ƒdK°±‚ý8qLDœ„]«û AbrÿXdëG¤‡É fP\cMÙiÍŽóÕ:¦e±。ÀÈ¢Þv .uIh;ž\µ ¸ï¨u[`çBÓ`g“|Yï󇄹ºýð ëÌéó5ËfWá[¿î,ë^ûÀ,( ÓNa7òŒD­ßÅ‚iÿä"ðظþÇÎ\»P°lºé €÷º™b¹Êo€fÙ,–™»£ÚÁ2sx(¸Yšøl“§¾h²Keöa³*­ãí¯fo¶ÝâÚ,ËÎXÇUš6¯š/Þz‚ZÞØv´ó¦Ó:ô‹x×VÚ3*ßVºŸ™P”Ñ®¢´Ž.>´WdÙçÖBÉnpq¾iƒ?©BBo 5ë‡SU­qû> endobj +557 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [71.004 367.478 111.003 378.357] +/Subtype /Link +/A << /S /GoTo /D (requires__requires000009) >> +>> endobj +561 0 obj << +/D [559 0 R /XYZ 72 686.127 null] +>> endobj +562 0 obj << +/D [559 0 R /XYZ 72 667.868 null] +>> endobj +390 0 obj << +/D [559 0 R /XYZ 72 519.972 null] +>> endobj +94 0 obj << +/D [559 0 R /XYZ 72 505.402 null] +>> endobj +563 0 obj << +/D [559 0 R /XYZ 72 341.624 null] +>> endobj +394 0 obj << +/D [559 0 R /XYZ 72 193.729 null] +>> endobj +98 0 obj << +/D [559 0 R /XYZ 72 179.158 null] +>> endobj +558 0 obj << +/Font << /F46 237 0 R /F59 309 0 R /F73 498 0 R /F47 238 0 R /F11 313 0 R /F14 318 0 R /F76 529 0 R /F13 312 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +568 0 obj << +/Length 1836 +/Filter /FlateDecode +>> +stream +xÚíZ[oÛ6~÷¯Ð£ Ì,ï¤6 ÛšÅ6tmP h»A‘•Ä@"¥’œ¢ûõûHJ®ä(n,{Ùò$šä¹ðÜÏIhtÑèåŒ*˜0%Âh©ñÕÊZU8¾çèÍËÙ§³g'ØJH¢¹ŽNÏ#Ã#mb˜ŒN—ÑûX6_pEã¼Jëu5g6ÎÿÊÊeN.ÃþÉê*«7ùy.Y>ÿxújFb.z¿L+35Àöâtöiư¤ ü*’pe׳÷i´Äþ+‡/±Ñgë:’Úâ{½ý¾AÞn¶Þ®,aº}û»9c,㦬ðÂDÇ˲ ‹›ª\®³öGyÓ¬®WçËð³)Ã7K¯²õUÚäíöe•·Ër}³nê°N=§í­ÕuNæ )müs™×w@_ž| Šr'g'LDš$FXǼŒPÍtàÿÏpmðFE¬ÖÑ¢wË#_ÇcV•u»ÎÓì2¬Î¾4^Ë@& ÐñhÁI” +hËs\3Ì;ÖŠW^öÒªJ¿„Ý´Xv÷Â#±—•EݤE{¹Î=ØïPfe~>ç*þ@)ÏVyÑ{ÉãYY³*‹pTåŸÖ«Ê)Þýº©òEgF›+Žy.|Dk ²§dpJ8W`Ì39‰S$±¬»#ø·û`¹½Ê[.ƒ°Ýê«6=×AõþJêÅêßÔBy…„…³o]<‘„©¡ˆ[›@ÐñªÄ·³.,ïšF#8\ìñ Dš­}rC”5دØê-Dá»-‘ØN$ÏßýÁ·‚!4ã>V%=Ø…–ð)onx=çÎgÒë¼q–ÅãlŒØ>ÝŽžJ!Xµ3zF›zLxÂ’$RÛ…·ƒþ +¼èIŽAbÔãBÊb6HΙ£ÕàÑLqgP‰TÍ”!ËÑ_ò⢹šg…°º3µÉ)ÞpÃ×9Œ@ŒÆ¿®ëÖ–ÏòÖ-YŸªf„Ó{ÿ0â•Ö³1Áï.ÁÉ]a(œàr‚4†Vp!øt+: >XO3æ@+Bb PËtuÀíN3šFuÜŒúT[_ŸåÕÐŒ¶§.×U–×»ôº7{C½p‹ +ÃN×ëaðA¯T¢h±»ŸÀ7ÙýjåðOnÀ%’ù^œ7gWõýzDu\­=ª¯ËUá¢8üœû‚Õïh—Î…ÿ³ æÎæ i樀—]êÆ™¯Aذ@ñ¹g]¾¯Ã•.Ë;¨"l…, ƶªÁV›Ç¢¯y|jBSoÕý?îûjrhÁ€Ö:™î‡Á{ 'Š©ƒó£kƒd¢ £­5ÖÕ\˜8»× &õ‚áçmЋm7Á3ÚºÎ×ò›׫ñvizvªràè8'«ú@ø jKÑ€Z +¡>pâ°Â—^âË5ŽzžFu\Ï}ªÖ³coU´mŽßH›´­æœÆk +ηKÿ{?c¨?ã_3]ÿûÃ×ì^¸ƒ¾`”âR*’®/iÖUñ –„Ybh‚¸i.xQí”fgC‡˜@câ Ål†B?)2¥®*AR®\‹,$òꈙ ‹&ÁD‚¹3»æ)ÙÈç®$*EW¡ «ˆ•­(Ä-Š¢²ZÀÔQÈjD/%‡dݼä.QXTâ(D-'Rò!Ñ›Êåò.eNa%þúÁ”9²E;0 \×yP±›A¹é…AHnBEaú 4RþÚ~ ¢ø.\ÚzjÝM3Žˆ¹€ÊûµÉ&änAMwk]Ô«‹"o­1››ø2­FJ#7éSönm4`À€~wÅŒstgWõ( ÚO=‰ ÓgâF žl$¼˜˜Š|p¹/ ûÖ>DôJ«oð#6dºä²-4u½V±A¬ÚŠQ #uÅ—€jMîþy'p{%š©ÝãNÆj8îé¦ÂøÓ¥¨Íx?>¯ºf¾QºdÖ ÃˆJ çr±RsõˆÃcçM·<ÊüX=d~lžæÇOóã§ùñãÌß¾}þ§Nõ#L9+%›\6ïÛ&ÎáÖe‚ÌQ™X#¿=AžHt´ký¿N™ÞÑ|í/¡œÚ铯áƒQ¸ú£cL9Õ ö€òD¢ãVÔ#zœùñþÜ µpƒp²Vƒ÷ZeÆú²ìócær‰Ö O#;ªÖÙ§ ò£O÷VåÀ†´äÓÿÂz |ð´wܰ£L™NˆíFAßš O$<î}ÂÿÎyv‡ª85Ó'ˆÂU+gˆæ(d'yEå&È©Žë¹Oõq'Èû?c¨?€6½ˆ™ßUåC<EˆeûþKÜ?MË?ƒ +endstream +endobj +567 0 obj << +/Type /Page +/Contents 568 0 R +/Resources 566 0 R +/MediaBox [0 0 612 792] +/Parent 572 0 R +/Annots [ 564 0 R 565 0 R ] +>> endobj +564 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [71.004 591.693 111.003 602.572] +/Subtype /Link +/A << /S /GoTo /D (requires__requires000010) >> +>> endobj +565 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [71.004 265.449 111.003 276.328] +/Subtype /Link +/A << /S /GoTo /D (requires__requires000008) >> +>> endobj +569 0 obj << +/D [567 0 R /XYZ 72 686.127 null] +>> endobj +570 0 obj << +/D [567 0 R /XYZ 72 565.84 null] +>> endobj +375 0 obj << +/D [567 0 R /XYZ 72 417.944 null] +>> endobj +102 0 obj << +/D [567 0 R /XYZ 72 403.374 null] +>> endobj +571 0 obj << +/D [567 0 R /XYZ 72 239.596 null] +>> endobj +566 0 obj << +/Font << /F46 237 0 R /F47 238 0 R /F13 312 0 R /F14 318 0 R /F59 309 0 R /F73 498 0 R /F11 313 0 R /F76 529 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +577 0 obj << +/Length 1709 +/Filter /FlateDecode +>> +stream +xÚíZYoÜ6~ß_¡G-P1¼‡HÚ"u @’²–k °%G‡Óô×w(R²´Ö®÷0Ð>øI\i.Î g>GWŽÞ,0ÂŒ0aÄ”äžRhM¢ +>oùtþfñýÅâÕ¼2ÈH*£‹u¤h$µAŠðèb}ˆ"Ë„ +Û*­ÛjItlÿÊÊ•E×þýY~cýêÜ®­'(2»ütñvO2.ú0"…ˆ‰œHûébñyA`‰#âíÈPe·‹Ÿp´‚÷o<££/ÕmÄ¥†çMôûâ·£ã¨pK÷fì‚0æ‘”¼rn›¶*êé&êFìD#…M”À3êÙ‹²šèÞPœq`QÂ)"Bñ@ð‚B0Æñý’ò¸ÌWÆã«u'uâ Â4’ZG»}°]^¢Èh3øé±''H*¢0Ò8¸‚ßÛ¬™Q+"R>‹Z)aÿ|ªvUÎ)UñŽòt¥š"ÎÙT餷ˆËÕcÍÔiìÈOÖL1ï2e¢9]ßÿíÃü ¼L §ã¼è¼ðêLÏ0Hp +*:Ö[|ã‰66ˆ”T=Ѽ BΞæ~‹$Êæ§j‹:¿*lÈÈl©âë´ò\PS¸„† \Ái3(Ð?läjÝ\. ŽoêY+ ÂFŸnÅKÀÔ ®¨«%Åq6ëW°VÚ‘0HrA\ ȱ—=Œ÷jV¶næ|BÐ d ™¬B•(†°QB9pÏôæÌ% C~#£˜²¡rG I¬ýÓSM„ +¤!É’•îìèƽ;MP=ÊÊÿvgº[ÜUåªÍÂ/yZͺleÙ6wmS#§ –HCè]½”4˜÷p`H/œQㅻŠœ1t×ä·ù?.@î[Súg–ÞdíMÚXÿÓ+îè[§×¿MƒÀ4ðæ·-ÁuüciëMÎíž„¯ku´+çvW{¥iV•u0Ŧٵ_]~m¬÷ƒRa `ú¬“^l¹'kØÐµõ‹¼€MûeZUé×°,V~«¬,ê&-mmnå%jøn×K*\^Ó,·EÿݹÝ=½ñA«·×­:{G‚F¦ ‰MRÅ?¤EàŸÛÚF=ŽñûÇÓã°&/®€ŒR‡aä¸5 ;…—+Û!ð"&ñY[dM^ž¦²ŸÛ¼raw„w•Mú +$ÔïÄùŸ|¦ P¨XÒÇUq’ :È@Ã茜nuˆWÛ½YÁÙ`ç(šð¾¼#I½[¦ß›,B2Àª ¿?Ÿ i=uvç 8Ê}rÁòqz  „åZ­ÝâüÍ&x…xR…œ¥€Ò\L:DºTã´33¸äõû?6@ì.¬ÆðÂA‚¥x8Hï8K«ôÖ6“xÞŠy›_7Q/k™Q;Q/@WAÙ€5ž“c"•‹ÒØ!¨}ÐGpG±q#áNCšš³Ì ;ápð±J§ \¨®KO”þl‹«¾ÕôÙŠÐL³Ê ÿtçÅÕÈä—¶©|ié$ Ø‹>Á¾›9”€øùßzYD¢ÇÎp šÝáÞ˜fë=œŸE§ñû,‚¾­µ>1‹àâ‰,áJŒŠÚÖ4:Në|µþÚÞ^ÚjšF›ÉSC•Ìl½+®›7‹ÃBpÍ8:®§ñwqe†A-Þ½¸;²=ª®»TEx’‡kÀM½5®GiêXë»®H.¬p!ñ0‘°ÙÎÝÞ£õ’'8;DŠoàθËeBâ¯ÍЯ·2tn÷Íå£{5Æ'ö…o}»¯=IhòWá_uMÞ½$² ‘ömÜ zhã‰G²É]-&hkÔágÀ¡‘œ$°cfúèü?ݧ¿†j‘:µ9ºÙÓi¸4ô—O¦à.¹õ§xö L¿pTØîü±¨ý¯Çåm„ïv†ù`s§‘vLÇA'òûPK´:97€;@&fz¯ŸóqZçã<ÖºwœyyÑ_qÜ‹´Ir’¶«kàÛÿƒ·1°Ku<‚9‚ÿÀÉ1cõàà?Ó™Á1Þ>84¢ +Ì—'Ï9é$õC†]ccö:ÝИ˜‰Îí3ã@x¢J72Æz¢ò‰‰1VÏ —bh‚FNô†y1õáíÆdÛÀ–œ==0–J?90¦Jí10¦”ÌHñîQ­›’=50¦Jî?0ž[?i…Þs`,Ô>c S‡Ú‘0‡_é—ñËÀøe`ü20~ÿÆtçx! Wöÿ¨ð/0äá +endstream +endobj +576 0 obj << +/Type /Page +/Contents 577 0 R +/Resources 575 0 R +/MediaBox [0 0 612 792] +/Parent 572 0 R +/Annots [ 573 0 R 574 0 R ] +>> endobj +573 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [71.004 480.404 111.003 491.284] +/Subtype /Link +/A << /S /GoTo /D (requires__requires000012) >> +>> endobj +574 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [71.004 154.16 111.003 165.04] +/Subtype /Link +/A << /S /GoTo /D (requires__requires000013) >> +>> endobj +578 0 obj << +/D [576 0 R /XYZ 72 686.127 null] +>> endobj +377 0 obj << +/D [576 0 R /XYZ 72 632.899 null] +>> endobj +106 0 obj << +/D [576 0 R /XYZ 72 618.329 null] +>> endobj +579 0 obj << +/D [576 0 R /XYZ 72 454.551 null] +>> endobj +376 0 obj << +/D [576 0 R /XYZ 72 306.655 null] +>> endobj +110 0 obj << +/D [576 0 R /XYZ 72 292.085 null] +>> endobj +575 0 obj << +/Font << /F46 237 0 R /F59 309 0 R /F47 238 0 R /F76 529 0 R /F14 318 0 R /F13 312 0 R /F73 498 0 R /F11 313 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +583 0 obj << +/Length 1906 +/Filter /FlateDecode +>> +stream +xÚíZKoÛF¾ûWðHÕfßC ôÚ"uŒ^’´ )Ú`“I¹M}gTH™bDR rȉ+rw¾Ù™ÙÙ™ÏÆÑm„£‹3Œ0#LE1%¹„§Z“¨‚Ï>]^œýtuöì^d$•ÑÕM¤h$µAŠðèj½Ž"ÉŠ +çUZo«„è8ÿ;+×9zçߟoîr?ºÌor?¡ÈòäíÕ‹3¼H¹èõŠ)DLTOÚó«³÷g†8"^_ ÕQvöú-ŽÖðþ…•gtô›uq©áy½:ûã£R;娰Cû¦k‚0æ‘”¬ò2¡oì–I\÷÷; +±ÿõÉ~„pöÛ(%(Ûíé”ë1&’œ!f‘³ 2BÎpŠu G˜@ØÉRˆ€kåîò™ª·i"UÌåª *Â0ìþš·Mˆ×ò&Äsš…7 qž5eåo +ÿ¼þÐä5J qüÛ¶nÂ[ÚÏÎ é¢J‚( žÃûÁOé)¦âºð½—Å(zj V`”ϰF? +¬9?ˆ-÷1ĬQä‚„ ÀŒ#e¨·ÞãhÍC¢.êïÛûë¼êÑ~èÔå¶ÊlÐöêdõúna6-pë²õÞ¯X"mÔø(C†v+…{…ªHRŠ83ÞÀ·7Íõ]}ر³`‡ýÚ…}Yn +›ÅáœÓ¸)í“Å<rÞYÍínOðŒÙÀ)çÈhÒÎat@б)R\´;宓‰?4 ‰s¯eZUéÿÍF¤}õPå«,½Ë¶wi“¯ý·¬,ê&-šÚO¹NëöKYøWͻܿØIdA"…tø°mZAùMB…U›®¬ÞÑJ*$¥ˆV.dCºÍ69€‚©®ìÇ0¬–FÏ?ËÖ»3 G°›Å÷£-L„ш0oººJ˜Š³ƒ‡`&îà)èâþèýÞÍmþ\Ôþ—=3\{QBdŒùyº¶=GÙåŒÏ/„®÷ŽÖðÔK !ÈùÖP¨*É:‡Šâ ›ç¡»¹‹z´Ÿ­z›"m6e¨†Öi“† +(¡8ÞºDÿ¨ÿ'o£ï? ŸÌ|÷O^>±%\#,•·ìeÞl«b¸Ø÷ŒF +È™°œ…ê¢(‹Ð3õ°÷€Wî 8³+nÃDïZ4?ÜÛšz“rž2—ê@1¤V× €MÃn"³³ÏSKN\}ƵBZSðG(‰`%CÐÏVJØ?ïîË!Peì$ ÍœÓ>èCeKÀrý™bˆ7}12ÅܶÉ}äºÎ½‹ß`“— +rã« Õméáš‘[¨&¾ó“ö6‡”Ü50ÂEPtë’!Ipo3¬ÚYÛ¢ÞÜyˆÆ,Qñ»´(‹„vý¤.ê) ¿b«Å:³»zP ­§œ¥„ê*q@°5;KÀ¥ 14+èAùT=V â[ºá“ã1ú°L{µìÛ„ Ö©_é媽µR rvÔÞ¡¡T¾8·±ÖVµ,’È(¦ƒl  I´ýk ®HCº\ufi§Ç`/e³¿ ªr½ÍÂ6m#•H¸É¶Í®…mm©]ª”4ð5&„V8£Æ ·ƒpÆ@ÐC³¹ßüçªcøæšxîêiÿÓ»ù[‹ëߦA`Önîs”¬àŠˆ)ózåaKÂW„!9Ï5åÐîjšfUYU<ýaG–æð–c) dÕ^Ô¹2Aß"ØAèì0t nX¬ý ¸FmÛáÕ¹UÃŽ¼DÝë&|ËJÿôÊÔ@×è oGPGµ] Àý¨âŸÓ"¬Ÿ·®ïñJ=«é÷÷º˜r½)na¥–Ñ,×V +%a§ðr;¬ˆI|¾-²P,Áœ*¿ÝTÖívb·' S|ÃæÄùŸC '…,€%=¢Y¤Ÿl9'Iñ-§U+ôìx“îúD7Å·“vN»7ï„`€‘s¿?Ÿ–®Õz ÊږŸ†Ú+®ì-k)d7¸¼Ø§²ÁŸT!¡wšõ‰ã§ªÒ8uj“¼zõœ#²ÇjUjP g ΔjyÈÏJÃYF\Í®–—-w½#ö‚'!ÅÈ`úiÒx&è`«ÔýZIc"G:®éÖè,'d>½¸p½"(vm¾:m̰FpAÏD£.êihãéêõýËÕøòq¿.[ïüJµýÛ;mL ´FEσôkömüÅiãÉ®ìŰ]ÍÅ|6qáz¤†ÆÑœ„6¦¦µ<Ž7ž <| ºÀŸ‡8ž®nßU°œÌwô’ÕÞÍJ\.NBSahYÂQÒx&ê°»¨_–4ž¾¾÷„/¸g{úú‰´1tJHSö•ÐÆ|"m¬]ݪ[N+'J²` +1FË“ÀÚ¸;Bó“€:Ú˜õA?E³S {Ú˜ö‘SÛw>þÛ§ŽõaêXpz u¬Ž ŽÙQÔ±™ÅÚš#¨c:;Ö˵ãŽÙ±Ü±œÅ ò;ãŽm%j¯"¿î)‹|dT 9Lý_Ãÿ´Kj- +endstream +endobj +582 0 obj << +/Type /Page +/Contents 583 0 R +/Resources 581 0 R +/MediaBox [0 0 612 792] +/Parent 572 0 R +/Annots [ 580 0 R ] +>> endobj +580 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [71.004 367.478 111.003 378.357] +/Subtype /Link +/A << /S /GoTo /D (requires__requires000011) >> +>> endobj +584 0 obj << +/D [582 0 R /XYZ 72 686.127 null] +>> endobj +585 0 obj << +/D [582 0 R /XYZ 72 667.868 null] +>> endobj +378 0 obj << +/D [582 0 R /XYZ 72 519.972 null] +>> endobj +114 0 obj << +/D [582 0 R /XYZ 72 505.402 null] +>> endobj +586 0 obj << +/D [582 0 R /XYZ 72 341.624 null] +>> endobj +391 0 obj << +/D [582 0 R /XYZ 72 193.729 null] +>> endobj +118 0 obj << +/D [582 0 R /XYZ 72 179.158 null] +>> endobj +581 0 obj << +/Font << /F46 237 0 R /F59 309 0 R /F73 498 0 R /F47 238 0 R /F11 313 0 R /F14 318 0 R /F76 529 0 R /F13 312 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +591 0 obj << +/Length 1839 +/Filter /FlateDecode +>> +stream +xÚíZYoÛF~ׯà# T›½wùÐéáA[¤©HÒ‚¦h›€M:$å$ýõ=Èr%J¶(5 +?qIí;ßì\6Ž®"½X`„a*ˆ)É%<¥ÐšD ü¼ã§×/ߟ/žÁ§¥’Êèü2R4’:EŠðè|½"É’ +MÖ®›„è¸ø+¯WºvßÏʛ­^—…ÛPåEòþüå¥\ôvɈ"&:àöÓùâÂÀGÄé+PJu”ß.Þ¾ÇÑ +¾¿4üR}´»n#.5!"ößêõݺkÝ:óÜ2Ï¥¼-P²d˜Ä?ÖE»›Ç‹³wXÀg°Ð³3Â"‰RÅ´9#‰”E I"݉þtÛ‚S ¤¥Š–£]8’é÷ÊæMÝúu‘å×îÄŸûÃÖ—þ×Ö"$t—„ T'¦¬àô°O¿¦É>ûeµr‹­Ãj°i]µ]b6uîC[X•´ ϼ.. ™!Ïˢ귰èþ …{ñºÃÊë>0¢Vw÷aݘ ŽYüCVy +ÿóº-¼Æ—ÖO€ÔÝ•¢WhUVWÖ 84ܸH2“îØf±*ìíJ–Bêøl]å]YWø°.ã æí®)–½I†]FËÑ=„÷ >‚œr…x9vz€©Ø„cp”jÚïat‚]Âåþ¦ðZ:{›•ÅÔjµvž`·dÖ²öLžÊb˜;ý7ç ÞÖë¨Tˆ¦Ó^kÛUP¶l„1AÊ. $mKÀ“*$´r¬_[|ll7¹ç¦i(ØF÷¶yþæ I…Yš‡!éˆtÉÐr¸X)îå¿J(f·Eg1‰§µ˜°ùëf”"„{£¬"HP6DÚSÒ#’¦‘à°‘}<`·Û±°A^±‘åX [^Úˆv–3niLš*æ + &B! Ë@èÏEuÕù,jƒŽÉ². ÁÊ…=Ÿ{ཬÜÓ\‹ ºÇ¿¬!ºkIÆÒxŠN{ÇúnâV*ðša÷Ž3„èm#p4Fù +„è9ct¾÷G'¦ˆ(u¤÷@¢HF‘êë„û½î3Oê´ûŒ¥þº¾½(šÐ}6¦­×M^´ûp=X½ª¡ÞÐóq=ŽÞáŠ9”0zÿ(ÄK²V +÷’*P#Nœ}¯.»‹›v7®³¤NÃ:’úª.+½á~S[³@u<™Ã¹¹ÂȽäÁ Îáâ38(w‘,IüÙ”…Ó²OÝð›­AàÓ¸F±¹œÐ!ß·nKŸå Uå>¹,ŽÌs¤}úvŒþMßK—ð!ßK)„?ÎìÓWàP$Cj)Óù7à8z{xJ‘ âè¼hÚ$žJD°÷ƶI˜Šó—`¦àÉ[~î‚Ql»s7£uo¶œ"\Ÿ"]¾éÃÕ  2äÐÈ̆úHzµÆÐ [D94ƒâ«‘Uáj‰iœçIÆy,õÑ8õÊ*sÍýu™¯ˆŠãµ —@·ÿƒâ§\Ã3ÿÃé§kukÜ 2Œá€\"ÌÒ¾éÖMõ¨N„h¤°i”43G^Õ•ŸâìmDä! !1Ž¢†¡2¯!06U ô%uiºd†!¯N¸ÓH +1 ú󽡨ôLé`ŸmK¨%dS¦ÒÜ›BÜCQ4!V2ºŸBª„àEÒPªžlË'àvçñB5EëPè]cjÀzµ-™bã$ê’)†t˜ÊPrfZÎûOÔÁl¦RÉ’KaÙ7)jÜ;3Xò¡ô€ªâ·iã„Pmò4#B…vTŸLq‚üMéPŬ«¶¼ª +ï‘y¢â묙(Ü­¶ë£@òe¿ÇT ´f7í¤) ÎÒBµØ¡‰1…Ô…ä 1ßa×”©CõX2Aðê«ôaC‘Úg˜M›@g7*d ÖF Z*†°©ð(*ïx»G ÀCÓjf›âQPN@'Z*75yj˜ÃËDzïä·Æ–&µõD?•B:Õ6rJ*žFÍ_ï¨z›îiÔü4jþŽšéÜY³ü³f +GåœÌ.´¤·%Q­N2k¦oµâÏšg +쳡_Û¬™Ñ=mÚáVÑrS/Íöžãè÷`¸pÐIbÖL±a5Ï:í=#¡§™4®]ˆ ++(g£z½E•(mK¶LšIÊ45Ï; k öiÖüÅgÍCø°¡ætþß`¤ww@JèÉIfÍD¦H÷C£‡fÍ3O_ƒ±àÿfÖ|¸º!T@ŽÕüYã‘ôjaQdÖl,/0Ĭy¦ÔiœÇR¿ì¬ùðc„ø¹"ó‹˜ô}5òÁP„hrè?×ýèzF8 +endstream +endobj +590 0 obj << +/Type /Page +/Contents 591 0 R +/Resources 589 0 R +/MediaBox [0 0 612 792] +/Parent 572 0 R +/Annots [ 587 0 R 588 0 R ] +>> endobj +587 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [71.004 591.693 111.003 602.572] +/Subtype /Link +/A << /S /GoTo /D (requires__requires000015) >> +>> endobj +588 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [71.004 265.449 111.003 276.328] +/Subtype /Link +/A << /S /GoTo /D (requires__requires000016) >> +>> endobj +592 0 obj << +/D [590 0 R /XYZ 72 686.127 null] +>> endobj +593 0 obj << +/D [590 0 R /XYZ 72 565.84 null] +>> endobj +395 0 obj << +/D [590 0 R /XYZ 72 417.944 null] +>> endobj +122 0 obj << +/D [590 0 R /XYZ 72 403.374 null] +>> endobj +594 0 obj << +/D [590 0 R /XYZ 72 239.596 null] +>> endobj +589 0 obj << +/Font << /F46 237 0 R /F47 238 0 R /F13 312 0 R /F14 318 0 R /F59 309 0 R /F73 498 0 R /F11 313 0 R /F76 529 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +599 0 obj << +/Length 1921 +/Filter /FlateDecode +>> +stream +xÚíZKoÛF¾ëWðHåfßC ¤ml h‹Ô1‚IZÐÒÊ`“.)9I}g¤H‰R$Ê@zè‰ËåÎcgfgf? '· N.'aF˜J0bJr O)´&IŸ÷|ººœüx=yqSIer½HM¤6Hž\Ï“÷©@dšQS[åõºšÚ¿fåÜ¢»0±¼·ate6,(fvúñúõŸ¥\ò>cD +‘Óãöêzò÷„À'$è+¡:™=LÞÄÉæ_;~F'Ÿüª‡„K Ïûäíä÷R­rT¸¡{D‹ÓµAóDJŒŒ‰V¹²«uUÔýMÆ'TuȉF +›$ƒ'f4e Ô“½%8# +üÀ’ŒSD„nýàUN3‚1NŸ¦”§år`<½]x®=¦‘Ô*‘Øíƒ²EF›ÖN»– œ ©$°ÂHã&@žìl5 V2ÐR<‹X)aÿ¼/v^ UqÁžE¨¦ˆsÚúá-Òr¾+™:‰~ùÙ’)æîLô%×µ .þ€žf\ªtYx ¼¸PÝóË’Ü»'»·ÅwaÑÖæßÄEÃŒEŒÐfÍÓN”!†U³j]ÔËÛÂÆhœMUz—W +òɆJhБêl@ò›%·‹ÕÍ”àô¾T lä(%TW‰=Š€%¨i-QWSŠÓÙ YAÊOÕ#cßÒ§‚ŒGéÃZ1s[¯†lBÐf  é媭•)†0DF9P™@tyábFáP!£˜Ž¼]€2$IÔöϰªÇT -ìn³J{=|­xr GY…wwœýà±*çëY|ù´\Å*¦ S*"]˜+׫ÇõªFN6¨.‘†Sæ’¦¤ñÔ¼›BZ1”D10؈—òqµ|Xþã]¯«Ò=i:Ëïgëû|eÃôŽ +Žrí4ã[Ú¢ùîÝ¢›Øðu‡QÔ½eD½îa¢ ”Œc–þ”‘"~^×6j¼ðq¤¡Ù±BóeqëÍ€û‡è„ÀÉL†m»ÁÜúöhš ©Ó‹u1[-Ë"|ªìßëeå‚Á½=V6‹1æLÒ®rú{Žá!rå%ßÍ ½ÀàPiÚ¼Åè?:…‹«A­`o7r> õZ‡HðKroY¿§Hå}Â˜Ø ÷1ÄB4A<Ô +roßèMÔAØ ´Õ’¹ÚìºL?¸ºÜîvÁŸT!íQlëœ| {ToÇ]-oëØÛ·¯8"[ï¡þŽ3 çp¶R<ž©7®¡Ë«üÁ®\3MÒaE†lÝ¡VD씡Ý”µýÉsÒ#bLÂ( Ò°:ø»Ó")Ö­€`1ìy1¤©i{ŽP¸Þy¬Ð~#/”wÙú‹-n›åóŽ»)…œ4På–Exº³ãÒ$øô×uS¿ éõÚ:+ÓÄÖn¼]ð}à Yz×AM<Ý +}ï9æl|ôœG¢Ê»ÖúÌèÁþááJtÛÞð'u8|ºR[?ÜØª>ÛAS—ëjfëC~=Y½¾_\ËW’Ñ~=Þû•iøðà®aÈ~¯R¸S•plàI6÷†ûz¯_GIöjWê›®Tέpòm #l°Œsw„(¿ä«EœÂ%qPîfš‘ôË +Ú´lª7|ómLuÚ”•/ç„¶%¿KšB見0 +=L´YäH› +m*xj>”|éî"Ýšß-îƒGàTOöØ3=:þÏ#ᯠ¢à©s‹¢Ã¹˜æHÃ=¢¹­2—Ͻ'`œàÁ3Ðü2^:‰í1‹:¼ùv¾MoM}l/t{Ü|²º}O9¦ãûŸ3郫¥FZÛÿ83€9€'¦ ûyœÔa?w¥íg§Þ²ÈÃ5ÇOä«<¶CQYû<°ºCþ?y}ÿ¹Tã;˜ô'¢ÌŒqÔ4ßdV'‚Ì:¡ +Ô—çcÌÊsjpyb–Ï!4"Ì]¡fþ"=¾Ìz"¿/³gÐeÚ“›»{æÓç>À¬÷Ì‚ÓcfuÀÌŽ˜Í(l×0Óf}¾‡fv,Â,G!Ì‚ü0B˜ëåçq°²h@VA»¼û°²ˆø%<»°2D¹,YD,Y,Ö4X2ôÐKî±FÜœcÇݽ56²hAXÑ‚°‚Æf  ƒç…F od#"‚ sa‹0³ýtÀŒaÞK™AÌæ½ÍaÝ3†É¨.LGua.03v̘7˜±£ˆŸ#f 33vl[ÌØ+ü5̘R7 +ƒ3f˜u0c÷iƒ»·îe¬]Àz~yЩŒ™Bô[ÁÅN©æ§Ýõ¥Ó9ºÝ- ·H¿£H܃ n|OM»ëCá°B‡J¨Üº;þ§@â—ïþ8øgh¸ “"§þ™á_ïìç+ +endstream +endobj +598 0 obj << +/Type /Page +/Contents 599 0 R +/Resources 597 0 R +/MediaBox [0 0 612 792] +/Parent 572 0 R +/Annots [ 595 0 R 596 0 R ] +>> endobj +595 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [71.004 480.404 111.003 491.284] +/Subtype /Link +/A << /S /GoTo /D (requires__requires000014) >> +>> endobj +596 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [71.004 154.16 111.003 165.04] +/Subtype /Link +/A << /S /GoTo /D (requires__requires000018) >> +>> endobj +600 0 obj << +/D [598 0 R /XYZ 72 686.127 null] +>> endobj +379 0 obj << +/D [598 0 R /XYZ 72 632.899 null] +>> endobj +126 0 obj << +/D [598 0 R /XYZ 72 618.329 null] +>> endobj +601 0 obj << +/D [598 0 R /XYZ 72 454.551 null] +>> endobj +392 0 obj << +/D [598 0 R /XYZ 72 306.655 null] +>> endobj +130 0 obj << +/D [598 0 R /XYZ 72 292.085 null] +>> endobj +597 0 obj << +/Font << /F46 237 0 R /F59 309 0 R /F47 238 0 R /F76 529 0 R /F14 318 0 R /F13 312 0 R /F73 498 0 R /F11 313 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +605 0 obj << +/Length 1934 +/Filter /FlateDecode +>> +stream +xÚíZYoÛF~ׯà#”›½‡HÚ"u @’´D;lÒ%©ýõ=H“2%‹¤ä!O¤–»óÍÎÌÎÎ|6Žn"/0ÂŒ0aÄ”äžRhM¢>ïùtq¾øñrñì † 2’Êèò:R4’Ú Ext¹Ž^Ç‘eB޳2­¶å’è8ûgU¬3ôΟmn3ÿv‘]g~B¾Ê–o/_,ð,å¢× #Rˆ˜âž´_.ÿ.¼âˆx}2TG«»Åë·8ZÃø +Ïè胛uq©áyý¹øãA©V9*ì«}‹ÓµAóHJŒŒ Vy¹¤ÕY…–„8þm[ÕaÔ…ö³3Bº¨’ Ѝçð~ðSzŠ)¤¸n&|ïe‰C€å¬Ñ+FN¢YË} 1k93† !(p'ãHê­÷þ`MC¢.êïÛ»«¬ìÑnèTŶ\Ù ÙïÕÑêõÝÂl6šáÖyë½_±DÚ¨Ã[  ²ß­îª"I)âÌxß\×W·Õ~ÇN‚ököe±Ém‡sN㺰OËpÈyg5·G¸9Áo0f§œ#£I3‡Ñ)ö‘â¢Ý)wµLHü©^’8óZ¦e™~òßlDÚ¡û2KVéíj{›ÖÙÚ[yU§y]ù)WiÕ|)r?T¿Ëü@+‘‰Òáý¶ne×K*¬Ú4±zG‰THJ%.dCº]m2;tƺ²ðZ=ý Ì[ï΀0Ánfß¶0F#¼éªrÉT¼Ú{&âž‚.îsï÷nn»÷ç¢ò¿ìÁxÈpÍE ‘qÈÏãµí9Ê.g|z!4s½w´†§ž[Aηæ€BU©pHÖT{Ý< uØÍ]Ô£ýlÕÛäi½)B5´Në4T@KŠã­KPðôÿèmôý§á“™îþÑËG¶‚k„¥ò–½Èêm™÷»žÑHa9–³P]äEz¦öpBà‚3›p&ºmѵ3ÜÛšz“bž2 —ê@1 ]¸ÔÁ4Lá&2­}[‚p‚$' J!­‚)ä{(‰`%³ùæ¨R"BLu] a*ƒ¸›9‚™cݽ/mX¬#SlƒD™b¸ +ì#§¶í|ÿ‘z7¿Á/. $åÚWªÛÖ3xåmÙÅw~ÒΡÖn{”aA„" +*tj“!IpwSÚV0Û¼ÚÜäYˆÈÕRÅïÒr 4`)­×F=àËfŽ-—ОÝVƒZð€™¤…îj±Gk +Ѫ 77¤ÅÕ»¦Æê‘0Iü‘„ yŒ>¬-P›ûe×&±N+H/aí$ªD1HpPÝQ{‘†zùüÌ[SÚ²H"£˜²1#C’mÿ(nÒ3“Î,íôl¨ì¡ö·TY¬·«ðãÃ¦éæ«ÍÇp›më¶}m}©]º”4p6¯àÀÙ¤‘M»²I\Ü×›»ÍÎ?ðÓ߇$nkj¿$àÂô­…õïi‘ú9 'C¾–þ¹Èª…ûÍȰFÜ̱ãã½5®Ê¢ +ï BÑágûš€¸~À’ð¼Ø‰ÁÐPÛ~§ùÚù-ÂHÓw„áÌiãFºí„ïü¸³9Ìóºg~0¨ ÃA]ó‚„o_Ü@ ç,þ)ÍÊðyë;rí‚ÀŠu´fÖ(¼Þä7nç¸ßÒd¹åÛæ«P-Á§2ûw»)ÓáW·)k§8å­8ÿê8)ƒlwD¯HŸì8GIñ§U*˜Þ:¾´:·Û)¾›t; +«¼;àÅG‚}ñ¾§¦Ýµ!X¡P% F/ÆÇÚ)­ì%k d÷rq¾Kdƒ©BB·å™uˆc§ªÑ¸½”Û[àù«¿è£}¨Jƒò×h§*ü¬”1ƒ«Ž«É•ò¼å®Obj$¢SÆŒbd0}š0ž:Ø&õ@¿V˜ÑÝÖxkôƒ–2Zœ¹ÞGæ.Y‚2¶×(thGPÆQ‡Ã¨‹zÊx¼z}¿Àruxùa¿Î[ïüJµý»;eL ô~FEOƒôköeüÅ)ãÑ®ìŰ]ÍÅt&qæz¤FÔ˜“PÆÀ´–ÇqƇAøóÆãÕí» +–“鎞³Ú»Yd¸8 aL…A¢aÆQ‡}ÜEý²„ñømô½'|Á=ÙûãפŒ)…óCÙWB›ʘ琉¡—²u«fl6e õ™%{š2†»â°–3†ÞƒÝÏÃUs +PËsÚ}‚3Óg"S¨Ú,×C®ªÌ»¸¡‹Õ>ºX ùÐ|ì§‹•OÒÅPA3> endobj +602 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [71.004 367.478 111.003 378.357] +/Subtype /Link +/A << /S /GoTo /D (requires__requires000019) >> +>> endobj +606 0 obj << +/D [604 0 R /XYZ 72 686.127 null] +>> endobj +607 0 obj << +/D [604 0 R /XYZ 72 667.868 null] +>> endobj +396 0 obj << +/D [604 0 R /XYZ 72 519.972 null] +>> endobj +134 0 obj << +/D [604 0 R /XYZ 72 505.402 null] +>> endobj +608 0 obj << +/D [604 0 R /XYZ 72 341.624 null] +>> endobj +380 0 obj << +/D [604 0 R /XYZ 72 193.729 null] +>> endobj +138 0 obj << +/D [604 0 R /XYZ 72 179.158 null] +>> endobj +603 0 obj << +/Font << /F46 237 0 R /F59 309 0 R /F73 498 0 R /F47 238 0 R /F11 313 0 R /F14 318 0 R /F76 529 0 R /F13 312 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +612 0 obj << +/Length 2168 +/Filter /FlateDecode +>> +stream +xÚ½Z[Û6~Ÿ_¡}“јáTh³ Åî¢Mû’f ,ÛÊØÒT—$³Aÿ{/²%‡vÆò O¢(ž Ï磣U„£—WaF˜Š0bJr O)´&Q Ÿ|zõòêÇ›«ç×0• DRÝ,#E#©¤nÑ›X 2›Sã¼N›®žçdÕ"Gk7]lr7z•/s· ÌòÙÛ›_®ðEÊEoæŒH!bJFÜ~º¹úóŠÀGÄé+PBu”m¯Þ¼ÅÑæ1ü}°«¶—ž›èõÕo;6nïê`ïB#"ýÞÿ;#„ÄyÖVµÙ!‰Uk4¾¯«E—µn¶ºo‹mñÿ|á^ÛÊ=³t“u›´ÍIS|ôË»û®mÜ8õ,R·øäh»fñ?«¼9 |yý;˜[<¿&,’(QLÅÖˆ'$bHétÿŸ[6ÚŸ@Zªh>X¥# ï­×0««Æó4[»ÑíC¿­jéw½¶.î„#&t4'%B89E {†… ÓºNÌPÄi¹psn‹0“UeÓ¦¥_ÚäV ˜·R`&«ò匊øwŒiVä¥ûÎÍaÓ=w“^]˜öêœc$¬ºn¢k;ÀꜳøEZz +ÿ¹k¬[afiƒÀ°µ‰÷ +/ŠrewŽÇ[†$€,UTûÂ`‘ÛÔc_weÖUé>ÕùŸ]Q[§ÃÛ}ÏûÚ-±Êvî!}$ð‹)Sˆ‚*V° „G‰Þ­a4ÀÅŽÎáò~“{½©a4ð¥ÑÙ»Ý,IQÍŽ<•s \$˜ó=Mv»v1dcŒ +…¨12øç±ÆEÈÖ Srì +ÌAéR…„VŽß+ë[ÏšFîyh +ѽE^¿þ‰#rP©0Có0Ô"PÏ9rù#â^…_gÔ$LºÍ[SYIV$,àðëaÙ +'˦"HP¶+OIH’D‚ÃFNñ€ÕÎÉŽ…­ÚŠ ,GÀbØò‚³Šhg9ÆT£MRÅT¡#gˆ@ ÑÐååªõÇ¢«‹xW3qü~FÄþ0ÁÏîi2¦±UÇÿîšÖÏæ>/ÉPª$ˆbÑÇØ÷´T=» üÎñ"}n Ç(Ÿ`q9ctz]F&ˆ(uaAç¡À¡Œ"Õ7ïO†Ñ4©á0JýO·½ÍëqOSuu–7§üz¶zc¿P í…žî×Ëè_1‡ŽEŸÞ…ºIŽ»•B~Rê`ĉ³ïjÙÞnšã~$5ìÖÔ_«¢4UòœÚ~Åty¡#œ›~ÄáK¾x„³s¸¸#Ü(w;›“ø¡AÃç´ôg·ùfâÑL ûs˜›oý߸%þ˜·T¥›²Ç¼™Øqdž#í[DÇh’Ï݉/’RøƒC>œçzrÁ@-e2=.£·ÀŠŸÿðD"‚}46õŒ©8;š³`$øßj۽ˌƽ9øÔW¸þ¨t=úQOŸ¯îÈU† ædW_Hï\­1 ÏK[!èŒ94³m€µø"oÚã~ž&5ìç¡ÔGûÙ¨W”=Ê1i›úhFqÜÙR°ºSþ?{cÿ)‡x&ûÿ|úpÏn;Â@†1lK„YÒ#“¶«ËG¢‘ ÔM äÌ‘—Ué¯gNçaLL ¨Ým¢Ð‚ ±éJŸT…s«e ̘F’&Ó ??YŠ |JvöùÜ:E ­6ÓiîM±šÍÍ}S(¾%|úrE‚4NÆr³´Ëf*^›¶ìÄCEÐŽžB~r!ÍGò·i[÷PÙÜ +Íæ\ȸ+›bUöàÚ*˜Ö¡æ€b +tjta±[“>s+ÆšAë‘û;ž6À…Ð!›m GX=†Í®+º pIÖr¿%1ÆÞi1§úŸSŽXoÔ—y™×þÂǾ½O¯gàe÷º3ü °o¥%îÖsô—I0Zö}¼½%*ÊÚ]!A£C=Šæ|/š3èÌ ð>¦Û{{ùÊýÅ–ùàºÙ f0ÿaÛ, X«µ›¼¯j_…9óü†By\4î[±NEPëg7åî»`°©ŒôÍÀçËmxm&û[h"ë.k{S¥Þ˜ä¹‰ó½|ãïz?ß”î‚î]ð*”ŠLöLÿááò»g¾ëøö~v7'ùéo?Ý=Û«Çê?”6ù}·ÒÝÎC¡ñå jÖU·YŒ¥(g¼Ç|u›ÞnrtÆMR¢‡|šS ßéW¸Ib*šžŽ/¤·íÕQÆ/kŸà¨£ hBÌÙá +ßÑÖi¢Ä`ë4”øfûñî­ž}Õ×’uÕK ·öGçë:r!ÇlúUá…ôÎÁ +Ž?}¡1À)@ä;šíqÿNvïPb¸Þ©]lÆ7ƒÃ2‘Uu7÷Ué‹û)ÕY3*‹÷imª³ñ‰–ùìí= +ÔR“éq½‹É`º8å¡M£R!BØ »‡Ä4‰á˜Š ÅDVmºm9=$Nùþì}Œ' 5ÝùçÓŸ —(…„Ãü2¸DŸ +.‘³á‘ ?áO— +JÄãàÒSÈõpi$wÐrŒÅJ0´WòR¹Öõj,÷+Á$ú40‰%˜$“ X1•8˜$N ¤¯ ‹Üß2cäõŠŸ¹Ræ{ Ìx„Žs¿!Û;tdÞB +šyŽÌС#Ãb‡]ÌtÏo(´ðÔ{tdȆ+~v‹ŽÌ`ŽÿØËSž·Âctd&Rÿ!ô¯‚ó§û¯ñ¨…øUŸŠ@2($=ç“oïæwßeù}ì!•yB* ï/ª-xtóྺ¸`Œ˜·ëÊïØÆˆµÅºªçKuÄ—Êœ§þ;uù‹}Hà¿CSÈ¤Ô +endstream +endobj +611 0 obj << +/Type /Page +/Contents 612 0 R +/Resources 610 0 R +/MediaBox [0 0 612 792] +/Parent 616 0 R +/Annots [ 609 0 R ] +>> endobj +609 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [71.004 591.693 111.003 602.572] +/Subtype /Link +/A << /S /GoTo /D (requires__requires000017) >> +>> endobj +613 0 obj << +/D [611 0 R /XYZ 72 686.127 null] +>> endobj +614 0 obj << +/D [611 0 R /XYZ 72 565.84 null] +>> endobj +532 0 obj << +/D [611 0 R /XYZ 72 417.944 null] +>> endobj +142 0 obj << +/D [611 0 R /XYZ 72 403.374 null] +>> endobj +615 0 obj << +/D [611 0 R /XYZ 72 312.543 null] +>> endobj +531 0 obj << +/D [611 0 R /XYZ 72 201.31 null] +>> endobj +146 0 obj << +/D [611 0 R /XYZ 72 186.739 null] +>> endobj +610 0 obj << +/Font << /F46 237 0 R /F47 238 0 R /F13 312 0 R /F14 318 0 R /F59 309 0 R /F73 498 0 R /F11 313 0 R /F76 529 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +619 0 obj << +/Length 1605 +/Filter /FlateDecode +>> +stream +xÚÅYIsÛ6¾ûWð(M#;C{èLíINmêž·CKÅZ"].µÓNÿ{!J•HOzDâíË÷áè!ÂÑÍF˜G±Xr «J‘¨€×G^}¸¹úþöêí5<ÒHK*£ÛMÓH*b£Ûu´œ Dæ *ðÌIYs¢fæ·U¾6hëž_§;ãvÌÆ¸ÙÊÌïnß_áIÊEË#Rˆ¥·n¯þ¸"°Åqú +¤©ŠVû«åŽÖðü½å§UôÜœÚG\*XwÑÏW?ulœíñíB!"½íÎdkÖ¨|föŸÝÏ)žÕ•{µÎMévY^¹÷uR$YeKZOI‘VŸÜÃÎg©'î¹HÚMÿØ/×ÐÙ/¥)ÊV/ÏüyN0ˆ­BÛ“õïuéÙu!x´V¿½&¤—\bD…͵Æß¹#AÒ,Ú3·:(*ìÖ.7vB÷9`¤µŒ”!%‰£ÿqN­íÉÞT¶¦È¬ ù®ÿ÷_ †ª&ìdÁÄ ʺ¢yMzD´Ž„¦à-}Šœvu,šzYÏq„SD5^ î=Ÿ4Ž +L&dб"ƒh# Û@ärÿòxçz`RMêÁ¶I6X·ùnív«ÜllÛÒ[¥&«Ê/uœ!FùeƒYòø4ùÉO¤w!VÐ̱˜b¬8°¤ÎÝûã'q8Â}‘Y½¿7…‹b¾qk‘ÛX>—îWÓ¼`í:bï¢0åSžyÜè%EY¬<á7nñš:‘ÛÈ9–ã“b½K +©šn9µîDd)¦\„'Å8‰ÃIÑ9”«|Wï³ñ9q*øÛȱ ãƒ9ý0:5Þ È0TÕιLUÙ0êG¡kÀ_Pµ›g~=‰¼$†I—†ÛLQÝÄ‹Wè|A0†!/+Ó‡ÌØNÕl5gÛ¤p?6IÇHq¾cØÉ + ^éÎY_º…@¹)œÒÌ»RŠQ~ù±Àóòˆ’ͰÓ½FXvãLâNBဒí@‚Î>`PÇ1Ì.1îuü2»ý&0;³7Íø?n®­ÆÔÏY,²´¶˜6‘b1$‰ÇÔ_F-óÈêR†m±} KsÉüß;ö“Ø MÔWÀ8¤*Óãkq"}Óˆ¡‘# +^¯1€q ¤ü¿°‘";q ò]öTWaÂm£—+ºÈ1SãCw9ý…m”Ù·2±^§¦^ƒJ¾÷ˆU¯ü-@µMü«Ä-/ÁÁoÝò7ùgZSf¾)§"ÇZ0£€Tà ¨˜Ô‚™@˜S` AEЃ-ô9«†Ò, ñ«(—1‘¡Ý@ÎF>Ik"ß»àj"¨‡þ ØÎ…ÇñbÄ¡X¤“gá¡ìãáùȧ5¢J6È'8ÿ +ÈG…„ïÊñÈ7‘¾A>Ê9z"ò1H +úp…ˆâ]c8}#eBßÌú|ŠE¾Ëu]äöìèÐM£w¡ƒª£œM ¸Z…ÞãuÛcއnœÌáÐ…2CwT—ivàê¨ïl]¾ó¿¾É¬­Ý%ë9¹q±‘al-äBÓè]n"¨×¹P¤”!ËV gÆ(‰Ã‰Ñ—X¦™ðZ¡ŸËì’áx$/U* PKMÆòrú Ç[¢9ÌLÇ[_‚¸«¸•)ËM½{ãÝ^mÛ‹MóBºó/> endobj +620 0 obj << +/D [618 0 R /XYZ 72 686.127 null] +>> endobj +621 0 obj << +/D [618 0 R /XYZ 72 617.267 null] +>> endobj +521 0 obj << +/D [618 0 R /XYZ 72 506.034 null] +>> endobj +150 0 obj << +/D [618 0 R /XYZ 72 491.464 null] +>> endobj +622 0 obj << +/D [618 0 R /XYZ 72 430.546 null] +>> endobj +533 0 obj << +/D [618 0 R /XYZ 72 342.337 null] +>> endobj +154 0 obj << +/D [618 0 R /XYZ 72 327.767 null] +>> endobj +623 0 obj << +/D [618 0 R /XYZ 72 268.906 null] +>> endobj +520 0 obj << +/D [618 0 R /XYZ 72 169.442 null] +>> endobj +158 0 obj << +/D [618 0 R /XYZ 72 155.701 null] +>> endobj +617 0 obj << +/Font << /F46 237 0 R /F47 238 0 R /F11 313 0 R /F59 309 0 R /F73 498 0 R /F76 529 0 R /F13 312 0 R /F14 318 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +627 0 obj << +/Length 1839 +/Filter /FlateDecode +>> +stream +xÚíZYoÜ6~÷¯Ð£È2¼‡HÚ"u¢@’òZ¶¬%GÒ:Í¿ïðVZK²Wró”'rErføÍp.,Žn"`„a*ˆ)É%ŒRhM¢–G–ÎÏN~¸8y} +Ÿ 2’Êèâ:R4’Ú Extq½"«58Nˤڕ+¢ãôŸMq•¢[ÿý4Û¦~vž^§~C¾IW/ÞžàEÂEï׌H!bÊzÔ~¾8ùtB`Š#âåÈPmîNÞÄÑ|ké}v»î".5ŒÛè“ß÷BµÂQa§vˆÓE„ Œy$%FÆTÞ­(“2¹Kk{eWýûN²8\}t!þS÷¡eí^ò<"ÆD’3$† °› #D á€S¬áQòp…¨Ö!—8 zW&xй,¹ê² +a˜öXþºÛÖÙý6Û$ù•·Ô!pg”Ï¢½%#ç«nÑq¯9FÅòe4Ç8R0:/Ç57å°æº,kîrBsGKчžÙw¾@uÇŸ?Ò iæ¡9Oë]™»Ch5RØDk1 Ⱦ+‹«Ý¦ö ×ͳðÃl7d¹ÏN?`©eùú”°H"£˜v°DX0$Áƒ¿ý¶ž i©¢ug—ŠÄß¡‡ÁkÂI wàÖàTšØ©X­ Æ8~°>¹È¬ìØÄ7׿Ê4â€# ›ÒE¸á®µö"œ N ‚‹7Aá!@Þˆ†Ð&^„«$àxŸëU1ÄTq$åË\U)ɬÏô‚žˆ‹€µ5‹ÕšCäÏòÚë]us +fÀð8ðpg·iþÊoêó˜ˆj6 "a)š=#”(;#Í®]^e7yDݬT|›”Á†y×8áš’5§>`Ì4e{‘›ëúrEp¼­¥ÐHr³\ŠI,¼…¢*WÇ›\…Rÿ?WiUÁ€ítO¨yîîjÍ¥@Ê­)G,øˆq·C‰MבÏò:²ëuœO{°v ï¶(ýoûšÜäÞ;ÈWþW ¸çx+÷e–Ôi—BYeEŽ,wÝ>¸ ix0?©%À©s²œMÜJ`¤ÀÅÍô¥Ž‡¿p¹oݼå¼)‹*H‘&›[¿åò‹» |sa¾Ô·áC–ßïš³e™|ñË><47¡ñ¦È«:ÉÇ*­ûÔ6Ez½¢ÂÚÝdi^ êÂ^ÄÔonÄ¢^,§ÆuÝ¸iDÕq±«AV´‚ŠÇ?&¹_¾ «»ÊY<|¹vІ‰/gÂ:Ô3Y~r[Ýøy¸ªãv%'ºË75¨Û/•é§]Vzí¸MºÞ$ÛÍn›4[LV{ÀLÌèÀƒã`5tàÁõ”ÎÁWÓ®û ×l±â6"´VGAÖ€ƒ&m|O<.61Þꂾ×=LkÐ:&Ø\Üfá\ï²OÊÖHwYž†ÕÏ·IÝð¨êr×Ù +ÆÓ<³2È‘æÉå¶‘²ÍLªt ¶:yêm†uûžëì.EUêT +b«? jM¢¿BÈ!Œ­fç£ Ï»Z‚[ž³eµ‚XZÖW™6­&f2¬&zLIó›ú¶Ÿò‡3 š¬×>®*¼ü_wU0 Ë4¼arŸQÜåï^°BŠëfÃwž£h¼ª9¾`ƒôôñi+ZvÞYƒºEª…½($$ÄRv<à˜Íä:lF]®¿íî.Ó²oF‡ÆS»r“Vz=^¼ž^ìq®g«uÙq¯U-à"b™VÁ› +¹ŽÖàUé>­ÞVãzÇwP¯=¾ï +(:œb)óÙ Œƒ±24ÃéŒXMÛt fM †©3#ˆ%ÝìÁÅ<ÊÚè]…ó!fÛS¤]Šô˜Ž6%µy–J!­x¶=ÉÇŒ ˜†zÎÆ@@P}Ή­ýþõ:ÍPÉÆš¡Q„zºj-ë©f(5äÉf(Û•í?u¢ý§!âÉö_‡ÿÍPƒ0çË¥o†REŸ× 5ûGÉ!Ÿ@c îÍyØ^ïe¬+Jо!þdS|§fÄ7E¹9¢+:«øŒ®èP£S,itÎjß~kt~kt~Fg'ƒ°ÑÄþiÅMÎÏÿ<ƒáM($´j²‹˜ûG̳Rn£OÛzóç_“{üIMŽýÛË +Oõ +endstream +endobj +626 0 obj << +/Type /Page +/Contents 627 0 R +/Resources 625 0 R +/MediaBox [0 0 612 792] +/Parent 616 0 R +/Annots [ 624 0 R ] +>> endobj +624 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [71.004 157.861 111.003 168.74] +/Subtype /Link +/A << /S /GoTo /D (requires__requires000003) >> +>> endobj +628 0 obj << +/D [626 0 R /XYZ 72 686.127 null] +>> endobj +629 0 obj << +/D [626 0 R /XYZ 72 667.868 null] +>> endobj +387 0 obj << +/D [626 0 R /XYZ 72 567.305 null] +>> endobj +162 0 obj << +/D [626 0 R /XYZ 72 552.735 null] +>> endobj +630 0 obj << +/D [626 0 R /XYZ 72 434.341 null] +>> endobj +373 0 obj << +/D [626 0 R /XYZ 72 298.401 null] +>> endobj +166 0 obj << +/D [626 0 R /XYZ 72 283.831 null] +>> endobj +625 0 obj << +/Font << /F46 237 0 R /F59 309 0 R /F73 498 0 R /F47 238 0 R /F13 312 0 R /F76 529 0 R /F14 318 0 R /F11 313 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +634 0 obj << +/Length 1835 +/Filter /FlateDecode +>> +stream +xÚíZYoÛF~ׯà#D›½‡HÚ"u¢€“4E;dÒ!©´ù÷=$seê"•´y"ÅÝ983œùö³qrŸàär‚f„©#¦$—p•Bk’Ô°¼céêròÝõäå<2ÈH*“ë»DÑDjƒáÉõ<¹I"Ó8-ê¬YÕS¢Ó⯼šè½~±Xþ+ü†2/¦ï®_Oð(ç’›#Rˆ”òHÛד·8!Þ_ ÕIþ0¹y‡“9<mõüív=$\j¸.“ß&¿>9µqŽ +{k/!"Ât#BÆ<‘#cBTÞL)O³:{(ZûÊ$mâ÷Ýkb{õÙûáâ¿ï}À)AÙæÎ)ˆ1‰ä ð› #DPá§X'p„ „.…¤ÖEnY”.TÑKVÅP£\u +…0ÜFF*Êû6Ôkuê9ËÓS"Ò"o«Úÿ^”þzû©-4…"ÄéÏ«¦ O]i¿¼ ¤kUD±÷œ½oý–È1…×ë ßx]D¢çÁFù€hÄU`ÕÈáE4JÜ׳A‘#k‚‚t2Ž”¡>z÷Ñ0«ýEÔµúËêᶨã"Ú.¦ZÕ¹-šÝY=Ù½8-Ìv£i'ïóJ4Ò‚ŽË+…ÁBU")Eœáû»övÙìÎì0»ý™íÚ}S-ÊÖ¥–²´­ü•Ñð󎸀Àéú+~‹1ëùÒ92z³ÇÕªShÛ‰¿Ëê:ûäo]!Á,y¬‹Yž-óÕ2k‹¹_Ë«²i³²m‚|Ö¬Wª ²}¿­‘ ºØãª]+*î¦TXi¾(@ã¾=9Êq¸lxŽ“÷Š%âF^5HE ŸÌ¦ž2•æ»+t˜áþ +í~òÛi=¾hÿËUí¦­çTÀÞTŸìnœ*§Æ Oõ8y—ja8Œy12ÕÐ’!ÂÀŒfÄG|^ÀÀß•çV{óY}êDœZWeÖ.ªLæY›ù;ÿÝK‘îÉòéÎFY†Aσ³<@þDd.™c¦ôUѮ겎og@#…M2ƒ+fA¼¬Êpt‰ložÈaÉŒÛrP›“¢ˆªéŒ`l¡mÆ ×±5Œ¶žbbÐê ócçÀžQ)fŸç‘ œ In ÒŒ…ɸ¤¯‚5RžÅ(€^EYW}F‡™"ÎbT)¤9‹>Ö‡UóËZl?‡e°ÈÙV3{øûøõY~‹žÎ¸PÐ{[ T÷pÍ@Rl€ ^øM±¨ +º9Jô+"PhBt1FŸ&Ê‘s«²YÜ—E(È|ªÒ÷Y݇qàsàâ9ƉP]û·Má´lz½ÐÐZäx/vxbCÁ6êaBSœæ;âª5ÿ,Ñ€>½Ö6×Ge,”–Âó÷áU5Ô«ãõ¼ú‹U™ÄKuñaµ¨}vMtX [LðVû€™þ㇪qsþÔã“}ÍM¬¸Åk„ÆÁê$hƒ‹<_ŽM:üäºFÈþv×é CØqb Kwsu¹Mœbø&Z­qˆ˜cC#ÜŽŸM¯~õût‹AÝGéhm38³(®¾EÉô;=ŽwÀŸq ÚåYJÆžz˜ h´÷GFÿ¯%£{§G#.Çt8•5RÞW€­èY(JÁâÂAQ´Ú_F]«ç¡(Ow/Î ˆK5œ)ïóJ$DŸ…¢d#‚ÅQå@»ý™íÚýJQv ôä(Ç⌠ç­FÊûÅÎfâ,%Ãк9Ž¢h¸¿B»†?Eyº»qª0 #9œ¼)ïRM AOÎBQR#œàaŠr ÕÞ> endobj +631 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [71.004 391.388 111.003 402.267] +/Subtype /Link +/A << /S /GoTo /D (requires__requires000004) >> +>> endobj +635 0 obj << +/D [633 0 R /XYZ 72 686.127 null] +>> endobj +636 0 obj << +/D [633 0 R /XYZ 72 667.868 null] +>> endobj +388 0 obj << +/D [633 0 R /XYZ 72 531.928 null] +>> endobj +170 0 obj << +/D [633 0 R /XYZ 72 517.357 null] +>> endobj +637 0 obj << +/D [633 0 R /XYZ 72 365.534 null] +>> endobj +386 0 obj << +/D [633 0 R /XYZ 72 229.594 null] +>> endobj +174 0 obj << +/D [633 0 R /XYZ 72 215.024 null] +>> endobj +632 0 obj << +/Font << /F46 237 0 R /F59 309 0 R /F73 498 0 R /F47 238 0 R /F11 313 0 R /F14 318 0 R /F76 529 0 R /F13 312 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +642 0 obj << +/Length 2018 +/Filter /FlateDecode +>> +stream +xÚåZKsÛF ¾ûWð(M£Í¾‡t¦McO;m’Ú¾%iF¦([­D:$•Lþ}±J\™’%Ò>tzÚ%¹ `,ðNnœ\œa„a*Áˆ)É%ŒRhM’>ïùtyqöóõÙËsxe‘T&×óDÑDjƒáÉõ,ù0ˆŽ'TàÑíüó×1Á£,­?¯ÖKtç_Ÿ/–™Ÿ]fó¬=Êò4ºþí ’-ù0a2¢"¢öæúìË)NˆW Cu’®Î>|ÂÉ Þÿfé|s«V —ÆeruöçV¨pTØ©‚B„i+„ Œy"%FÆ¥¼S>š–ÓUVÛ#“QŸ÷ ‹Ý¯Î#„Sÿ¡ó€P‚²Í™žr?"Æ$’3$@ hÀj‚Œ„Sœb-Å&v´"`Z§¹e–;UE‡&¸Š¾L¹j3 +a˜FLÏòÛ:øk1÷c6MÃðja½º(ýó"÷ãÍ÷:«ÐxÂÀéÿXWuxë\ûå9!m®’ Šˆçøýè—D‚)¤¸n¼ò´ˆD•!@ ŒòÚˆ½À’‘ýhÐvïCÌ*Eô! +ÌÉ8R†zí}=èDý¸v;Q›ëÛõê&+c'ÚuªX—©ušýV=Y¼Ø,ÌF£f¶ßÙUhŠŒ~äpý4%ûíJ"T%’RÄ™ñ¾×7Ëj¯e{òí¶l›ïûb‘×δ”êÂŒ†{Î[ÛäN›[ücÖqÓ9H¹Yã|Õ´áÄϦe9ýî§Î‘ —Ü—Ù$.ÓõrZg3ÿ--òªžæuöO«æKHÖw»y È ŠÝ¯ë†P6Saå¥é"ŠÎA“‰°‰“'ço!V¾Ë—@‰1HãËl•9öö©Sà˜é#ôAš5¯ß½½ºî Ä¨Mü§PúÛËõƒˆìéíXß-‚ÜA5~šÙ‰­A“/`*ñèÛ]æßê†à+?|Äã°ˆ„‘"„à=ð +ò>óKý™Üt1XÀ*•»#MÂmvB{‹i=Ê›h¢½ÐvÜ*Ü>¹4¤õvKcäÖŽÆÈ0í2ò„ƒC\7ûcòkïMngYfÕ}‘‡gwc{¡(·‹|ºl’¥—¦{ܬ;ž~™£8f·+­zÇÁû}T›Œ‘,8B”„xT•cpÒt ìǸ3FŒ +ÖÊp÷>6VþɹÆ&ϵ<à ©O76lç¬?¸ß›ZhDÕP8 ™ßª°¢–!ÚÎ2À•{íÜk·Û\· ¯eS+ +ÜëzQü;›ÖS?ó‘GŠÑ!+Ÿ,ll%ØŽu#Ÿ¼ýÄòOP&Q^—Y½.óîšoWÿ)l ‚‚|pÜö¼ÈC}ñÞa Op[+"ž³¢‹%2íVgª ï(3½/-Ö/fœDÜ-ÎÙH*æ\U™·¯…$Ó¥wµ‡GªÝº\"äyð|áÅ,À!ÉDu"ÖÅÚ¶‹eà¶¼YµÎ«ÅmžOLÇjt7-»´FŒ⼈¿BToøÛªÀö–U§á-"ï/ÅI¬&ÔF[˜)àœ=j5êY”1áÄ@ Q1 +kÇ®:b-‚UÛ1j'6M$Fš‘d±ñ€.έ›5`Ÿ%ÎßÓÆ°š!I‚u`tidm­Ò2wÕËö&{˜Q³uZ‡º„J¤vPÒ@å—"³ „Ó‘MJœª4ÓŠ TÆ‚/p ‚ÎiYTAŠÐ?â›ÂÞ9ÐÄ›º ^4èØî Ø +>»Âasº)ôü×*«cjqµÿî7Œ^ÄÌ/nÄ¢^,_æIP#ßAñޏiD…’b]ƒ¬¡ÝõzšûÏ7ák¨àÍÜÙ&Y9­Öeøž³E~>äð”ùy8ªµ/ùóužœŸÊìËzQz뚨KLV{…™îZ”ƒ×¸ü~jmn¹Ñ·(ÐXY-mÐo†šÜ怚¼B«Œ¶ØÁæÛ w“ˋݦ<”`TA"Üà«1×j? +„p›w6ÅõÕÕHT; úC@žÑà?_TÓR}Ö8ƒ‹/ |ôEƒ÷;Èϰx¤ztœaH\=ÞïdzïG<ÿ“ýï“•»ì©ú»Ð°ýÎ…¨a5[n€S™Â°#à=¹vzQÄõià§‹Ù…Š4îßø¸ßÛUÛ_)6~BœjYë¸xO¾Ý–móýŸ6À÷8èÉZŽ ¶sÑ¿]5p¿wP©¡€3OÒ™„òêjy\g²'ãnm3~žÎäéâÆ¦‚íý3Ì ÝÞÌö÷.ž¤+I…A‚Ñ#º’=¹vÛ¸Íõ9º’§ ÛHxÈÛÛÆ§ï?±/I¡*×” ëKÒÇû’Ķ$“ÌÀía­¿ ¹ždgÒþ&àDÍáì‹æZd-öĶZ¤q´8l<Ô†´^ ÈÓ°å +€˜ˆÙ®,ü ÿ…¢ºù/Ì.!á((‘üj·£„£jË;ÃB°ûÕ^ƒ¹íyM›PÖ\‡y¨œCÔ›7¸k‡ÙÖÈͲHÿÙö^Vëe½¸_.ÒÖej þ¦7…{6}P‡7í«ùÀwÔäèqEDÿû.Óð +endstream +endobj +641 0 obj << +/Type /Page +/Contents 642 0 R +/Resources 640 0 R +/MediaBox [0 0 612 792] +/Parent 616 0 R +/Annots [ 638 0 R ] +>> endobj +638 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [71.004 355.522 111.003 366.402] +/Subtype /Link +/A << /S /GoTo /D (requires__requires000002) >> +>> endobj +643 0 obj << +/D [641 0 R /XYZ 72 686.127 null] +>> endobj +644 0 obj << +/D [641 0 R /XYZ 72 667.868 null] +>> endobj +372 0 obj << +/D [641 0 R /XYZ 72 496.062 null] +>> endobj +178 0 obj << +/D [641 0 R /XYZ 72 481.492 null] +>> endobj +645 0 obj << +/D [641 0 R /XYZ 72 329.669 null] +>> endobj +479 0 obj << +/D [641 0 R /XYZ 72 193.729 null] +>> endobj +182 0 obj << +/D [641 0 R /XYZ 72 188 null] +>> endobj +640 0 obj << +/Font << /F46 237 0 R /F59 309 0 R /F73 498 0 R /F47 238 0 R /F11 313 0 R /F14 318 0 R /F76 529 0 R /F13 312 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +652 0 obj << +/Length 1944 +/Filter /FlateDecode +>> +stream +xÚíZKsÛ6¾ûWðHÍD㇧Î$Óδ®oIš¡$Èæ”¢’Jšfüß»xI„L)’lO›™ž€À»ûa÷[JQž\'Ø<^aÓ4O„a†™™€§àJ‘¤13‡_]¾:{quöü†r” *’«y"i"TŽ$É’«Yò6刎ƔãôzþáÓˆàTO»‹U…nÜðEYi׺ÔsÝŒˆJu=Õ£÷Wox¶äí˜Qœ“”ŠHÚOWgÏ4qBÜq9Ê©J¦‹³·ïq2ƒñ7F^®’ÏvÖ"É„‚g•ü~öÛŽÌg Àó„”sNƒ¸BDx \¬êiW.ë6ÖÉ?Á|²g>"PÆT2¦ Á€w”òh-hÆ1N˺óÃFc ÛpªoL΃É?´­Þ–c¦½ÃY¶Séú™k­ê¶¼®õÌõ¦7Ec?¿ÏöΫ(8wTŒ™›i•¡\‘0çzÞM*¿Ç§Å鲜 HÎR˜ ˜†9m3ý¶X&Àô±3Ýv`"²Ã}’% +oÏÁoœ#ÁX2& #óxuaLLýF,¼IéÌ—£Œ’Ĩ𻹏Y‘TŽ2™'ãÞ,eätï.×'wåmõÅõ&þ9ìuEÝ¡Hƒ-•Ç™D<£ppp('Œ¼Â8äÓ_>°2; +$ß úȉè“HdüôEè{tÔ Ž¤ÿ&êÈñ¨cO‡:¦"ò?‰:oœëZÅím3Êxº¼mÊ¢ÓA^c¨I Yú˜Òý0í;äðHYÖe· °èt­cÐK©®DFïáp èáðÔ*‹ªüÛ[œÑñäK0p–÷PÓƒÞ“óàè=ˆâ@Á-)ÎÓýx Ò=vXÜ: “â X[¶0lùðˆP#_À5Áò´8vÐ2C"ÏŸŒÅ1 +Rxö}D4ª¬w†²¨^Ù.VÆ‚•àT"J®K6Ç"0ûRwThÆTA¯6å­©fö] A C,ËÃÝït37§*¦æ”J¦ÝÒ=çëÚÈu­  n@èËOªåôOo1òV*§…=Ž+íSÄ®",à*¨ªLôã)°C‚ðÈW‘)HðãÞ,ë+4ƒ£Ó«›² ç´ò:Í´éÕÚ¿ênt8ÔNõ›åª+ý +‘®Zkg§œÉð987¡ÔxL¸“8Q­¿ù—?¾~é¡'&À¬ÊÊߢö ÝíªY[¸ +‡@ßGõ¨%­GÅrºZèº+îáb`ƒ(±ò׸s‘ „_ϭĨh'â §0"@w÷Tî–U¾®ÝCµÞ‹„ #@ƒ„‘ÌÛ×\Å=!õ›ù{BºÊØÖ® ƒxàªViƒ^€ëB(1¡3YLJ6üí¤xÀÎ:üõ¢*ÈŸŽd:Xp8#÷k´½FäÀ ²:88Ã*L…˜í ¨pXEóöe›ŒaÐ>Ý¡¹’O³«I#CzòFÎVšÙf ŒpÄ0‰ñ¿'fó‘ëÄŠƒ^<=4Ç„ÙÊkÖYTH™DB ¥>c¾\ÚÐ&EZ˜ߣ#ÄÖŒÒCtƒ:‘ŽÐ7•Iƒš00qÜãÜŸéó¶¡1œRø¸]¿ošâK»5éÜM*ÛHF[Ö×61À+“tå§ëJ›Xé:6_É}ùŠ ȹ<Ñ0¯¤“óÂï3ÑÎYåˆ]òŠO?0mLh’‹0M¹•]ú¸-Cí]çsSZŒÈ^n·§Pý¤ýqU62½môxZTÓUUl¦,ç‘I¡dèOZ´aÀºÇ*ˆ½fÞ†!ÙÃÒÔÉ&ý’FÏ‘ …>°¢.4ýzþã»gn'h“;ØÛv@€¤_1 o2ƒã7³çwNJ˜²%ôÚï–3Çwî wþÍϺv‚74Z.| …¡ÛÐlKHlYö­åôn²g<¦Ûxz3 Üfá) ô?ß~›ìÛ¬zS[Ý…h¨ˆ®‹I¥·Ù +°Y¸Å~®cQßA~F·[]¹Ðèp&2ÆpÇ„¡[('Êiü«ÉES,Œ†#BÒáÏ÷Ãò·ßnÿä Q•íýÉAÄí‡uG#s="P;ÑŒ 5{D`ÏûD*š>yâ[QTürÍFØÐnˆL§íÿ@Â%ÂÐŒö„kpÝù”lÔHye’]§mHÎòËq·"Ö‰g 1¸ G+»2ðAv? +[ï @2¥ìƒ°%3乄2ŠpÓ͇£Ýh8mÛa8ô·ýuik®m'ö¾8¹Tᥟ‚Ö_|–èUÚþM:çû€q´~±ga9—òtdXmë«Ô%PDï?÷e¬¬>níbbc$9íÏÿNhSu +endstream +endobj +651 0 obj << +/Type /Page +/Contents 652 0 R +/Resources 650 0 R +/MediaBox [0 0 612 792] +/Parent 616 0 R +/Annots [ 639 0 R 646 0 R 647 0 R 648 0 R 649 0 R ] +>> endobj +639 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.921 632.346 178.281 643.25] +/Subtype /Link +/A << /S /GoTo /D (gf__vect__mul_8h_a15d42d058c64dec106d9e3e9fc2e1136) >> +>> endobj +646 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.921 604.451 180.293 615.355] +/Subtype /Link +/A << /S /GoTo /D (gf__vect__mul_8h_a7a1f65b032f03494dbc68411f5614bb1) >> +>> endobj +647 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [108.921 576.556 161.125 587.459] +/Subtype /Link +/A << /S /GoTo /D (gf__vect__mul_8h_aa7a737b69a0a77dc29aa28d0f17421a1) >> +>> endobj +648 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [115.915 548.66 186.39 559.564] +/Subtype /Link +/A << /S /GoTo /D (gf__vect__mul_8h_a84eb9ca31c934f05a8e3fa7a02fa71dc) >> +>> endobj +649 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [115.915 520.765 190.804 531.669] +/Subtype /Link +/A << /S /GoTo /D (gf__vect__mul_8h_a8f3e57729c3382514325612c54e20eaa) >> +>> endobj +653 0 obj << +/D [651 0 R /XYZ 72 686.127 null] +>> endobj +654 0 obj << +/D [651 0 R /XYZ 72 651.32 null] +>> endobj +186 0 obj << +/D [651 0 R /XYZ 72 492.57 null] +>> endobj +190 0 obj << +/D [651 0 R /XYZ 72 423.813 null] +>> endobj +383 0 obj << +/D [651 0 R /XYZ 72 397.349 null] +>> endobj +194 0 obj << +/D [651 0 R /XYZ 72 397.349 null] +>> endobj +655 0 obj << +/D [651 0 R /XYZ 72 265.439 null] +>> endobj +371 0 obj << +/D [651 0 R /XYZ 72 139.795 null] +>> endobj +198 0 obj << +/D [651 0 R /XYZ 72 125.224 null] +>> endobj +650 0 obj << +/Font << /F46 237 0 R /F59 309 0 R /F47 238 0 R /F14 318 0 R /F73 498 0 R /F43 499 0 R /F13 312 0 R /F76 529 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +659 0 obj << +/Length 1894 +/Filter /FlateDecode +>> +stream +xÚíZKoÛF¾ëWðHÑfßC‰S Z u¢@’”DÙh:!)§iàÿÞYîR⪫Wã |à’ÜyìÎÇٙψŠè:Âör1Âvh¯3ÂÏòÔ.ÓEZމŽÓb–Žß]½:Ò·èÍ„QlHLU íÇ«ÑÇ!ŽˆsW Cu4»½y‡£9<eõ}jfÝF\j¸æÑ¯£_F8ؾf„ÙØ¡‘ë °ã ÁÇYQÃj©†íhœ +œ!T!AH#Ï@~À#ŠŒ6+Ÿþéa‰Ð‘{Øù›\!w +›#Î6¬Þމˆ—ya)Çú$†%¨0*4œŒ ‰ïÿt»ý <žp!›€/OÏUµL †EN4O‹'nRhF#IL;iYTÙu‘ÎÙXÅ7Ié¤ûk)ð sÒJ½Å˜õØW€&Öι^ÔSû¥ä}NPÞ욟z?¦<¾Ëæ=vÁ[MÍvi;§*Çdz-K×ÊœÒêjµó´ªûÖIcE‚1dÕ™=aŒÂ¾ÈhûøqRç6îÔ»É"‰ŒbÚk‡¼1¨tsÿp³­i©@÷z–niÒÕ½6|Rw¥»‡œVgòÏîn꯳»¢ª“¢FV=x'‘`OˆB’z ¾¸K+˜¬$@.bÀmA§´q[ »-Û"tlnÃ=¸=&që9<˜ºËîræ}út“–iÇK¸󎀈“Õû²L>W“Îܤ¬ +tTYqݤxX¡iî§§yz›6©RÙOÖ]·ï “H‡m O˜V°Togšº`q*¢Ú…—XV©÷qÑnáå³—/¤ª¸L§öZfíBVð!)ë,ÉÝͧ2«S'±X³:”4^èøÜß»‰eúq™•*þP¦“Y’Ï–y²žr·¶”ÑIgó” D8i4áiˆÃ•M¿4;Ýd…^÷ô ¹§6?å6g-¬¨ƒ ¿œ}Áøá‰³c²ƒ˜¶·ÙåBÔ×SNE;eCéŒ)Þ®gœ—þÍOiáÛPt—-Û¬7k?àªö¯¯H’¼ÍðpSß¹+£ÏQX4Ç™­EšÁåÅfIíÁ®•3xÙÄ´)tª E½¹Ûão•ñŸýöûFmÔ-G6’è„3åy÷ ~m³wR&·imë-÷{Ño`óíf1å Ô~t°˜R ÊVçù)å1&âÆ ! :˜íß)) ê'0è˜!Âùª.è©cX‡ "M„B†QÀïuí‹åæ[ï9{š Ùœ:uÚ$¨~ÞÎÁ¢‡Áµÿª‚hZq6,>ˆ†#å4”˜‡jOàFʬ«´|;³Ú ‡®Õ×wPÀ¦åf '6ò>ÊM~àÒ=7Úø·©½òñÉßJy0 ábïå…qqŒÅá¸8NÞáBq¤ÅÑI¶†\ih|ÔªŠfpìnGÆAvûѵۋŒÕá6Oꤋ)â“æ‰}†¤%ZÃá8y ”Çá jwCJ„5 û›~0fµ ]«½h°®dE[;~T콺0¬ N‡Å‡a±¿|ÑÓCò@ÿéS˜âm]W/Ëb§’ºd… Ô¡ÚPêıÏÕIU=ñ‰¸¾i#¸°|@’¹óf¸äƒÖRAsÝ Lw9(æ9¨Uû¾ˆb $¡¯‚õé#‰(@§*¢‡©(V)9‰UûMÐèv& +¢iàÃ9…]ÈD ¶gën4Ç]rç‘i¨¤×8‚Lý÷Æwæ¢Nîݘâ;óRñþfy)ŸjJØÆu!˜gEÚUVVpb|g°¾3X߬ÿ'ƒ5XP`¦M`¢¿…D…A„^ö)ßt”çiØI($Ør$Úþ}ˆB:Ðho3}T +iÿU…Ñqeøáh8NÞ¡ÊaÉÌqh඘†Q¶ÿ£ÜŠ…ÃLöc¡kòëHþ¾­>–•·A ?wé-«Õ´ù¢öÞ› ÎÔQâO°p"î‰B^ÖŠîÆ=h¸U]ÃJ>í¿ª0  n›Ýƒqœ¼C´ †Ñ“°O”0$Ú“z}:Ðj?ºV¿ öiÿÕ…aqÅØá°Ø_~‡Ÿi&¬Këð½i¢0ÂÃÿdÛ•Ö ü¦uNaÕÑ:Ñ¥uNa×Ó:á¬ÈêMZg€‰Óý™Ìì1™–Õ¯ú¸HLîLvP xÖ:$;^Â6AÛ˜ý•öÔö,¬<m]º½e&ÊJvi™U/—0D–4¹¨é¡-|¸n¯â¬-†š¾–¯<‡áºëÓxÝ@º1mÇ®ëÓ4^¿sÝ#Û)zHgLñv=¾{=Þ3ï¡ïÃçînêm)f:ŠÙ›õ0§Ô!†~g I +IMvþ¥Wó7 šÅh +endstream +endobj +658 0 obj << +/Type /Page +/Contents 659 0 R +/Resources 657 0 R +/MediaBox [0 0 612 792] +/Parent 663 0 R +/Annots [ 656 0 R ] +>> endobj +656 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [71.004 549.72 111.003 560.599] +/Subtype /Link +/A << /S /GoTo /D (requires__requires000021) >> +>> endobj +660 0 obj << +/D [658 0 R /XYZ 72 686.127 null] +>> endobj +661 0 obj << +/D [658 0 R /XYZ 72 523.866 null] +>> endobj +385 0 obj << +/D [658 0 R /XYZ 72 398.222 null] +>> endobj +202 0 obj << +/D [658 0 R /XYZ 72 383.652 null] +>> endobj +662 0 obj << +/D [658 0 R /XYZ 72 271.302 null] +>> endobj +370 0 obj << +/D [658 0 R /XYZ 72 201.636 null] +>> endobj +206 0 obj << +/D [658 0 R /XYZ 72 187.437 null] +>> endobj +657 0 obj << +/Font << /F46 237 0 R /F59 309 0 R /F76 529 0 R /F14 318 0 R /F47 238 0 R /F13 312 0 R /F73 498 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +667 0 obj << +/Length 1543 +/Filter /FlateDecode +>> +stream +xÚ½YKoÛF¾ëWðHÑvßC Z u|KR€’V6™rH*Fø¿göA‰T(%¢ÜB‡åcwæÛ™oçAáä.ÁÉõ#ÌS FLI.a”Bk’TðúÀ«›ëÉëÛÉoWðÈ #©Ln—‰¢‰Ô)“ÛEò!ˆeS*pÚ|}´5º7WÅʆ«»´UFtj˹Í>ݾà³%\hx ï‚~ª{BßÜN>O\ℬª“ùÃäÃ'œ,àù['ÖèäÉÏzH¸Ô0®’÷“vض©p—nˆÖ¦k ‚0扔-ò.£<Í«üÁ6nç$­ûÛ>ªbÿíûÂÛþØ~” l»§—\ˆ1‰ä 0Ã0› #Dá §XÇp„S¤ˆRˆ€ƒ½áæÞN½*ÅX\u5 +…0\öT^¬ËºÉË&pµ(7 ú…õŒò0ú¶wbäx×µkcÍzÓüÄ'é{€¹ã~†O_ÿÓDˆŒÛhLá'²)ÁØñÙ›jpÏ€o¨B‚¿\󣤦Èh³…ô#Â0=_ì¼P GÃÑ{ •#ÎúJ2"ÒÍ ¥@ëÑ+5ÌW=½umƒ™?b³)Ò[`ÀÑéæN0ˆl3×Ê–¯Â¤¾LÛ9›².îJ»òç™Jïó*,‚ ¾[är"'íª³õ +HÄÚ9îÄf§«! ”ƒ½¶)ö‹Khëb1 ÀjjNÑ[WÅéüÀε2/©ukÇ…­›¡}ÄøNŽ ½L½¦ŒÁÑÿMÁ< häW]_9¯Óˆ’%ÅtULÂ$‘(ÿ†Y=©i©@ön–ö@|@ûâ Gi]…û‡Íª)W_ÃÝ,Žó˜Ä|àti`ô”( R”y¹¶5LV2ÍÝ ŽÀqJ=ly¶ °e6èèÁ†{€‘´Efaø= ÓÓ½­l% 墳@@UÕ¾¯ªük½7é"L*ꞌº(ï|‚€W@jWqº]Ùë#¤r6Œ‡íÂ$ä8ùã ƒ²)Ó +¶õÌlp§2$o…¬N}m#Æek›?þ¼”îR¥•¹#´)Úl ð˜WM‘¯ÂÍSU46¬XnÊySK< +^Åû0±²Ÿ7Eø¡ÒÇÊNçùj¾Yå»)ëeϤŒN;ÆS€àá¼}àÝã7ˆû;›åqk4 ²É–½áé +O}Aá\qÑÒŠºÐôÛÅ7ŒŸ_MpMv×€Óö!·]ðúnêò9ˆh§ì‰"kŠËYâç€ò9¾ùË–A°sÅÀ¶ëjÞà:Öš³X³ä«6À»jFF_£½¦Áå1×ù‹›ëý¶ º|®UPxã}êÛ®áîcµÜå=ÝFÂ÷ïßpDöšµn²F§P^ÍõÐ\põ?´Aœ»‚V®ÄÎ\ï‹iUæì¼b,†½,l[¬¤Gꬤ»:ÀwMìÝýaH>>Dú´ÓXI zøûD>Vå§oªïKhH4ߟ¹>pÁ%[m^¤±âP8@”ý•Æj¤Úa:tÕ¾[Ck«}/N}ˆï¦›:Z´Ñ½Ž,‰ñß­Štº8ÆŒ“÷×÷,,?^î'ÆYË/°@ŒÉ³c„ûF 2”nËh¦Ž|1©x˜]ÅƒÌØæ·EÞä]~H‘¾h¤8yW}‡ÂrrƘ3×{F0ãR-=“pTÁÌH$¤é·8ƒt©u=­ƒtpPв­ÿ{Zœ¾»ž[Ýr¥ÙhZŒXâ÷eý½¦­íšMUþRY²ÂjQ÷É<`ƒu^ׯb$nî[.Ý'¼g æ#®ó•Ô}tHSf5¬óo€ÿö´û;€êö︺±ËL¥Ðçíÿ°‡<Ô³†Å|ti]ëVÚ˜F\JYäU$ÉS±hk— õ zOå3¨qÛzpCÁ_Ú,Ð~s¹´õ¼*=—‚·óU` Þ¥.`‚HNýã;Xú×4 +endstream +endobj +666 0 obj << +/Type /Page +/Contents 667 0 R +/Resources 665 0 R +/MediaBox [0 0 612 792] +/Parent 663 0 R +/Annots [ 664 0 R ] +>> endobj +664 0 obj << +/Type /Annot +/Border[0 0 0]/H/I/C[1 0 0] +/Rect [71.004 480.205 111.003 491.084] +/Subtype /Link +/A << /S /GoTo /D (requires__requires000020) >> +>> endobj +668 0 obj << +/D [666 0 R /XYZ 72 686.127 null] +>> endobj +669 0 obj << +/D [666 0 R /XYZ 72 667.868 null] +>> endobj +369 0 obj << +/D [666 0 R /XYZ 72 620.844 null] +>> endobj +210 0 obj << +/D [666 0 R /XYZ 72 606.274 null] +>> endobj +670 0 obj << +/D [666 0 R /XYZ 72 454.352 null] +>> endobj +480 0 obj << +/D [666 0 R /XYZ 72 328.708 null] +>> endobj +214 0 obj << +/D [666 0 R /XYZ 72 322.979 null] +>> endobj +218 0 obj << +/D [666 0 R /XYZ 72 256.871 null] +>> endobj +665 0 obj << +/Font << /F46 237 0 R /F59 309 0 R /F73 498 0 R /F47 238 0 R /F76 529 0 R /F14 318 0 R /F13 312 0 R >> +/ProcSet [ /PDF /Text ] +>> endobj +672 0 obj +[228 273 228 228 456 456 456 456 456 456 456 456 456 456 273 273 479 479 479 501 800 592 592 592 592 547 501 638 592 228 456 592 501 683 592 638 547 638 592 547 501 592 547 774 547 547 501 273 228 273 479 456 228 456 501 456 501 456 273 501 501 228 228 456 228 729 501 501 501 501 319 456 273 501 456 638] +endobj +673 0 obj +[833.3] +endobj +674 0 obj +[500 500 167 333 556 278 333 333 0 333 675 0 556 389 333 278 0 0 0 0 0 0 0 0 0 0 0 0 333 214 250 333 420 500 500 833 778 333 333 333 500 675 250 333 250 278 500 500 500 500 500 500 500 500 500 500 333 333 675 675 675 500 920 611 611 667 722 611 611 722 722 333 444 667 556 833 667 722 611 722 611 500 556 722 611 833 611 556 556 389 278 389 422 500 333 500 500 444 500 444 278 500 500 278 278 444 278 722 500 500 500 500 389 389 278 500 444 667 444 444 389] +endobj +675 0 obj +[277.8 777.8 500 777.8 500 777.8 777.8 777.8 777.8 777.8 777.8 777.8 1000 500 500 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 1000 1000 777.8 777.8 1000 1000 500 500 1000 1000 1000 777.8 1000 1000 611.1 611.1 1000 1000 1000 777.8 275 1000 666.7 666.7 888.9 888.9 0 0 555.6 555.6 666.7 500 722.2 722.2 777.8 777.8 611.1 798.5 656.8 526.5 771.4 527.8 718.7 594.9 844.5 544.5 677.8 762 689.7 1200.9 820.5 796.1 695.6 816.7 847.5 605.6 544.6 625.8 612.8 987.8 713.3 668.3 724.7 666.7 666.7 666.7 666.7 666.7 611.1 611.1 444.4 444.4 444.4 444.4 500 500 388.9 388.9 277.8] +endobj +676 0 obj +[1444.5] +endobj +677 0 obj +[339.3 892.9 585.3 892.9 585.3 610.1 859.1 863.2 819.4 934.1 838.7 724.5 889.4 935.6 506.3 632 959.9 783.7 1089.4 904.9 868.9 727.3 899.7 860.6 701.5 674.8 778.2 674.6 1074.4 936.9 671.5 778.4 462.3 462.3 462.3 1138.9 1138.9 478.2 619.7 502.4 510.5 594.7 542 557.1 557.3 668.8 404.2 472.7 607.3] +endobj +678 0 obj +[777.8 277.8 333.3 277.8 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8] +endobj +679 0 obj +[569.5 569.5 569.5 569.5 569.5 569.5 569.5 569.5 569.5 323.4 323.4 323.4 877] +endobj +680 0 obj +[777.8 500 530.9 750 758.5 714.7 827.9 738.2 643.1 786.3 831.3 439.6 554.5 849.3 680.6 970.1 803.5 762.8 642 790.6 759.3 613.2 584.4 682.8 583.3 944.4 828.5 580.6 682.6 388.9 388.9 388.9 1000 1000 416.7 528.6 429.2 432.8 520.5 465.6 489.6 477 576.2 344.5 411.8 520.6 298.4 878 600.2 484.7 503.1 446.4 451.2 468.8 361.1 572.5 484.7 715.9 571.5] +endobj +681 0 obj +[769.8] +endobj +682 0 obj +[273 273 319 479 228 273 228 228 456 456 456 456 456 456 456 456 456 456 273 273 479 479 479 501 800 592 592 592 592 547 501 638 592 228 456 592 501 683 592 638 547 638 592 547 501 592 547 774 547 547 501 273 228 273 479 456 228 456 501 456 501 456 273 501 501 228 228 456 228 729 501 501 501 501 319 456 273 501 456 638 456 456] +endobj +683 0 obj +[556 556 556 556 556 556 556 556 556 278 278 584 584 584 556 1015 667 667 722 722 667 611 778 722 278 500 667 556 833 722 778 667 778 722 667 611 722 667 944 667 667] +endobj +684 0 obj +[600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600 600] +endobj +685 0 obj +[556 556 167 333 611 278 333 333 0 333 564 0 611 444 333 278 0 0 0 0 0 0 0 0 0 0 0 0 333 180 250 333 408 500 500 833 778 333 333 333 500 564 250 333 250 278 500 500 500 500 500 500 500 500 500 500 278 278 564 564 564 444 921 722 667 667 722 611 556 722 722 333 389 722 611 889 722 722 556 722 667 556 611 722 722 944 722 722 611 333 278 333 469 500 333 444 500 444 500 444 333 500 500 278 278 500 278 778 500 500 500 500 333 389 278 500 500 722 500 500 444 480 200 480 541 0 0 0 333 500 444 1000 500 500 333 1000 556 333 889 0 0 0 0 0 0 444 444 350 500 1000 333 980 389 333 722 0 0 722 0 333 500 500 500 500 200 500 333 760 276 500 564 333 760] +endobj +686 0 obj +[250 278 500 500 500 500 500 500 500 500 500 500 333 333 570 570 570 500 930 722 667 722 722 667 611 778 778 389 500 778 667 944 722 778 611 778 722 556 667 722 722 1000 722 722 667 333 278 333 581 500 333 500 556 444 556 444 333 500 556 278 333 556 278 833 556 500 556 556 444 389 333 556 500 722 500 500] +endobj +687 0 obj +[278 333 278 278 556 556 556 556 556 556 556 556 556 556 333 333 584 584 584 611 975 722 722 722 722 667 611 778 722 278 556 722 611 833 722 778 667 778 722 667 611 722 667 944 667 667 611 333 278 333 584 556 278 556 611 556 611 556 333 611 611 278 278 556 278 889 611 611 611 611 389] +endobj +688 0 obj +[333 333 389 584 278 333 278 278 556 556 556 556 556 556 556 556 556 556 333 333 584 584 584 611 975 722 722 722 722 667 611 778 722 278 556 722 611 833 722 778 667 778 722 667 611 722 667 944 667 667 611 333 278 333 584 556 278 556 611 556 611 556 333 611 611 278 278 556 278 889 611 611 611 611 389 556 333 611 556 778 556 556 500 389 280 389 584 0 0 0 278 556 500 1000 556 556 333 1000 667 333 1000 0 0 0 0 0 0 500 500 350 556 1000 333 1000 556 333 944 0 0 667 0 333 556 556 556 556 280 556 333 737 370 556 584 333 737] +endobj +689 0 obj << +/Length1 757 +/Length2 1108 +/Length3 0 +/Length 1645 +/Filter /FlateDecode +>> +stream +xÚ­’iTWÇ¥‚…àEñ"1bYªPÃö°)R[CfBF“™ K¡ +ZD°PR* †‚ UTR¡ÄQT”Vƒq­ ²iT¡Öö”~í™/sïý¿{eX¤-Ââ`†â¶4;š;ðñ¡9šƒÉÚÚ[sqC}¸8ìhnnt˜(tG@§¹Óéî W’5ðÆÄ2 /ÀÕ{Õ”È0E°áqQÂŰˆèÁã +A$ÆC`\f˜B!ˆ˜:!°–$Á‰FÂÃA $û)¤”—wi(Qü¾”K¤ NQ®#„¡B€`>ÉžÃ`åÿ šÙœ•(²¹¢©öÓ>ý§Î!BÙ_ +L$NÄa Á X‚ΔFÃïàB`Iͬà\!Âc¢ñB8¼K!R’CaÎ>W(…§ó0 +Í„ œ›F°ç„Fú®þk§ÓÅ0.‚âëeâ¿ÛN©§cÚ?1áI±„¿4BH|ïÿ6Îæ‹ò0AãÝÉp%®ŒD¼"r©4€ œà‚ØÞÅpâ LÙø˜„4µQWW`/M‰¦_„HÅB®lJAú¼°”T[:ØÒÝœ‰ 'pq¡oû—’—(‘À(>ýbgÞÇ|„ð†S`é—›oMÖæ’SÙÊt_EWžŽW|C»¾åúO†™½…:ÂªŽ ›¾ã1ãµ¥&óô–%¿1—înJ ïd½ØžP ï™HÚ4PºõGó˜‘ÒY¿xùï™O4žº1öÌI'ôZß%e§ò\ÙÐù§è>ë}xÇrVklÒ‰Öﲜ]bX¥Â 9;S-#Œä Ê\FŽ&Ù¨hŸ®æjfúæ}õêÛÃXSâGã +ý_O|öRÝq¾ºùd×ò¤~ãÉ£6÷ÌŒú>ÄVЖu¥©Ú¬F7åfX4×TïË¥s²ßþP{·=?hÝ#ù.ËžðgúñO;|Z¢¢‡îz¦:è~?zÏ1É™hò}½«ýލ¥.:½à½®/ýG2¨Ã­Ž'²–7ßÈv;ÔÀÖydt?ðÛQ?í˜[ð[u2 ݥˎxÒ̉½-•å­®]Àg/M#{,Þu6cö=2¯çñ]Ýq•Ÿ“ÅŽ­,P‰| EvãÕUÕujeÊZ«Ï[ŸXFQÌ÷ÖÓv$øöÑbÑÖúÞS©ŽV¿sŸŒ±j´ Þ2ÇÖœº,ŒÙ% Uëe&õ¾8ÍÉ RÐòb/Fel×rÌ[ºWrlL2Fu¸³ÌÔ*ÖÔ¿ÉÀ"7ß'Gö[]>èï¿rÉCUÛž¼¦½õTMO=óh)_‡J>íXò•Üß÷ælL׃¦·™óÓ ~¸-ߺ…×Àr}Saù}žÀ¯œ¼sy”øÖ~M¿Ê0ù¥²¨CløÅ‚á×ç=ßj­¶; –63ù1-?©-n!¹FQÜù‚ ]¸Ô‘üÁ””|{år{ÍFë(%ø:ÉsGqnþgæ4·NŸýtp°sr«ßá|¤7¸<šbÚªBA_Ì›÷x}·"°ovŽÀ`EoOƒç».÷$ípô†Æ·ÏŒ¯P[/™mìó¥†bÐ>ÿ›îÚì%û8x¾üUÂRö +2¥¼gÙ(•Á‚Ü_ï¹oj|Û~£guú#Ƶæ›V¯¥Y†{ê,>^KákBº[Û]C 6§ÖtŽ1IGU•<Œì-ç2æ¹›¼Z4é 5­8´2»Ýõç5G·PW¼Ç“ ®ùÚo¡ÝÀε.çZ­Ÿ+óˆz*¸öÓ\’wD°Ç­>²ƒxµl¶mùÑ„(*^g´¾?('A÷à6ú^Å©áT¿¯½ÆÎá‘·dý…tõîÊx1sÛ¹W—#5Èγa+lM›­CìF´Úžˆ£ WFf3Ï  ·èÓûåríܕ姱ŵo–åë™ )û«'oOιé·V&7xùëÕZ1Ë"_ÿØÏׯ“]Z>óêÞz©µH]6gÍ~ûžS”cÎwŸtŠÃMc.n­BÖ*†§å1öoŽmh+63¬Úaר&¯¼_Š<0-½hÂ.{9+•þøjåÙ¨ÓÃú1¥09dLílTi~uâ¾qõxÐøóð’¶g*bqüîtäOø& +endstream +endobj +690 0 obj << +/Type /FontDescriptor +/FontName /YQJSDJ+CMEX10 +/Flags 4 +/FontBBox [-24 -2960 1454 772] +/Ascent 40 +/CapHeight 0 +/Descent -600 +/ItalicAngle 0 +/StemV 47 +/XHeight 431 +/CharSet (/summationdisplay) +/FontFile 689 0 R +>> endobj +691 0 obj << +/Length1 811 +/Length2 1849 +/Length3 0 +/Length 2409 +/Filter /FlateDecode +>> +stream +xÚ­R{<ÓûWêȪS.…„ïÊrkls¹Ì-Ãrg¹fûŽeûN³isK’£”$&9,¤r)NÊ¥”tEIYr íI.©3:óúuþý½>ÿ|ÞÏó~žçýz?îî…ÄQ˜¡ #b#ÑúhsÀŽ@À£Q€äBÁ;HbÓ˜=‰ šh,ÖpæÐŒ!€2576476…!;f$E gÚv:‹$SÇY42 $v8Èô “耓LÙ<}G§ž‹Q€'²¢AŠ> (42ÃhÌ`Q¢2Óoa +'ò{*dEIDÚK2u‰H +¢ó +H…ìbJ¦-ÿY?6wäÐé»HŒÅöKNý'ObÐ輿LF$‡ ²“² ©~à7qBã0~ÌâÙ$:ŒƒÂè €D飌¾ÅiQŽ4.Hq§±Éá•D—â DùQ‰Ä¿%v¾;]<|ôþ^íRÒDƒØÞ¼H@ýË^Âè±Ä$  ôQ(´„(yßA? s€ÈL + +0Æ&‰Å"ñ`’#’ c  Ð +È@®D±>ÄdKJ‰3ñ•É‚-îÕÄ 0°_ -!3`àþ’¬Í€ô2Áa‹G)±õ{ ‘p—à-°µerc‘†‰1–HB™¦Æ¨øÿ!’9,±—ÎLbäwL¥I¼A.H†‰:™d‹ä=95)¥ Åíe+u¢6çžOn½yèJ®…þH¯…ü3VícoP}RîÜZùzþ˜ËE +Õ¸_¥'Œõ28Ô%'\«¨SxÚKfœ<øËòfÁýÛëù‡Å"¡ÈZ½ñ[?öEß\YéúmZ¤2vdEéóÎ… ûÛúE«OQ¶óaA‚ë®Ù ïŸ}çFw2‹™¢’f¥ÀÓ¾ˆTn÷tD¼\›‹M¤ÿȵü,‹ÒáRÚ`è¼ ±ëìe¾j³É3ß3¹€Ô&Kx.Ѫ¾Î…ðnÕàì )žïä‡÷™V-+”'—ªÒ-w–¨,«nû72¬ ¦_‡ª<’ä#ªÚ1–YèÈÚl„gÈìbRóØŠ© ùùÞO_ÓTÇɱp)åKËýôÌò¬£µõFtZQ*+Ÿ¦ +á»Iá'ÅlœµSïj›´ûŒGÖqõ3€ˆý#Q±óBêVöÆ|–‘sf;Á_ïr03Ð+…Ý}Ú1PôþíÝÆ´<Ì/Žv½! ÞÏõš+®Þ*¶W¨øuE°ÎѱX³n³kÐV n¥°ÙbÃz\à7ž.jêàfŒ†ßˆ“7ž›U+77Éïøl1ü˜ï#¬;o¢–°rø jDºþ¨·n¬Ù;é›.!¼v³ŠjaËF­ŠwÒ#'¢¼Ô¥4…Á›ÀÊf—a«Þ£¥ÏÄݘÂÕÝ£ +X@¥¶Ëþº:÷Á*&Øë3Üç‹BôY»­oC,hèÒll4¦Á-ØØ"0ìK‡Õyϳ%±Ç÷O<7R; 3_=Ð5ˆU‰tˆá'|MžîÚÉY-çP× ‚Äe¹=-ý4ìàÁgå8[-‰·Y5ªTÞz5cãÄÈQ½cQôÝzG– Ì!(õEŒ +EEq¨Ù–¦-Rîà§”!a}dZŠ#qn¡º˜ïk0ÔesÅÎv)2‡¼¶ákèºRË{VÌ|à+}dÈêdzõL:Åúe¡»ÿtáœeß“9N¢Âƒ±#mÝ× TÂׯì%*koÓÂOÝE{„înmròùÇ£küZ&§üáŠfoš, ++ù¨)-í‘Ô~ãàâé{ÓR¶P«µœlWT(SIÜ‹ýüä$ç\IÞ3#M÷;NóøM —à•ˆÐÆ¹âОÝ6õ¯ì•/xÿ>}½-ÛL™=/ëˆÁtØÌ{´LÌT~±½£7[)FSÄ,í}Ãò2y”ú ýÆ’y™Á‡ðÄœÊÓ fÕY¾ ª/Ö= ×çœÂõæ']².­ÜJÝ…¯büêsšN1Yac÷Τš?ÜÑÐáh½ÏÎã-èºe8¹nreÞeXÞ†××Â]Òb›60ðöìö˞Ĥ‘@í¬¨¬ñ)®>¯_À¸ãÀø© Õy̯^·a]’Ik 9y€£×@Êý“²î‘De,Ìþà¦Ý2¸ *ÍÄvûùܺèxA÷,'X vÖv®numt—i§f×;¯uíî¸&J3)] î¤EŒÏ›-]Eê]QÛûJ£`Á‰-ƒ÷rÈS¤Š’³E¿™%´ÿ|°§›S2\)Ää7-gY¿€ +o¿küN8°½a‡ê‰í£ÒÏ’ÖM]vT—â§š¤¨µ)ÐY ÕxÛ¹-•>猲Æ+8·U'⛟Œ¼–&Nßù(HH̉Òxœ¸1ób©1o c>óTµVjà®ÌÄp·ÝárN¯lõò[rëÏoqïk·jŸ|5ª*'[ôˆ»ÈýŠ=¡owÃÚ¨nÈî³Ïz.LF?:>¢!Ð#K)®Û(Ÿáþ!Û'x„ès=\ðZðw“$£½>Æ2*1üKmỦIÓ»”aÖ–­üÐ*Êzybø€ùç›WCÙY™Ó†;j½ë.Àw£6[CçYáîJâÇN¤7ïñ3RO›‘— ô¾>™×q:¯¡tÖ:€n4è?<µª&’ÞQ÷@ípÍKÍçoeôw!Tïï¿6p5vHµ;É݇žÞ‚²<1̉¿bÑúUV®ü“Æê˜2…NM=¾Úó7Ôl¤ð’øèEôÌÓQrF6®ØûÏtgu>½¯RÑžù~,&¡¯‡[ç§p.ݪÖmSf¯ï*y?Äb&芟²Ö‰©ÎRh¾®b® º»wa¦¸šÓ­úå§>x8Ø­út4tm¿ ù÷l|Kú4Ñí±áÛÂÑG;m›/ÏÊI5°E=FWc¡üš-w&*ø½²š>ç{© zð’™ +endstream +endobj +692 0 obj << +/Type /FontDescriptor +/FontName /CVGKQU+CMMI10 +/Flags 4 +/FontBBox [-32 -250 1048 750] +/Ascent 694 +/CapHeight 683 +/Descent -194 +/ItalicAngle -14 +/StemV 72 +/XHeight 431 +/CharSet (/D/P/a/greater/x) +/FontFile 691 0 R +>> endobj +693 0 obj << +/Length1 792 +/Length2 1655 +/Length3 0 +/Length 2206 +/Filter /FlateDecode +>> +stream +xÚ­’y ]<ƒL¢D&9HÀœFœWvøΠÈ)Hy  @dà zC yÔ +’ Ë }/SüY?Z ÛO è¬b"1$…É ÐKåÀŸŠYþX?·ò§ÑHô•ñ+Aý£M¢C´Àÿ˜t–?d&d3~¶º‚ßÙ ò§ÿܵáhÙœáM=Œ!mø½ùYA\âqÈ>€‰æ®ÖAågq|«(K+7¼­åîï»Ús$A Α@ ÿ2¯jÌ_Zâh$ÅÏÕ‰ŸÎ²d™ˆá ècq‰Í&ʣţô±X @ +È@®…d09â-€8˜PÀ‹É–_¹U¬1€"3étÒJyµ‚Acô7‰PÔ¿I#å»*ÿùÍLn0ÐÓÇŠ0FÀ‹ýٟ͜՟JœÛ퉣A.H–ï2ɦÔ´ª¨â0ËÜŽ2?õŒÂˆ¶ÚÈŠ SääKS¥çìê§GÀá‘p*T¢˜:ewEñ©V™‡4Q‘/àͰ͈k™D¹iòäñ“’-9MõéÙ±£½¿¼aUïžîÓ ÔÊܶÇ]W:/]Ü#\œ ó=ód¨W!¢9’*"çž} +xtlðÒã¯ï1s™½ù-[gŠ6-õªÖtúöÃ2ŒãrR=ƃJúyBM“¬ÛÏi°k]*²”av¿æ¦u/èpãKþz'>³XT%-Q½]\ÆíT°;O?#µæ)ä]ÎB´n;~%æÒ£<þé1Ÿ¾ˆ˜ÒƒØ·•í†1ãÒÝ­\'BØ!ßù´íæId¥ÖpB c  ¨ l1ÿ©¬ÔDNþscÓÉ; 5žºg¹`éõ×oM<Ϊ«ëðÏŠ$%+Á¤Ù9Þl`šTîîë’€úñ°_lô´‹ÆsÌ’ƒm¡Ã`²fÔËÄ­3µÏ•Œü»…ÑÑù’Öät÷¹ðRàw|Z ½èp¹†4–„¦ÊDPnÆšÖàì{ÝQvȱÆXaf†è×àßt|×”ÛdБtlìØˆŠû‘·4ëâ)uÇÏ øÁR|ãhò¦ƒíKxíÌŽ[B’ubs?.Ÿ¥¡æË'mÖvËqo¸=] lÛ|,H¶8y*bó½±; ÎóšÈ< Ò×…œÎ:J„üy„;™n? ! »Õûè¼a?¿Åü7Q{ôVNÓÚÎ8öÚéψ˜¸Í{F/;då3¥Ÿ™Ä–ÿaë—§#>bõëæù¤îªíÂ÷Úè—/©ÊieYZ 2»¶5ÎÙçDüöĉlW`½Àš;Ö +«³¨V]x6ˆ*ÿ:ëYãî&t§/º™})Ì´HмtµÒ8~’û©²(;³3ën«‹­<$§™¾<evÀQÃÔYŒsÙ8/$§ã;jó4bç=^ŒÝ^l~¨„è23UºtÀ>ðrü…˜´è'MYLÝ·fªß¬ –ÞÖ¸nµ>M½gïâù„Û0)(ò™‹ÒTzƒçt,¦NEJ¿L†Á[àòï +3»“¾ùJD¶½9m·È¼ÚrñÁ`áËÈ¢Ê#ÜÈÉóü¥GþÞDƼ&’}ªu rFÿ zUFÔ™ìß–ÿÎ".^Ã^øíàÕÚcjZÒª¶s5„“²c ØÑç6>O_äæü8ùpq!vVõßëy€…[çÍû#[à&í°’Q²¢Jâ5_‰Eµ¨ð}0eäðU†X¤ÞÕ ©¤œœôWðÈýc–PË+JÌ«ôÞf”yÊúÓž)«a¥'Åüô¸‹kv:ð 6õœ+é<̪T¼]·)ÁXm§õF¥pª +ˆÑïÏ>j1œéq¨ÇKVw×ïs»^h•§4j»¾D¦cK“ñ$—W]!NääV"ö±áµ7jûÆÌæâz`ÖrÍ:×5%_–L`f2c³Ô¸AŽâ«%AÂheù¶M5&"ʶ¾å68š¤ùåµwåò9O ¥\ý¯Ãùwڴܷ܃—®³cÌ4¤’tŠ&²¦7E‘¶ðê¶[4É]¹[”èîZ’´SÆfK{ϵ½ŸâÒ›…Ê'KÑzÙ¸=ѡݟ Ñ«ëq8O\Ï{]׈r5„§Ìg˜¼ÊÚú™Ú§€¼8KA4ëü0|.CV£‚H|°ñ«Qxô,¥8°ýÑùüJ[ëÀ[aWÛͲ†<_Çg· )æ…o-;¾šÈöíƒòn…¹,sÖʲúžË[iL„o¶W„¶•‰³p5q +¡ãAQ§Î-ÈÔ£©zï‘"¦YŠžŸ`šÎ ÍNU²£·æ¦o‡×¡ -3Î(z¤ïûQ™$B‘tOÝ®ÊÇŸû§7-Qˆ+ìXŠ›²•°›²HñÍo|ày7=Òc x(±!¯ëTQ]èÉîß½®¸ëîÎIËnu™í² lÎÞÿ|ïèãSY8ß5—z¸Û1˜®–ö…¬8†@/úïàVçí˜/1©NÉ6YC2ô©û¦Ýdÿêuý:½Ò–ÚþˆòÌÅ’³ÒCG«Ë+ÉÞÓÌ´úxÚ„©ndW¦eŠÍT‚½áûአk-‘¹Ì» +å±$þ(UåL¿;¼;4Q0Hãù–æöÁD§2,ÿçKg +endstream +endobj +694 0 obj << +/Type /FontDescriptor +/FontName /EFXCJE+CMMI7 +/Flags 4 +/FontBBox [0 -250 1171 750] +/Ascent 694 +/CapHeight 683 +/Descent -194 +/ItalicAngle -14 +/StemV 81 +/XHeight 431 +/CharSet (/comma/i/j/k) +/FontFile 693 0 R +>> endobj +695 0 obj << +/Length1 778 +/Length2 1256 +/Length3 0 +/Length 1801 +/Filter /FlateDecode +>> +stream +xÚ­S{8”ù§"g²Œ[ÄQ¿Y±.k.®¹l2ƒÖe\FE$;f^¼v¼ï˜‹ÆµU³Š\ÆåT¬”JkQÖôh*Ž.›]´"¹Œ³i1r* —NgŸcÿ=Ïû>ïóû~¾Ÿß÷ûy?ßßÏ”líÎF£ /XSˆg@£3(d@!’ÉTœ©)10Šx03 89Ù/( +[`¯³½³½ ÎÐPnމsšÅ*ɸÇC<˜ÅD)ˆ…â±,&£,$;‡«;ø€ñ!^"Ä&â(À†YÅÀŽ´*ɉFã˜-ä~L%B<>& +˜¯É´˜H6Šp’ŠÆ‘üQ¬„iùÈZ_ÜKÈáø3ãW˯õ§43æ$ý‡€Æs…ˆè(â!ë©!Ðmtˆ ã×g½LÌrGb8 €`¾,‚ذ€ ¢™>´†C{½̹5 $Ÿ>>Vfº– dˆ`_÷¿UWÉk1ås‡‹@8³—‚±çã*b]/O„…²a$ØØ;&ÇLÂa§‹ìA +ÀH„ &T€m˜'i åáVê@$(Aˆ ƒ×;'@BèØ¸! øóR©¨(ÅÚÆž°Ö™LvNNiÿÃd y<¬#Ì®q4Œ™ A"ˆ…{Ú‡²\2㊛³.§{V=¾¢b©L¹™ïÿÃÞÛ[ŽœQæÔtû&X7„.Ö‰u4d*²GFüo%©A¼f2òK~Y‘%~%'·…ΉéIÜOߟÒlmþyþ•½rÀ“á\.ÚÈ[ÏíB%Î2K=…¹?+ü…ìºj­†¿§†¾jb¢¬µÑR¼óªd÷î”d—•Ú€ßz–â÷…7H:*o-fo®«(ÜÏùyVmçLHY¬Ró3çúÌ-nw™ór]¨‚!Õn‡ú<–—Ôˆv׳“äBøÜ·_ùtÂ…K~âÂß• +¾[‚BæG„ø½õý äU•ò­ë±Zš%ŽErU]ï çáÂM6ÉËUM°]M“Å–uRÕ󆥊w ·çÏþø²\Þ’Úv¯§È;·§à¤¡>¾™ ¥ýfRsp0;D7E÷¥*ß|rláïi9 ™ù4eOõ‰ÞôK¥ñSX9¯®'D3bp~ Hª×HÛn`­.¿V°íˆMXï™I¢•N>×ÑLŠ/UR51øöJ×ëQÛ)S—¡“¸½kâ´v«Fíº¡'m¶ k[Ðð=Ü»·›º—Y)Šñ×ß4áN6ÙQî5ö~ÓO`U*E|í•3½µm>“6Ù5±Þ™³û³¿Þ°3?ÇQ^x:ïW0ÛE¯Ølþ¤%Ã5ت™êJÓ~ÉÌâùEÝ +ÚzC!}^·+Àé,ƒTÎé;›³—ûõàB¬e`Ctñ°†Ö;ÿû_- åÚá:¡¿¶ Eãç-úËó|žº¿81=Ïn)Úˆ{ÞïZÞ6'ý©è Ž_ºÈFM:m³:ºy`kEÈÆÈÄ_€œ2ó¹Hzø¯Ö¨Y\A6÷9gj¸¼ºkn¬Á`®:c‰ÜzÔ³»M§a,¤M‡ø¼4ÊÃÁÀd§pk” N,zLxŒ½6¤m[AœqÇoöëõ¢o­ï=â íÇtCeÝ?äÓ©y®²Y¢ëcƒI?UŒïDK¯Ð6oìzQ•o†ÝÇìÏ^yá%H×ͼ8¹)Õÿöì9 ¹ú´rZRœ_K¨²¢dÜåLzDŒé7yóωëïñ¼—ÔŽ^Ò:Ö1瑩go]Û¨â3³ÜÄ1|÷&æ/Oúz+hÆ„¾«í3‘ƇÞtŒ&6Þn|¶á{Õ™h뢓V‚…°¼Î† s¯÷ œÊ¿us8ç“R¦âËѵŒ2”ðöð5ù r«/(å¦A®ÒˆY4Þnè&“þÖ:dÖÞIÒ.| 1¿óoLFaØ +endstream +endobj +696 0 obj << +/Type /FontDescriptor +/FontName /JVDJDJ+CMR10 +/Flags 4 +/FontBBox [-251 -250 1009 969] +/Ascent 694 +/CapHeight 683 +/Descent -194 +/ItalicAngle 0 +/StemV 69 +/XHeight 431 +/CharSet (/equal/one/plus) +/FontFile 695 0 R +>> endobj +697 0 obj << +/Length1 822 +/Length2 1824 +/Length3 0 +/Length 2389 +/Filter /FlateDecode +>> +stream +xÚ­R{·‰Ï4ÄZŽòkZ.ÆššyØf3%ÄUí0Öp•Í +.JÄ%Œ„ȦŸ_?Òៀ¸i0< Ýæm^ÊC\¹°zlþfgƒp™Ù:û¶+ÂMžX Eʨ,ýäJHÍ•Lí_Ἲpl²_Zº,¨91Œ¨¦¬ÔnWþÜúÜÃád +λ7h}oŽ7h2B´ÓË=P½ Z~*1z!ze@VÿÍôêsš»ÿÒ6uüè­E¿ oaŒ ªâEÛuEå±3ÛöŒÉ]Ú«œK*nYr3a uûj¸ñ²'ÚŤ¬Fïåw´Ëut‰¥]ÛýN|*¶XsEÌ‹!NðKËP +ï›GzcãFÿð˜UðAú%4}ŠúSêUlrG¬Š{û&ÛÇw—£p>¤k´©?¹ÝɦÝ&ÂNµ´æ…øÖé%âSûÅÆûÇ¥}ü]bÚ„oñµäñS#tjÊÃÈIÒ¨Ù£ŽRÄ­Wç£_ú‡9Q¸˜!ÒiÌͺ^ôëäœ:Ù&² +±9W®G8)‡º›mUÝh)lÓÃ%½ªo†>®i´M7¨ÔÚõã;Í.Ï-L+°Ñ³ÞŸ[iP•-ïv]‘„Õd}¿êᨼ¥Yš{"©«2Â/öøIË+6LQ^1N÷Äk +´}ph»]*ßËSYbµîj,sjá:“)þFôïÈGpU>¥’%ù>“¿š‡-g®fÆ“‹Gg3ÌE¾'â‹¢ÔŽe;DH̹XjNB—}”‘)µ :ôßò÷dKçsÏ›öÈ„–ä3q2YNCß •D þµÄ'{ï1¼.1œ]Ñ4 ˜ÍIýÐSWµõ!ŸloáË“6–˜y=èaé/ti„ÞÓ5Öë3™ÈW[¯ß{ëŠgõGŸí”Èj'«îAc;í[ìôí/ÊÝëß5pŸ¾Ø”þâì‹•£ê憾”o¯´ISGÛO–ÂOu½àÜo~^Rb1Q1ÕÉ¥Ô=ì&é6¸#£S¦¨Qã ©ž£‹óù!Äëµl@Åû_Ú¤ +ïæÅjÏÑQDÑxÆß©K[ûêâê?zU87Ô÷„ù<äÖgÿpIÐXë¦#WY*5•È$_`ArK)ÔšIwçßQ:7TaW ð]•N+ª‡(ˆM]æøû«ÍGÔðr:ûG­kÊŒl9cH®,xàEZÞ»ð¡jåÏ-œò~‡Ó¤Áije¹íP|æëÈí¨­K)-¾gl]9¥øHʈ2NáÚT{ÌбHj㾂¤•VMØÒ:ÇÌñ©ýµWŒgN©òæöî`%ën¸¦^F n[ñÓK[IØø%¢§I²K·,ÄK”]Ÿñ~ñp> endobj +699 0 obj << +/Length1 798 +/Length2 859 +/Length3 0 +/Length 1406 +/Filter /FlateDecode +>> +stream +xÚ­’kPW†±U(AkG × õ$Y0PÀKC¸+á@Q—ì&,„ݰ٤ P ŠjQÔQDk­”ñ¤Å‚ +,,¶0 RµF¡]°ŽSüÛÙ?û}ï{¾óœ÷;ë@¡#!¢Q§!äøþˆ ‡agÇ'Q˜ÂÜ ¦Pw¹¹A€§ˆ 8®îNw®+Ã𠙚Ä$1XÃ_;gr¼x”ÄD0üa*§gˆ`)" ¥Ô,À“JAðÜ +9Få(©D‚‚‰(J0œÁž#òÃÅp}ÓF²·’%å4XCC®4"BàR5@P1ƒ- è½Pšäÿ€Z8ÜG!• +àø¹ñó)½§Ãñ˜Tý¯ƒˆ—)(”þ‚’øBë6ô œ?Š`Šø…ªK1—HQà­gqœ¹oLP$£D1@ Kåè|Å‘…(t|ó loÿpA—ý¿÷:/ÂN…¨e(à¼sÏ×лšN‰ÄT ’Ãâp ÚHoÿ¢læ‹Ã%À‰ë`’„Õ úÑ$AÃTPMÌfáE/t4 &HÆÜµ:6,§£Âäqô­Ä̉ó}ˆãØÑ0ù®Ø2ÚF "§ý(2¯¼pOOB•äèäÝ\hr®®\ÍŒ"IÒSæßßÛZŒÑ‘£¨ +1z{‘GZìɪýߦxu\XÂÖŸn®ø£WïFxuÊ Ñ¹ùAÖªøIá€öp=3®Ód‹È#×¼º*[µsü¼áEmfAiøÑ=Ü:Ö¯B¦úëÌËfíW?ñ«O;•—>`æ^Gž>hëÐ;n›Ú¼4öÜ^T;Ùßc°b]pÎ:S×Þr½¾EÆLußã»VcÕ©'›6ŠžÝ¹¿Õ/)÷É\Ý)Þd=¿bD‰•öAx7»‡¾2A^U©±È°9`÷gƒ°T5‘™b–t¯E¦ÇìÊxš]8‘ Ï¨³ð¼Ý×QŸÖ4À>²Ç·Öb«yó sÌ+Óf{Á # §ßùƒËªWµÆ…^ª„ü=¬gZ’2U +Çå];ná5’˜PV³q2”™­a}Yu*âyqM½AOÍJÈpsw/ÿÈô9}A›n¦“¿BûòDuÌá§læÃÑõm=¾Åƒ{âu–®:›u‘ûÌêfß|Øè¶ Jü¾lKšÃ̧Ó&≂3‚ +ü‡ži»eø†Œ•)z/Ž`n‰ÅG÷f&•ºÔ3:-ˆ®ï3é¶½÷âwmyî¶T﨑[Š¢/¬<ø·omÖB–e™a©­—ýÑ+“—cì ídôDë’Øº¦‚‰û¤>åW4J8U\¥×t–îuQ+å&¿ª5Ô[æ‹79¿<0²«âÁì†ûŽò~“ö!þu“ýãºùæiy\Û|Ž!x\ó‹ÑÎûƒOwT87”T.^¹ºðµCû…ÆÝÎᬦ¦ŠžÔX‡S›6‡D:í³‘ˆÊW¢%cuÝ–ÇdÂÚ©Ò4Þ1ÖLE[ÁîhÞäPcË£Úé3:üŸlÛ>׆èE1­{ ï†\üÙ·!½Ù:Å\î±Óà’A¬£?;Jø¬ÅdÇñ%Æ-טwU»l4þîºÖx«ä£ÐÉóð`@±UYò7eQhÎsõpYdéáœfîB+ŸÅ“]…UýdrÎbiEiÍ¢°½±ð¹ù!íÞ™ *÷¢ÆMèhØwîtá¢Òªä¢ŽÑ‰&¯+ë’R>K3û0T?KŽó=õÆ•‘­¯˜ÜfÙãæ6bËåiyfË> endobj +701 0 obj << +/Length1 750 +/Length2 628 +/Length3 0 +/Length 1146 +/Filter /FlateDecode +>> +stream +xÚSU ÖuLÉOJuËÏ+Ñ5Ô3´Rpö Ž4S0Ô3àRUu.JM,ÉÌÏsI,IµR0´´4Tp,MW04U00·22´26áRUpÎ/¨,ÊLÏ(QÐpÖ)2WpÌM-ÊLNÌSðM,ÉHÍš‘œ˜£œŸœ™ZR©§à˜“£ÒQ¬”ZœZT–š¢Çeh¨’™\¢”šž™Ç¥rg^Z¾‚9D8¥´&U–ZT t”‚Бš +@'¦äçåT*¤¤¦qéûåíJº„ŽB7Ü­4'Ç/1d<(0¤s3s*¡ +òs JKR‹|óSR‹òЕ†§BÜæ›š’Yš‹.ëY’˜“™ì˜—ž“ª kh¢g`l +‘È,vˬHM È,IÎPHKÌ)N‹§æ¥ ;z`‡è»xEDDiCb,˜™WRYª`€P æ"øÀ0*ʬPˆ6Ð300*B+Í.×¼äü”̼t#S3…Ä¢¢ÄJ. QF¦¦ +Õ† +™y)© +©@ëëåå—µ(C¦V!-¿ˆ ©–& +ú9ùé ÈHú(Ç…é'§üŠj]]K Cc#Ks ³ZuÉ¥EE©y%àÄ ?-ˆ©©©É\7¯å'[·dMßÖ¶²Îuñ…U¬úœ?O¬}y“ý@ÄŽºÙ™)µÁ¦óÓK–¼Zøhkßañì‹^ÉÖS…‹¶HöúõÄ}Y$¼fkׂeL÷ëݯlîšÆûO[ý•çá°sZI[í/z<«SYçæåú<óR^8E-Þ÷ýÞ5n!­ IZJRæ7W°ße¯¼ûüêiEÎæyÑA÷·'ÄV/ ?czÍóÛëTéær“]<–·{²TBì¾ÍÓ> endobj +703 0 obj << +/Length1 751 +/Length2 632 +/Length3 0 +/Length 1151 +/Filter /FlateDecode +>> +stream +xÚSU ÖuLÉOJuËÏ+Ñ5Ô3´Rpö Ž4W0Ô3àRUu.JM,ÉÌÏsI,IµR0´´4Tp,MW04U00·22´25âRUpÎ/¨,ÊLÏ(QÐpÖ)2WpÌM-ÊLNÌSðM,ÉHÍš‘œ˜£œŸœ™ZR©§à˜“£ÒQ¬”ZœZT–š¢Çeh¨’™\¢”šž™Ç¥rg^Z¾‚9D8¥´&U–ZT t”‚Бš +@'¦äçåT*¤¤¦qéûåíJº„ŽB7Ü­4'Ç/1d<(0¤s3s*¡ +òs JKR‹|óSR‹òЕ†§BÜæ›š’Yš‹.ëY’˜“™ì˜—ž“ª kh¢g`l +‘È,vˬHM È,IÎPHKÌ)N‹§æ¥ ;z`‡èû8z…†{iCb,˜™WRYª`€P æ"øÀ0*ʬPˆ6Ð300*B+Í.×¼äü”̼t#S3…Ä¢¢ÄJ. QF¦¦ +Õ† +™y)© +©@ëëåå—µ(C¦V!-¿ˆ ©–& +ú9ùé ÈHú(Ç…é'§üŠj]`ºÓµ45T0425R0·0ªEQ˜\ZT”šWN-ÀñÓ2¡˜šZ‘šÌuóZ~²uKÖômm+ë\_XŪÏùóÄÚ—7ÙD쨛™Rl:/P1½dÉ«…¶öϾ(á•l=U¸h‹d¯_OÜ—EÂk¶v-X1¡Át¿Þ`ñÊæ®i¼ÿ´Õ_y. ›1§õ‘´Õþ¢Ç³:•un~Q®?Á3/å…SÔâ}ßï]ãÒ +š¤¥$e~sû]F1ñÊ»Ï/zÊíO]Ù3ÿÑÆó½EQ’žý^ÿŸYì^¶Q¹íøgíÅ×ôI\Ýä÷LèÐ!~ç³Öy?hKDgêV«ï;®É÷þÎOý©w_dÜãæf|üfÇçg‚û¸þ81Çú`¶©Ž‰óêü´¸5q¹­ë•ê-Ûa·ê²Kô¦_j‘»•V^,•uþ ÷êŒY³uU¾öíx”ÿkÏÝ:›KŽ©¦—|[[äèɸŒoÅ_;•¦˜œ +Ú.í)»çG¸«DǽKÚý|æÁ¶3®Ý£]ÇwÖºåÁÒ0¿G"­½ÖŽGÍŒÝäÔšcÓr½Ä„m{¬­_¶íËô}çŽé?áÚúçuÞz峦òÑGlÊ +'oúg¬õÉÔs±RÔõå*Á%Ï +endstream +endobj +704 0 obj << +/Type /FontDescriptor +/FontName /LAJUWJ+CMSY7 +/Flags 4 +/FontBBox [-15 -951 1252 782] +/Ascent 750 +/CapHeight 683 +/Descent -194 +/ItalicAngle -14 +/StemV 93 +/XHeight 431 +/CharSet (/logicaland) +/FontFile 703 0 R +>> endobj +705 0 obj << +/Length1 1612 +/Length2 12917 +/Length3 0 +/Length 13748 +/Filter /FlateDecode +>> +stream +xÚ­weT]Ý’-îîÎÁƒ„Ü‚Kp;¸»;ww×àîîwww'Øãûnß¾=îë÷§_ÿ8cìUUkÖ¬šµÖÞ‡ŠLN‘IÐÐZ$jmåÀÄÊÌòðÝÔRßÑ^ÆÚJšIdìø0r"PQ ÙôL­­„õ@Ÿª C€0ÈÀÆ`åááA YÛ¸Ú™›8h•Téÿeù+ ïúOÏÇN{Sc+õǃÈÂÚÆdåðñ?Þ¨L@#S @HVî‡Äw1­Øwe€È +d§gsÔ·05H›€¬ìAt#k;€Å?k+CÓ¿J³gþÀ´èìm@¦Û@. ›¿\Œ¥©½ýÇ3ÀÔ`l§gåðÑk€©•…£á_>ìFÖ²±³þˆ°üð}€ÉYÛ;ØØ™Ú8>²Ê ‹þƒ§ƒ‰žÃ_¹íM?Ük£HCkÇ¿JúÛ÷óáuÐ3µ²8€\þÊ¥šÚÛXè¹~äþ³±3ý›†£½©•ñ¿0ì@Æzv† {û˜쿺ó¯:ÿ¥z= ׿w[ÿõŸLìAF̬l9 >r›Z!ÿ +#k+Ë?솎6ÿô9ìþní_3C÷ABÏÐÚÊÂ`2B~·vøH  ýŸ©Ìü¿'òÿ‚Äÿ+ÿ¯Èûÿ'î¿kô_ñÿïyþwhQG ‹ïz–ð ðqÃX¤Ý1zvÿW¸ž¥©…ë³áßUAÿ ùÿÀ‘pÐûh† •ñ‡ ,Ì,ÿ0šÚ‹šº€ åL LFzúÛ®le²³0µ}(úw3L¬,,ÿæS2150·ú«õœÿp¬ ÿü‡HSþ–û&¯ÎðïwêßQrÚ;(¹Ú|ûRd¬ ÿsñÆ·oÖ.w¦ÈÄÆþ Àõ‘›•Õó¿Éö7 ë¿Ö2zv¦.’YXÿ.ü?~ÿZiýŒˆ•µá_³¢è geø1^ÿiøËmàhg÷¡êß'þ£à®ÿtÈd€°4omÀ`–œ–âP…›50&¬ÑÓÅ +9hST«”ŸëSaÝé¼ÉS¦ûRÈ\7þù­ÙuîØæuW’~o¨ Ç‚¦3tžCäIA׋¾FÝú‰aϨ]„œr¢î~1+½¥ÎÅ¢²·5&¯ ]øC<ÞÊnwñ@çCá”ëƒEyoƒâeT…݆V†Q•w|BwøpOÓ7<8ÐßyݽKÈOÅë…Læc›I( ®\æB“RDxÕrñFªÚá®MEI@j)ýGÎ8gÙªEú%:¥E€/NÆN¼i÷—ÎåôxŸ`Ü8ÏTÖûŠ#•ˆ=._=ÑoÿžëIsJÿ‰4Ø’;ˆKÚû`÷*Ë +ú?Ý(Y3ƒòmE5Î0»T,Lƒ!Ž¿P„šlì©Ü4¾I™€^Š3‚­¢úîgUõù[»¦Ì+O¤ ³´ìªÒðä˜~aÕsåéÕ] ÷þ–ð¯¿Tÿ>*NQp"ïÚêuæÔCHSâwϦ¦Xž| ¬+Rnk”žQzˆê(hFm6!œ È¡ôâ‰C +¦Œ¦@ÁÑŸIù©ñ~Ü{ê²n…‘\väëv䨇CŽ09“ò9Òã–æPZZªå÷[©KoÔØ+#?—$’ETØ>Ž,¡Œ§óùòGá„kµþAEЬµâdÚÉ~œ!÷¶ë‡6Ö1@tC6FˆàkKÅ¿q‰¨E´%• w4%#D=Ÿ®ÔÏó¦›lǘ‡dÛ·8¨=É»> I‰kö +å~”óJˆ"Z|±2BWÒãTiBûCzÞl˜G¥Äôðv¸>€¿0¦jÂOF‹™ešGC±5¥CÿxÉA>Q¹âØ×Zpk·ºË$#5d#HÕÞ$®Í3–<ú€|\ó;Ηx÷ò“8ûvßÎ)VŸ8–W–dê"«!©xEUMYõ£cG·æ; —Ö¥n~ˆ¤Lšéq,Íò^t/)® ;t)ŠÃ½[lEvXTà»V©À×™&Ð4{ˆ ÿ*ü¢±1?›†ºµEÞ¥Z={Ž@¯F¦úØ ¸Úuà“ªøóòål`ËúÙÈFÿƪe ¨d™tukp6YÒ…þ3zÏ ¡Ç º–{G`B¹5×6ÿìó;¼¨\¸ z—Œ EƹØíPaÖ­^þQ‰b¬±_Mw]?,=G9éŠ`UPO…‘y¥D4… ížüô-Þ.²çg¤<ÅeÈ‘\n ЀÌí2óš›ëÃ\s"G¸,Î0˜°¸47-kx¸ÆJ8úûÑ÷ü˜ }ìÑn¾gÎW=´o$Œr%…ÂÇQºï së–¡94öã8¨¨ó\h ³2å·ÜRÙšð‚ÏõàP#—ßê˜&\÷ÍNþ…ÈÔÝ¢>B”c%ðÚJSßv¾C@Ñ´á=9©òºçû ;Ù£ñÊÞ¤°úî;ÌN³ùÔ8È”$>Ä…õFôtj¯È®’‹ )“8"c˜5ï¸éP»†ÄÍé`¤0¾r%ç‘f>Q2šÞð™çã­¥¹! +«…Z—©._”ÌŽ«)­X[: ÃòO-zz«—%cýõ†²b×+”‹9_kE%ÝWlê¤ô%æ%èAaÉp}¼ÒšyʘLW%)%t¿ü=ýa¤{‹7篡0²çƒ²AÝEÌŸ.äzR ¸B8+£»£TK÷¦‚ö]݆fèi|ëæa,NùXÙ„G’-Fõ,¼¨1ÒB&œ¥&3ï[åÿ?U€'¯`ç\Äb­,ÆM»^£J¬†ë0 +)z­ZÜ +ƒ‚\†ßÎ*¥$Ûb’Ø:¿P[x9_rM6vP==¢çCõŒ«;ßa.ñs+×ÉýÉ™5פ&¥6]bž7|þRge9¯*Vâ+Yî;¤“7ᦹ3àfû ‚Þ’¢j£à{}Ñ9ùÞ;[¸ëzËHáÆ©¹œX S ‡X®ökuM†#MvøI›µ¸2éùªM¢xàÝ–Ã¥c@JT=]!¯;xt¯²ô¥këÔ%†4ÉQéª%õÕLUÕ‘« ×"±–Ô×Ã#¾à¨šâ'1ÄW3%¯1CQoe¬_›B³¶$IæÃH‘$D'ꃪ„°.]GÓŠjË05Èœq‘ö¾{®òFßø¿ô˜°$ ¾äRWUOS©¼¢ßõ_¢ŽçÁ‘sABרC–…Ÿ´Á‘Š¡pÍfb{?_Óý–y!ÕýÆ|В̲戚m_YÔÐÑëá+‰y&Z¥£ 7§%ìxÄìsäJjq¡¿÷Á.8§ÆñúÀÝÖzgÚœ–>ÇÑ'* ‚±ñ“\È é=NžÔ#QaÞdû,îgE‚’›8³›?mDQÑKbvÃNÔ)qÐÜI~ÀIÉ)²Ì`ÊÞ"Ùš£Oî$Î(«šÇ›ã¯»í Ø®âe’ÒÆ¬â)ÈO×öViâm<™ó¬ µ%äwŠ’+¯¦#•'Q€c~©D¥pnX}JgKêq㮼ÅbóÌŒWÐë ¿9T‘ï>]¯‹brÔnï^A«C}MÎ|z–ÝxÊÿÕ`Uažoå²ö¾òÅü¢t­ium<+&ݺŒÒ+kcÐIl-rÑdMõ=¦K€ +Y¯¬¶/ölÖã,”’üåÏÃxJ±röHíœëÚèðøç{5?n6™ª6_QÇ•oŽ{H_ÒoÈ‹üqšK óÂyô LË2¬ît™yŠ(“Ùú¿ÚxŽ™I¯Ág‚éШt¨Úù}‡d ×w,²ìiiádõOttËÙÆÁ€Wš-Q†$ár33oÍ\ +»’תxØ?ÅÄ~“e?y¬˜—4È7¥Á–»Î6ϼ„IŸÖ2]rOlžîç¶Ë4~DCàMH)|uržæá°•uÅÈiq·VÏÈh…Ušc¡²Ô䡯^Ë(åŽ4[ù¿ç €ÌÙ¿",¸Œ¸ Uª¾Ñ±½H÷_1…,.‘JÓ7×,±üfµ¦¤eì.ÐrL÷–կܰ=­ÏÿÁÝ]¤k.EíêZ­àSnïJ>vŒyD/@[Š/Ü:lMì©„Gn-cFcM| +Xy%ƒÈlNΔ¯Šë"~t`Ž6qg'Ðõ“¹mgÒbŽrú~!éƒYLH(Óëo•â¸u AíA¢Àýô=¿\Rœ'!¥‚—tŒ(ú]±õûg L²ZP&ºÌ·-l¤Få0“1>D+‚Ū]*3'^e3³2{=øäß-äñòZ‹¿¥u²[d W»Çžë³=ZF™$Kfp Üìα[·¹0@'E¤Ð%Ä1-aZ Éx÷ØÞÉO²•²Mwêþ<ƒ'ÿõ¢­Ž¬ŒnãÿœÀêlT ÖCÒ*ÀKŽ›t‚vú.»¯÷ª¡Ø¤¹ç§z±ÌNω EÊT”<Ê#oUø.>Æs‰g—øø+ +±\°õîNàá@JOì*Æ3Æ ½Æ5¶UBÄκ‹ã^î©I/©£Í²¹®B è’ã²EòÄÓ:à<§ 4ò \vÇ=9o¶ÈÍülÞýØÝ„#‡ß“¹¾‹:¡ˆ?•î舚.j=¶ÑœkñX_ö¤pB¬)*ÿÓ¦´ŸI®×›üOS!_Â$ÅB·J3¬5ŸÝõ½Ñ 3„²´Õ™Ùöĸ¨Ÿî×P)®ùRnm—Á¨£4·m5ø™káofë¥A±¡ãz‘Ãî÷&÷6Ç®&úgÓ޾̬)\–Å×ÓM'dÛm9%[‘JK²iÍ­‚ãª0%û5ùJ_) o\ê0† #’h ÆQV]Î ^!ÚMŽ0 ›x̳C›7Î)öÖè>oÓ R:ðœÉr߸C(‚”@%€QÝÚùT¿ÛXâl\=³Žþù%ºßj¾øi€v´¹É±¥ú|F®°+Ð%›O”ƒ?u¿žµ‡&£%`nÆü ¡—Àq¹ˆŠN¹JÛ°Îr6ý“EbÑ.¸x­g¡yu[vdÌqÓ&pŒc,‹uAI KóЏmbŸ}ùò³&öË€æWóPÏ’5D¶ïÕ>|»Äcôp„1š÷ÏmÊbü®:Æþ¬ôß„Yñ<ù %w6ø¸»_o¡iÙkîseñÉØÙrO¯ÝòGi†É¨÷{`£ÓE/Œ¿ªTå•e¾Š)s<Ó“åiÁƒkÃ^:º`ûá &ûÎ( +EÕo"¬Áyò°•ÍlbM7ÙH,ê«pêPÈß"¢£ø²^)WÃ,bœI¸÷BrNÌ‘êDP֟ߘ5ŸyÒP•£¶¦jŒ“uæ[L +±lÌ Óì'MO:”©f¬½õmÕˆ( +³wLâìaó„ßÍÚ“Líuã‰Ì‹ cL[VôÖxæáìÐÆÉáôgî’”I©U²=Ùe- +Óõ·ÖÙØ6‡„ûê^êÏêôñhÊ Ö¾|r§´’†Ý[ØÎ&Ò‡ª[·D:fã-ê +ƒ„`ñyÚÏɆºßj>›@æŸÿMÖ`Óï€>ÙíôH@O.x›™íÔê]œ‚Dë¡4ðÅÖÿXš-##'5°=$k ½¸ÎìkÓYAO$¾)g¢ÝcÛA­-÷ŠÚgw[m௫’ ÉÐC̰»uÌõ@Ï^{;ÂO©˜WõÈ/4R:ÛDío¯h1ºȤÌ_QcÜÖgDßz<žF”S¿~12…k …HP¢”°í‹¥ä®ï…fÖ…E÷ÐrO¬Ò?îQ÷éo­`âWz%ž‘ö75Áõž³t©ØV &õÇ<&iì’QŒG¸ð~w*ÊS¿%Xáö¥›õ7 õØb4R½ý‰zBæ;ÓyǵzŽÐR§58¡öG`†x﫟Ì%žìsþ“U]‹nmnH +ö`ÔòFä-!Ô‘º“†Ì´¨ž½F8½KVâÞ ýú½kØHH©ÝíHD§\³V1ðz`¤úé!HÝ÷m¯&ÛfÈs~PÇSúçóyy;Eú‰Ë¨¦h"ýƒÏ¢óФ‡±TÎãÀ30Q'5c‚ž›7ót½T¿àbÿdÄ\gOXWžís~†Æ1õ$©Îm§&çî– ¾<ó€>Íø˜X6ÕÙý!Úg{"~CÈn÷Ôd¨¬#µÈðRª‡Eo“á³#Vn ÿp·ÚÐ@ÅÝú:FÒ##n€Ôš†á†™uT‰~ÜJ¹~¼’HÆnîù³ëÑ¥óýŒtÆ›.øæÆI?üi4}|²“ß<‘Œø0k¥‰cÓÕÌ;.G®Ëc£¼Í *•¡úö_E„¸›b`Lq%`ØÉZ’‡‘øƒ™ ¯c¥iÍjWN…p˜gãÇdv‚¾Ù„® =‘;×2ˆtÄ1Êú.Å]5E½Ý`Ï(6Ä›´ÌšR¦Þ'¿”LÖdæcOÉ©Ä*ãu"àŽ,눔o.i;„šNyWÔjë76 ä´ã²éÉýž~GNµÂÞ^¨õEù$ðj`‘äÕøÅc09|£³£2OßU ð¬`ªÒ¾üŠÈ¼; œh4ERü*Æ^üö›+ÇvÆ\˜Å~뾚’SÍcš%Ã;º'cì½àIàUCÍüAx*Âù  ŽD²$%½"ñ0‘<:°“¾S-Hkö#~N9)í+ƒ¿,¬È¢ã/v'wo¶ÐÈHEáóø7…Pö¾CQýgHBñ%¨~ dÆ “q7éôUrK“† Aãœâ•b§áº)Èdº¸È@Á€âIÖÒ}rÞ÷"'ç¶8e0;€Ñ%U7šì ›z*µæÀŸº–+$»\.êN‰¿9Ý[$]  Î"Û+‚Õpžþb êãû:KœgYZïkç/ÕPÇfݦ÷þMÇ]ŠÄœÆÞ©h+Zš2à"¢j¬Ê9nqDÏxàÑÄIº›ëÆI‘(ûã + k|{É„…Eù'ÙöˆúÈ«C¢¼HŠçËÊ:Ï<_1ÉGBå€*¥‚³„‡ušÖöA»£DÒšäæ`>}h¿?¥Í×{4Ÿø+Åù‘N—#¯²ý†ù爋³ëÅà„‰÷rr4± +.¾^V¿Æ™LŠ$¸bZ”æÔ!ôZNÙvHÉ©|¢¢Šn&²§œ°ÅÜzggk©’i?ÑÅûéÂ7 ~½N?”ï³7 ›ß` + Zü¡ï¶±;¶ÈRØ¥ÅR¿‘&#Óvæšú¾ÕOO703ÞîàöŽ[Xù7˜î }3jäòo¶óÙy»Ó^5áŸC½+$§ÿd1¡~V‹¢¾×ûStM‰7 °À¯~Úœ]5Ùv›’õÉg t ݸ:ßá±R#ÚˆŠe! LŽQˆ9¿ +2PþéDÐCª=åúË_ú÷ïh5â5lNç0<öð°h!8…:éY¸McÄ(ß9G/Ûä€uŒPX ×|@¼ÙÚÛ®Ìë9w‰ùRÃ~ù†X1NJ‰w!§ëïS„k°àðèûE¿Ž¤ 9~PIµh;nþô!:†Õ·†þ +÷¢ù‡ÙàpXõ c‰’ÏC›‘ÅGËón8ô|yÌÙûÝùñ8+Œ†&ÒgæeZŠü-n˜½WÚpߦDNRëFDé’SZȯr€p®…·ø¸•î×M©“N-ÿÆÏhQ,{²ÒÆVì_ò +µÂ&ÊøÃ_îxÉ$ò¾%É*'ù”ðQÙ–LäžÒ¾usäZÿ|Ûe½å©¿6Ñò¸¨Û{Úô±§>ø~ÁG®.ž{áaй +]Yëä!åñ>íòÏP›R¹¾"‚ŸsVˆ­_ºæÐyjz »L b7*_»ÍÆÀ Ä¢ýp×î6龨´€YéÞ'íS“{`¬ñ†…Þð +kÞâõ}I›+ê{¿ +·ìzŸÔäØü韶sI§pvFÞ8õf÷§‘¶u["ËþÙÔäIf—& +Eº5øÑÖ|`•*@œ¶ÂbX~XPV¯†ÜïI+äS![¢ ½Û/š¾‹:;S 38±%µ1(Ï¡­ž½çR)`Qoº+t÷ä@©LÊJóƒp¤º/¶M°¡’8ƒoÇ/õîÌ?gÝv VM†ña÷¸ ã×¥\rÉD…†˜öŠÌÚCÓ"íù7\)ù*‰‹áHÒOö ڮ⌒'ù)Ó³Ó¢læq4Bi©C½?s ׯ7Hæ¯")¤ÇøxúMx6¾åƒ,hú‚dï“Ƀ³EAåŒ(‚oŠW¬£’sçp#lqd¥Íƒ~oìb%|ÓA(ټĉžOCS¿Äd.fä>n»ˆç0CU¶ªØ9ç«@‡fiYdìãµf^ƒ÷îû1<ù’1a™˜[Ôøk8ת™BÏ©åM”¡’rPkþãó”°ã«•Ë¢‹NK3¢ú­˜ǸMJ^þ¡•X/ˆÏ—.UaºÉ«(ƒwd‹(`”‘gðq$kÉ¥ŒÛe%W”CG€„úŽ·•‚øjB‚óíN–ƒ¼¨UýüU¨ÌM›2h´ß÷:ÓðÂÜXÖE>swߜÆ-gˆ>òpÏÞc@bvÀ†ä'±Z.Å,Mk<Âñ\>»G0/ŠTÄG=I⟠Û'ê]^û¤‹Ä½øyÄÒó ´RÎ –¡g8·§‰×à7E$ÑßÁ’w„;³qUhãÊ ãUŸzæëÖm—Ñ5æ(H’…o÷ôîóÝêʆ÷z‚›58MâÉ3o‘ªÙ±kÌÚþõ’-÷‘3”#@dT­Ò\ÔxÁëÊìŽèèŠÔùTËæ·@ŠPaЇé)Ë„W‹ œ¼¾iÔÑÛÊÙ{#%~»Z(§5 +ë|·æ”úºI­ª$L2_Äü“:ƒ°=Å3ro´ ¡2À8’-ŽWZÕ¬>µÑ6³¯ÙŠÛæ­ÿÊöûÀ^¦Ð]Hâ¥ì‡ Æ%ý”âD‚GÏÏZÉë¸Ñzåé–¥~mýI0û©°C.Enô’f-5r/–ÉàTZ¸…ß‘S‰¶ñy&ÂÉ7Rü[cSôоû¥ F°dª*–Û{X'O‡5®óBBÆ£±Þ\sï©flæú£·§á†*Cª~Š1×ÅpèŸñ"°NCéíPp r-º¡I,,ݼ§Q¢R7ÈѺKágÖŒÃe8œN’‡| +«úVL‹Ž\4ºoÞ¿›æ„îðÅlm¶ÄzizœY›ÐÀKvbüY¦f&…”¢ÑýYÝéÉ«¸l+-+½CÞ7¾b—¼²ˆ?ažŸ&6/X+âqçÛ–p‡¥ùÄÆ‚*_lÎt iÞ¸>Á‘áMÙ¹°2G¡ýÚ:¹¹rù,¥ƒ«1tÛ­úÀût9‘ˆšcãklÐ<¯£Î5™–Xl?¿', x±‚õÒ/ lh»µÓBzÀJñIžÝç!–|‹ó2äƒuK +ŒÓm ŠÂ ÃWÙx +­Í¦XF)÷饫EmˆÎ×ÿ’ /㘀¯+Ø35-Cwñj̓…*º²0¹€ÐðÝ}Ò4@’¹Nüe/ÐÚ°ö×Wh5ÒñtR +RüóøP–˜9ɱ Ž¿(8â´®•Ò—4»ÝÜ`‡RÃîGN›µtHŸô­[¥› ·Ùú +L£@®&Ï8BXuD¢Ï Ä)9÷…u˜‚h7?2"-šù=îìJôQÆ¡pÑv†á®Ã@ø¡×e[ñþl>ãv€dÏH4®üLÝ𓃹p^i¶>qv‹d$%S?Ã+à †ï ÝkƒE“è”ÓÄaÅÈ£¢®¯ Ï&–ÿz }UÇÏ Gf3€â͉íúÚhÀ„Ú}))å×ïK“Ã(Á_«qpqƒŽj @æK´7® +¯ÓJÊr8ÚU2:¬ûþ˜ÄI{.v8“42žwœ³ +n µ5­G¸†KN‹Ò _oL~ë90‰F1,•eè“g…ð¹ÜÚ?Þ×Ä¡Ö Pûî2(Ãö·gÏÎå0±pn­oJ¯CQ/À#©+F`ùaHó°EÞ§8ëJ%YÀÞOLŠ«‚›å½ÉºÏ7g .Mí¨È=i V8™àŠW€a:#ožÝ‚ÙI<†npýÛââѳïÐÉXÝ#úbè÷RÍÞÑa%옮“#?4¨áú,m|.³?9nǸ‹–®ä~˜·Íð8§”à¿ó±Â¼ ’ŒÄfXÖ£üœv* sÜ\Mž÷¬ó’ýÊïüê·T'^€oø œO9nEŸa†6HûêB vHŽ„còœp“$°£ö>°ÚÏÆ:‡Ê»£ýÑ2kû"nñwÀ$êQJÇŒð(˲p”ËgÏÅoï³=ÇVžŽßatÛø”¶ã'ä^ým×pÏŸ;sÝ9KN$RWæðbF´h-ÊëŠcB¬JrÆ]Õúô;däÏ9aÿþ¼EíÂFe8tKÏ^tŸL!FŽÉòÜ>`ð1 ÐhFŒzø–vôÀH8íöÆÞmóÁ _ƒš-“£Yaœôf ?.±ÿfgͬdv 'f÷ y‘?{âéó]ÍïƒÀç>Óìÿ²å‹”ÁðyʤKI_š?4¶É`RjÌ•oê¤É cÑ1¾!L0uA3Ðꦫc´}F7´…Âr©ûöüSâ¶Ä.x6Žñ +Tî g¦ë÷°—Ùdzð‰¥K'çšàúýº'xâ‘à÷PÈYa‚×ø§Ýåçv;©2Ã|ÞÈ{QA·DOñDèG)Îpro\ +¹13 ½m•6i)™Y,‡ÓŸm Òt*±L51»‰ê‘µ£,ù©¯ÖP@D³¶À)µòÿ¯; +_Þ"¨,'7žo’‰c8™Ýü^ ¨ ×àào9`ȦS8Ï_kÒ¸w›_<“÷ò²Wfj:&s#*©Z«Ã!þl-4V0‡\:Ž'p•𸠳¡¼'´Þèƒñ­ õ¡r“"îÇwëO'u±HÆ’ >™_ÖœQ 5ÌWƒ[xöƒJÍX\’€o¹±ñù?Uì“íŠ@S…sàƒ%áz1 ) ÷´Yt:ÖˆOyr…éÚ¥E5‰¬†»c"m} î87žªúáXØí**üµ¸ÊskŒVF’Œõ4Å"ÆAþµ½áJ\µÐ"ìŽF8Ë;J?NháÄÅä„fÝ[ç)ì1ø'AiyðÚÒ/™žÃI3!¤â"úäÓ‹Û rqé†ûˆñ?.Þ;ÁSãNé•ñw¦Ë÷½^ôÓfô¹ß4 +5}Â^ÄñµRcCdfi&gŸ¯ØtVÒš`úg7C­ ’oe pÇ¢†yH‘œæ½ç‘Ü”ñh‰¨©°­û®>^¯‹Œí•8Þ³í¬‘U69Òéz1ú‘ÃÌ寴ŒÞÅ÷ì» ¯½ÌÓu܆BKë|ÕVtžRé;á.‚E’Sô5B@/Ò7!¼U’DŠúh).üïy „„ªÈ‰%Õ³§¯©!,dmí[%°HVî±è˜'<’¦]G˜d‚ÜÀë@v¦ç &I íZkôw“µœü¿ƒc^ÿX/Y+‡y&MÇ.ãkPNŒ4G”ùpºÎ÷L ÅìL6r\o‰3`RÂ"q>òLd(v‡s¼u$G¡.ÅÞK~«Šö¢êÊG#ê„t§Ã±mÕÆ2ÇÈÊ«éDIKŠóÃñyÎ!»§µ’%QIÌ6)Àà¥Ô›0¸i:AÓÙ‘Æ"ø¼pCX!Š‹Z—¿Z{æÚV°MÊëÑOöÕºU`™æë‚ÏhÁ<Γ}Ë ›ˆ†^ ;ì¡«ÑTP#í|wš—€ÕW3*½"gñk‘ì¸<–ýR%&¦.‰á«‡ ×vê­cᨉIEšrÏÄ—y]ymž~ç…þt]ÚÁØ,ßÉ«Ù*¢õÓ…L¹9†!š; ¨•w…ôבD‡Uðê–Ÿ„»K¸M—ÔªÓ]— 8 ëj£Î•ä߯~I0Yˆš±¢ˆr7„záñ¸^¼]s=T‰ŸÜ¡ÕÔiCàW›ÅYÊ,#j;u¸Ë5íÖ0ÐÚhE¿'©0Bá˸ŠZ ?•¬Æåq®ÌŒ0S[H¤Å¾î È+žC QU×z™¿O椸 +“|XÀœx•^‘c.!#£X»P’~Ã:Þ3  ü\ð~ä;ëI"ÏŽä*;‰CbB°ßŒ2Of|ê~ΈÒf¾4Ø={P8Ö*¥‚´’MAQöÚ@îl:…©þr»”\ãÏgT¤>5_tô 3› +Æw+ááþà^Çšõî8諃v]*ö¼Ý÷úçþãbÞ1}»ÍŽÆÄéëÑ5tZ¢‚Yxé7|TœbÈô2E´Ážÿðö`ßÛîMÖMF7?…# oƒavS^¬|‘Œ_BF.*Ž*ó“ÈÀçλzh‡‰¹0³¶÷ÄOyðY$Ö6Uí÷qŸéÇGîìט̌cu]|Ä—ºë0h'ú‡“¶Ubû£6g>i¤éé¸0ãhMŠ÷¶šUš\¹ÿXôï+ù-öÇð°šï}Bß¼ÄÐù÷«Ú^]|–InԘċ?|Þ(ËÖ:©/—<2‘ŒÑ׸°Ö°êê~Õ´4=[„j˜ý÷ëæ‰·J=*¹yë_ ÙÞ±ÐÆ{Œÿœ(’ÀpÚªèd®ì^^H<6t2[8¾ÔÓ‰Å[mÁÈ)]KRIIžé½|sO­†ÃZeee½ü쿚X}IBÏsIF! ’2,`TÚdI?œÅ¯r¾úî.*öÐÏÑfêqÂí{Ózb- “¿lø­8ÎÞ\u=žMRü5“s(jèɃ¢ŒŒf hJÆ;–A'oæîîú\Ã.Y¸³°& 9’ŸýǽM?0)ry¶ÌK—ÄÂ/˜ân¬¤Ìª£¢IÍÇ,ánÅèa7¾Åâu©óŒ{ü;ÁÁajˆbÚƒ/yq7*[½Ñoˆ…æ[K-Án0dB·žJy5JbOoÒÜæ›´”d›Ërüú“]ÍÆX«[¥æ¶ñ¼ðsj!Lh€„)s¤’ù@’à!˜kÅž¯Oƒjv›€h›õ¾˜Àý㯡öÃåÊç¶ôx$>ýÁ£xãMëÆ·u^ýJ/ešXè­¨ùrð-°Ã[W¯I—SWLÿZâl8§ H‚*g!7t9œþ¶™%KÙ ›óîõ}¢Eµ>`ž“ñ:jV¸C&QL>;*IJ ÷y´õ|‚‚Ђ +U;ü„"µIèbpa¡ðfžyÇâ£íDB‹LÃÆ’Ž;§Az>·BíñýQæÌfh£“5÷x9TÁ…r%÷/]ÈsZrÓ Ïë´Ô°jòŒ!óÌêæcºùþ¥öŽCryǾÉÜ©ôƒ‰Úë•ÜUö¥ÛÒôÖGZù ±%Jsøh/µ¿ÃÉÒP.M”ï'T$­TêLî…Í‘¬÷œˆIT™Kà9ÐÝèºX0)‹åÏovéd+Ô2>¹ ÚR[X²&O„XÀ“e~¯d€”Jœ¯÷ñ" ÌV'ô=GÂ"é’ÜíE +?pƒl»Î5’º áð=ycÿx¢çtt[Ÿ§ÛÀ¶’f°0·-ÃtóC]Mrý;•‘óWéù±­ð:âЉQ/"ŒÓß¾q ½}>GYŽ-K ††çÙ>ñÍ4ÛôŽ b›Ÿ½PøgË …Eæ‘LúJ‰2Âɾz6¸qEy){¨*g#€–÷›U«‚doaô lTÀ[hhv€=ÅcA”$ ÅL9¨áV/GÐ¥%Ç·D¹ Å½Å:9 4ÀáPËâœö +jÖÏÍmþDÊNËÍOL T«Å€ú•ɨÂ_l8,*ŠìOŒ*^سá[‹¢¿ªvÀîÓô˜ñvž¦ºS²7´;ëGøúrL4mVbÕT( ›ŒÙÐPÐg|µÎ<ü} ù\n7g™2öýqÎòÀ®q!7¼s°’«øÓf-/~K‡µ†Ÿ££ÞK ‚ÖV¥Ïa‚Þ>ß"cIðC˜˜C×RH€ò|)ðÌï}ÿc?°æW4)J'˜Ö…\ø I"oÄ +dzfŠî6Ë‘H”Gâ\{^ ;ãdO—R#HjonŽ9 ~£¬“9Íæq˜ +rÀ–ï*+õOˆÒ¢Ézåógs+ز6Ã(S=8Å€:ï…Í«²t³ú‹­ ©M#ÚG` õá•í¼‘•ÀF{Ñ…' ŠPÊÊà^ª÷žC¸X»èNý¤G‘Ý y§±À]îçìB1·ÑrgéR*ÿ¼åÝrjUDy‘Ð2IÊèß ÚŠ M§mË \Z¹Ec¢˜ªjñU õ“l&‰5¿3Q±ˆÏ¯O´gdÜ«òªv#1ý8•Ù†¤EVÉâòð‰ò—µZ#kÄ\J,<õDPV;(PÕïJß§‰Ô +¸z·0mÓIœ±Ðk„j·Dõ:v³LFPÕ3–5~¹€wzªC~ùÒI|ÓGÄ͈J”¤ùå0CÝðl °zyß»ï]xgÕå(R-¼5é%n—&"–ú”<,<ÿا4‘‹ø-ªÚ"L1/G7 „às!ú= š÷¢¡Pd¾ &Ú¯f‡·^|·ËN¹7ÁíûÄȃ ´ú;Q&|±Š>Y¿»¤kQÚtÏû1æ¹›Ÿ™°+ip¢ÿødUª +endstream +endobj +706 0 obj << +/Type /FontDescriptor +/FontName /YDPBQZ+NimbusMonL-Regu +/Flags 4 +/FontBBox [-12 -237 650 811] +/Ascent 625 +/CapHeight 557 +/Descent -147 +/ItalicAngle 0 +/StemV 41 +/XHeight 426 +/CharSet (/B/F/H/I/J/M/N/S/W/a/b/c/colon/d/e/eight/equal/f/five/four/g/h/hyphen/i/l/m/n/nine/numbersign/o/one/p/period/quotedbl/r/s/six/slash/t/three/two/u/underscore/v/w/x/y/zero) +/FontFile 705 0 R +>> endobj +707 0 obj << +/Length1 1608 +/Length2 7084 +/Length3 0 +/Length 7904 +/Filter /FlateDecode +>> +stream +xÚ­TeX”í¶¦¤D†îînî„™†˜Á™¡¥;iîPéIéni¤iƒ~gï}®ïì_çìïu½+ž{ÝkÝëyiµõ8eÁp+ˆ†âäåâjB­œ‘z–0uN9¸xç¼ÏÈ(€X¢ p˜‚% +"4‚€ +È+**zŸ(wrG@mlQ@]#VvvŽy~§­Üÿ¹;‰„ÚÀ€Lw?.¸“#†ºƒø?Ôƒ@€([ÐêÊki?WÑT²(k•!0ÂÒ¨ílåÕ¡  aZÃ@‡¿ C·†äºÃ’E-H'zw â‚8ýq G(y÷„"6Kên(8 +98ƒ¸ó[ÃÿrBÀï2ïbw`Úp$ + B@PÀ»ªÚ +JñDÙZ¢~×FBïÂ@¸õ]&rþÝÒŸØÌ]e …!(ˆêw-+ E:9XºßÕ¾sB@ÿÐpFBa6ÿbÀD@l,`ys‡ý{:ÿêø?º·trrpÿsþ'럠($ÄÁšë>/ß]Mê®¶ vŸû÷¢¨À¬á@^ž¿ü`g§Ä\ ˆ?bù½3¬w$,Áp˜ƒ; ±¾Ï­ GÝ•²üßTæúωüø?"ðDÞÿŸ¸×è\âÿï}þ;´’³ƒƒ¦¥ãÝüõÀï^$Pøûù_¹–ŽP÷“ý÷D#È_ ÿˆ +Êòn ²0›;)x¸xþrB‘JP7XŠÙ­-îfôÇoCPäNË?crò + +þ-¦o ÙÃ~]HôOÿù<xs«h뚪°ÿý5ý“¥}§:JßÝéŽØ÷¡ÿÓø!'wzrò +ó9ùy„ï.?PT@ÔëßÔûÄû/[Ã…€ºMïšæáýÓúÿ²Ìþ£ÁÁ¿÷De ß­Ö?¿Ã gâNÑ?·ý®åØ–qƒ€îÏNÁAâvI©É¨JŠÌîÓŽ6^Ìî §‚Oú¹Ù¾åðVŸ¤ÐeÑ’—¿*‚¸ª†ÄnêÝ'wœ®×UÙ6zÛȘ[ßAö³žxѳ¶g/25 +³oøs›&ïEzL¨/a™ñn¬ èèšçÿ¡jäGÜ;8gõ¥wÉö%e8szà Jüø†¬‰¨ +íaeÎÎ.ÓÛ­ó3æÎ¾žî®ÖCìöu*öŒ7xŒâ.X„L¾¯2¨¤M J<£¬òyßv–Ç··°ð/Î’W/ñM¾á}*Íyî~€Ô üü=Ÿ]™ÏÇÈÊksÓêò™ËK6ÌQ­]%&X'3ð=Y?±Œ–öŽîPQÝ÷]]ôx–LyZÿc X•{µR içË }šhwáÑZNc¥å0×g߮ˑژDµêÉ +¼8eRÃwH+ׯ~ÒÌ%Ûo1.ì«ÆÞæøZ{ûHÞ¬oæ»ä!"Ë«é¸O ‹¼Qwϯ¾8‘e…†= ¶OŸÉ—ëüø¡ñøØ%jíéa¯ Æ’¯h?ð²¤_`•*E }À©Ë+^+—)¢¡a'6°¥Lëã¿pféKaǰ­“òÏðŸõë&à"›SqyTâô©½¾½7øYãõ¡Àî ¤yËJ5À¨ÞÐ ÷“]œ ›PvŽôvåÓTà~. ž ú6oÒÄ…ÊGѲt÷mnŒWW¬>ÜžWi$®þ`8ø+šK…I\æà3&¿4ôQÝ!£•O„ö Ûhž#㯣åÃÁßC;âT +ïQð"_%\Ö–5ê£Ä§ Ä5öÉR³qÑWg‘r þ‰rú±g}ÊOûŠ¢A„HÒÇ|>¾Þé÷µ:ŠÒaçh9žÑ÷x÷¥úgÞgÇMIü +Ãg9KÈ`-טwËC ¼XÈöµ­¦Fv-þ¾|8^äpk¶B½VéuºÇrÊHvAÍíúËÑ7—«Úf¦è‰°Iïš‚úÒW ¶§#´² ;ÍD_Õm•æXžø1Þ{}ㆇDŒ«c*¢ÄjöÃF)˜d]ÜYMÁ€ö÷õWáÂåÜ€ Z‹Ž +¤Ï*.¡þ&ã¡ îk³u +ÂËGœš"†AW²Ù3Æ¡H3R\ªŽñªV²#/È)»…†âo|.œ‡«iyåBn2uüSû3‡ÉjšÛµ›™Íéœä(J$°[ à–wH‹J:I2ÚÂÀÜ4ŠER!‚†¡A{vî¢ê'CñCgÜ‚4 ¯W:Û5è¾Àè'8ÜoÏß Õž¸V4·•2xë>ñ€{Äì ÉŒ¼–0Ïù±ýêxhßI›)Ö?½H²uâ=z³ýÏÕûCg½„—?(Aè&¾‚E­Ô9|Äš6a úp=—š«îºå(HÃhHtfeþÅ•º"5ÛŠsìóÌ)Ú³Z¢V×^ßFeÙüÂ=A¿Uç¦ø½]Oïг‡öá¢Üi=äxÕÁe¾)¿‚–ÇçÔˆ’õ^î0j´P°4Ÿµ·NbNšØy€\*4À¶‘4ú°ƒ•HÞ|ù\Ò÷8DÊ ýw´Ä Vvq£•ó¢«r6ÆÉB’QÝ’ï{‹ÐÄUU›]ÏJöéˆê+/ÁéçuëB5Ðj+Ëgn.ËýÆe^̼ +Yé=,ö_•Š’viž@©2íü÷Pò9èTr(xu7ËîÎW™oÏ tF +á­›“òð{¦T“¹„«?4÷¾óQø‘"ΰ¾ÞG)wsõÍïË'“Ž€ùÉð +÷4É›¯#^ã=]/¾?ƒTÿ4ÃQ¸XáÑá<#B#o¾TE:q% ÄøŸéh“%ܬ #„’Ø=á^ný5Æ:L§<ì™ÍË¥†­ÂÛ¡˜³®!xŸé“–r]azÍJ M½¯ÇmlÃ)¾òi½5°C “PyD¹Õ£I3†éò<;S•&cQŠQÏ”j3gµóbÉs’?wG Êô- í­;{fyœ¬C¨±8ºYä…œKN뻳l^ÂéMö¤„¤?}}x¶Þ! nAZ龬϶_3ë…”dÇ?AŒæJs K8îÖš’?†ïH½°'˜ôúJ¶ ã²m ^­Öœ¨Cc®ëºGæð.ãÝ™Ç@£r1…8¶ÆmÖï9„Ï7¿:é>´~À|¼£M~øÜoÜ\rդ탧V{3fGÄÙä®$³Ž¶äö3›éòêýyì$ã**šA¬‡CúíÝm/Yc ëœÔ‚5*ŒÜ­çËŸ6LwŽŽr™-¤Ø0SkìRWI'LD^DKPbá`l.Ä øcÚÚ~ŒS~\Ÿmö’øñf+DÆ=­û€‡ËxzÞˆEuópã·BªŠ)j•Êá]5Ïr2·TlÂ}"R?M`+›j‰Oó/¦èžK½“r.+îùÜãOJÙ®·SŒx~ø!Š]m §›ìGM<_··å+÷Ëb/kO’â(9!ô^>±• —Ïm¼ü˜x Z&XH`â¡‹Ù`†€Ë-wñ,‰L]Ä®„ÁRe¦TÇ¢-ºÙ&a€—fPé³ëòC&fk_^>§¸+<š×^œ òc#^4­Ä¨2}+(ÐVÕE½ Ý"Ü“«ûU °Ûº|mus_ÅDqäÎð0l‡¾³Ý‡P¥”ÚÛó¶·¼ àöÌÆ{Ÿ7YËáVþ°ïñ¨Ï/O)ÇñºÀæ‡ü§Ñã_ZÏ©ndMûÔ†°Ç$®ñç*´è»h1k^Lˆª-R`3E-ñ}ž«Íy…3Ã6l6ËkM°~ÌH[cp¨B¯…÷ùjvˆÉÔŽNòÁøœS»ü-5ÚÝù ê/˜T²LÚ4õ¸O‰:æd 9÷¸q;–ùØfI$Ge~pp"!ýDr?+9vuÜrŽ;~ŽYrš§}~ æÅWòëŠz$`¾©ÑNIòø½ómñí/r+Q¹·^Þ² +MK2ìË}_ +üa±ë`3KMPºKÎ}pâx)-|­³wâƒØa¾Õ³«Ê¥™ïɰÛx…³»p¹—ˆ1 +|Ê6™)Õ‹'¡ìáâ7TX ôCé~^Zçrk®ƒÜó”Ó¼äÜÚ{²ä?h‚ôLõ}CÁãw)ôßËØ¾÷è)î½÷zõþÂ9ß>rTz½òôþšxSC=8@hidé†;ðš *dd<ÜîÕòCd€ÿ¾Œ‹¸›W= …BÙ¤£ɶj-ežF\Kò`¡]Ÿïø%S®tAÌŒ÷¢y ¤mI'ŽЭÌÒTÙ«¸½zé)¤³5Ûó|³?ËzŒ1Ïû¹vdŽÚí·'fz¬Ú.NYõoñŸýtBî1À}Ÿþ”`y0ÆF…ƒ]«/ø ×´`Î,P׬O†Â{ÏTëµO\ÊÒïÉœ£Y W¬KQ×®ÙàÖd2A/³Š0€cŽŸÈoG›ôL~»„Ð(H`‘C^K: #L4b|—"©?í5—úˆñ‹ ›H¹#{èmÔõ½^þüÕ\šºÇ•ïʤ Ù}»ÏöžGØ-pÜ‚E§¥Õ>'Ÿ5©w¸Ü‘S7®ç%\ˆÛ¦uÏàá9Õƒ¸œáž¾§ù×´‡ÅKÇ@‰ óRÐ4‹›^'H±ÀÀvs^ }…„Èd&u·©ÀÛqntveåêpÍÏ’2ÀZwйzÚÙrm ‘º^-3 :ªbwÌ“eØMfso›¤ÂÞNžÞE f¸ŸîýØxÒc9be¿‰%A޼`Ú ªMMñ yÔ…¯)?“{r¢RR|È(ŽÆoÞÖ \E¼Ä–éõ*†÷¾]®mÂèi ¤½ü‹–Xo‰þ܉¹<ÿZ_Vã—8Ù‡%NU•uüžÕâ,•'q×îR9^Ý^oGžy;µh©¬`šªvi•+U¦Ü'á8&Kf§:~Ì"æ¿V‡ç‰L8ðêH5}Œ§D£õ)ÊlHŽgŸ!1}j¨ê‚zcú&¢]ó&vª/ÉsfCM§¦A^ô]tBâ¾R3Z$Fü¾„Œ´6Ö¡m»ø~×d¤ú³,¾bk±#=­€Äª÷Ï>’ï£+ý SÿIï@¿k}Ó?K^ªð«ý³¬.^Žõós•=\ìO“…y›JøÜ“1Š-{:ïÑpÆèÒºë2†™ç•iøÔxÐ_¾ Ö1^Ù­ßy0|Ú~[z½ºž&~ÞÇ¡C”ª3Ÿ‰re£Ü8³§c©È§ü1HRrâ“üZ.´øI䜹<¬L Ï782†“Td»ý™Õiýôê£ç˜h;É1©êíÌ@kŸóðBôcÞ,Ú^ðª5­ðdJí(¢Y·ôÂÿ×»«²­Í5oµ•EžFÇ€I^Ê—.}º¯³K<ÓÞVâ÷®û¥ŸG§s¡Qã-§UO›˜/̵÷Cƒ0qH'qp3sgþè*ÓÚÝO­¶¼j•U°›–1i¾ÝQ. ¡d{:uòS x5àòϨcß.šôœÁaÞÛy€kDèû´DL¿óSÜÙäÚÈ:1Qα—Þs,ŽéA‘ŸÙæX±×2Ð_ãhÃܲBòhlF-ÈîãÅAŽ^NÝ©8ï7`½ú„ÕÁ›i¼hŸß 5†Äáƒ_ZHP²I(×Üõõwº§ç¨Ü¦™N+ùTõIJ0µâÜ€4”áÅ9¶”AÇeÂI-¯®¥`ªÎˆA~¯@A4ÌúÜ! +cL"¸æ`Èxpª¤àÈ©;Hq—÷B?•­È'¯´sËê™HÁÇÅa•uùP8ºaŒî&‹ + Çsqøb³ZqiB25Uß´bVÏ7eÒäè~Ó•ÓÂ_ôžÅü´aôH¹ßËiê^-¶ØCoFPüzûÑœf8­aÉô+eáºLß[)‹îU²GK6؇=™F)·6né9.?ŽX!ö¿vYùUŒäexŸ¦ƒ {/ùoºô¢²ä|Oƒ>MÚ¨sï£ð‡ßXü`ØáY“ºb¢_\6e£ÓÝZ¼ú­Xó¼ôözXo¶nöluæ\!|ý¼Ä‘*”º:Þì·ÊÆ)x?›¤ÌPpA1=ü'Ìf-í¥aͪˆ*Ç*ˆ{BXV:f›QµØj”;îœ,2¾Õ+íge ~(6™¢¾)…OgXnËe<©‡µF+ËÒ˜vDdÏøNŒ^ó×KÇõ̲/jÑô[ñ3 ÛW>KO8oR/ üÏ ˜Q~߈‘áf*-]ݹ!R¥ožDù>Oì =ó +&ÂmM¿Ùi†·(½2<3©`Œ€6Í’h]…¥‡éðñjcÍS‰ÒÀPø$Õtõ—D¾)KÀ0¢¬F‘&ŽUY£³ä$ý9ˆ³Þ¸wv )Ÿq*º—ù;V5W 6¾sé…u’àðÐ9¿ô¬ZÎ*ÈV=}_.»¨œœ×zì"™:Q—·G%åÿxHFʽÏÜ`} ýjÖçqsD?R‘;—¼òñÔ¬û%‰´ë[ †ïgAïoù\äæ MÓq"}Ù&Yã d¦ï¼²»RlF^õ¼Ì[ãxëvZbq[ ÿZÁæ¼:Ü…í§aJBSÌ)(«8åì>àž¾5°'Ñù8þ@\í¢ãÄAQë5Å7©x²€Ót‹ZƤè{ôá…ñM +inrÞôµ6GÞg93+<½s›ëD›†˜ŠÏm~™å.%¡Íh™&yÜbYߣo%T‹\2ºŸct…$÷°²_;ØGI#ð,¸Ô:‡Šâ 'rÎéÜ•€-ì45!¥û’ù‘õ'ósVƒÒáN@JûM«£/Aö3c!=L® ˆë Ñ7¹Ö¢Þ“ý×Çj‰l£„×kãi÷æ„Ûˆô{&­)ªz=®;ä;«*nw"Ù©M)$Ë“ÕÑhP:<$ÄËñõ:ù¥úu׿{±Ñ)»&Ϩxì-Fßt…]+¨§›}KÑ•ð¤ß×9{œ:̹%À;6æ»UJHž…X+ˆ`¹VsT—òõëu€YU40å]hW¡ðk©Å#v&û/¨2n¥Îšp™m}bú“­$ºÀqtý5ÚÃæ¯“K7>ucvÅôGæâ øü0'(-ëÒíE¾VñqDø{ñ}äÕºÅøaxKQåϰ¡ÈÏÙ%¹ãEÛ8 ÉÑ ·‚ÏÛ} tñøô¤±MTôD—.ôØE´j”vo ¸ð[yߌÑ? •OOä5žw¢‚‹ÍVnê¬mx>Ÿ²#Î`ÞVå-nqÃ¥_¨>Òÿ˜gGF¡‚}ÙÄÙH°tãö­Íæã|ï‹Ê~-l³éRÊ^¥=óï3,Äy‹¨3úøÍ•« «ñá?ç!#¼_e˾’_ÍŸ'^*-Ö›­òJSŸWTJD—HÑ4õ—YMdWÕ8ë@ ÁòýIww©ë×af¤4èSŒ?ìÖ\ÞbµmÒB6¥Jœœ[U%ØM±9m ¾•´·h÷SÓ·™ïkx.wCßRÏ<¾YïçÄÖUEZü¹í;}Á?B +1hÖÑW‰,ëÌh"ç†? +ÜñˆÊ³ÊÐ’„/¤EÍwzM64E{WÍ7–óVpœD¥~A\ÁY£où¾÷™Ö|b“-%âyG³ Ñ€e‚ŽÓýþ<Ûe"Í»6WÂ(Y?Yß-vSÆÜ5“2Ãtíiy3½Ëžý)žE±]L{¡ú&òÉ4\¤6eEýè¾[®l‡üÚ¥µ¤wľ‘„é«Ú‚ÒïM­žBCÃ2KtO_Üê°zù$f4N" [¼©Qo+¯ˆP öDÍÝeÏàŽ9W¿ èì·7ናÎikï#–ºç8Ÿ?ÈplÐT¨u¥Óc¬[‰šqdf ÷¹áfM½bm÷hË©2Ö°I“šà—rÆ„·–ú’;Wf EõÒ‰2…žviÌR„‹õOi^Ðf¨tœŒõî‰}OXhr¹ÕèÌÎ}InÿÊùt>pq>µId‰uâÀMðÖ~®T›úœ‘=ˆÈuŒ&ë€<.»ÊÞ2X)¬Ì…Œ˜òvó£ > endobj +709 0 obj << +/Length1 1625 +/Length2 10429 +/Length3 0 +/Length 11255 +/Filter /FlateDecode +>> +stream +xÚ­µeTœÝ²- 4¸[ã®Á!¸»»Cãи{pwîwww'¸»{мûÈû;¿î=?zŒgÕ¬5k–¬j2"y%:c!PdãHÇDÏÈ5·6trP2°‘¦Y lŒ+,™=ÐÀÑd#làä¨Â@#33€‰““– ²u³775sPª(ªQÑÐÐþ·å¯ ÀÐí?‘›æ¦6òg ÈÖhãøAñ}Q 8š&æV@€œ¼†„¬€RLV ´ÚXä ­ÌÒæF@ Àd°ú×`ô‘¥ùßÔè?¸[ ‘ùÇ5 «Ðö/D °Ú[›;8||̦ö6Ž5pÌmŒ¬œŒÿ +ø°›€þdkúð°þÀ>ÈäAŽFöæ¶Ž€¨ò¢ÿÒéhfàø7¶ƒù ™|xƒŒœþ¦ôöAó:˜Û8®ŽcÆæ¶Vn±?ÈlíÍÿ‘áä`ncúß +hö@S{c+ ƒÃÍ÷ßêüwž€ÿ#{[[+·nƒþñú/ æŽ@+zX&æ˜FޱMÍm`þ‹„ ÀÄø/»±“íbÎ@û +Dùwf¨>Dƒl¬ÜÆ@XYãGHåÿ]—éÿ÷šü¿Ðâÿ•ÿ¯´÷ÿ­¹ÿÞ£ÿãÿ¿¾ç§u²²’5°þ€-ÀÇ–qHþîÀßEóW°ñÿï–µ¹•ÛÿpïßÕ€ÿÒú—îß1 Gƒ‚ؘ~4…‘žñ_FsQsW ±¼¹£‘ÀÄÀê£ZÿØU>”Ø[™Û?ºúOAtLŒŒÿ†)›™YÚü-?ë¿ àÇ¢ü7åúG7ƒ„†¨¦Íÿ´[ÿñ”ÿ˜Ge7Ûqÿ‘‹ Èø¿yA®:¦oœºoŒì޵ËÉÎêõ?„ü‡‡é¿Ï2Žöæ®­¼™þÉþ?~ÿ}Òù7#ñß¡Qr4°1þ˜³ÿ2ü…œìí?ÚûÏÓÿÈú?ÏÿL<è +4‚ý½2â°HIOu¬ÂÌÖêéb‚´-ªUÎÏõ­uú¤„lr–é¿TÒ×Mp½5»ÍÛ¾îJRï uaXQt&Ïsð¼H¨ºs‘×È[Ùiöüt‹ROÔ"<.æ¤7 5ÙU÷¶Æu _ ð'Z¿ÙC_!?|¸§èèï¼úܽ‹K“ CÆí ‰@îk—‰Ë§©RæQ‹7lìñÐõŠñpŽüU°*ï:s +‡@4a×/#ãš²Äæü74ÛPÌKl3=k]qÇ\gn£¬4ôõÒ¶dêØÂ ±õ·øò<ûÊSõ8ûÞtLøª5Xløzé8Íac’¦˜®@ŠÆþ+(û!±aŽFfú²MÈã5º„Î X¬@hMüTÈÁDeacÏ!jyalcÐ3¦f´à¬òîØ] k4{ÌõyØýç&ªA¡J[ïU /ÑY —`;Ž–ÁÛÌ +€&El’‡º«.û¸@)Ÿ}‚„Z/·h£âVýûº_#RÆ1z*^ þ§œ²2 +œÐ"%´&9šVsàð'²Í|û\Ó‹b7:5ƒr·p¥Þf…z Îå!*¸¯¤Ò/òYÒ«­1I,V‹ û^/P¿ )–¼ ˆ°›n}mM0ní5Ex7Ñ=‚kk%!é\t®¾Åa=Ò}ÅG ¦Ç`I A +Bc R®rƒãúpC½û'Â’ºì„>6‘Kê`4à{%È6û$³8¯3³ü ¤ýTU D'ˆ†µÙ²c¸àvé΄ Y-’<`ãöªÁ/ãÛšå€(.þÔ)Á"N“T.@Ê-#÷¾qDÒ%£s†pG‹Ä÷.%_¸¤dþá”Yü=3*x!_E´¨¬ ~sFüWYFI¬òa³WeT~©Â}}‘ô™ûM¸Ð’jä¨à«K»çä+Y9Oç×(Xo/8m¦»9A}ãü-dÖ×AîàM—ZzÈãS1· +ûS•îº <»—ß•¤OYé*· +Ÿ„…ºý9–ÝEÉ\íŽÇ{*^ª LA§d_ªµ ,2þ”¸Þx’%¹ß]µ÷|·e Úýò,—gEYåÚ$ 8剒܎Ã&F0jï´B¢úô,ß¼ù} ”Þx¸Ž‚ ˆWJÂZB3”YO2—Rëº÷Ä +Úü”¦×ñ™W‹}*fj….Ü–Ëî´*wVÐ, +ã#ó ï)¾¡„Ì-'¡+øãÒö–’zÃ*jY“¯!útðê\äù¢7©<ÝX¢Üð{l3yšõšø#+z1ýVótQë ‘O¤gG~éó2¬jJa߈Ú´Ô¤Œ¾ +Þibdñ«åîÒäqf|eî6þsH á !<”ú —5Ç7±nZ3O{'ã!Ùaú£èMâ¾Ç‚ÊkÝlMKq8ÑzÌ<¸#Y* n?{ë|;5vy>LÖÙìL_9Ž)>T ü©óÓ~tDk\šõù= bYéÁy¢ø42o™úg_V„Öz™ +ó. + z¢³|¨ÚÔF@oÎ;Ž%š›Å—׃qKVÑ_Œ»‚‹4—%jè à¼áC†ÚÂÆV«:¯4¢p©0¾3Ö—Ï7¢¹¤S9ltÀùìx¹%.9„=î{<eÍß#ì<»d)°èÛd*§\·û#*y}q|œåBŒ¥mÔY‰lfÖpÙ^ÆD}‘ýeÏMÅpAde¼g‚Ï'_™,av?£‰ïå;²(qö€œœ“z¯˜TE(‘þ°¤Ã¤qÈ’ ­^ºæÁÅÁe2£à’6{5ÙDìÑøM +/Ë÷‚¾\–ÕδåŽkåu +°˜´¡ÍKƒá[¥Jq»&þj¬ô¢$ Ñd±˜j«ç×ùŽ:H¬Ï7]ÒÒ:÷j‹ì¶ðµÚ#C¶>J“ U|úÕñЦ%«BÄlßñËXR¬…û®'2Nd2±ßF€‰ˆÉâö·m.üšË0¥ÚÓüu÷VÝè¬ÞFgÂ*–CÀÙâÈU}@áÖî ·ÂDßëã£9Þ€Æ~•”¼–8…µõOä–.6Ð)£²9Ylôõ]h©SèxI¶øö|=$íЃf×tw#Œb«ñx !w'!’2ŽUYS^Ëë÷°Ñ°öLWÐÿ”Aë¼ÞÍÆâáCa2òŒþTô¾…Á eУ&ëê¬AqY¡Úèw¿¢Åoâz÷4Aaí»C´®©FÜÌÜUn_¾;ÒºÓõËÞ®ù±!÷| ÖŸO ÷"µëÀúôµ^U4rç«è"öË”‘‰š(¤ƒ¼*÷ +zv9“ êp…þbxm{޲^hÞ‚T<0Dãä>ךž˜îtá$‘ƒú¡a‰K½õï=lÈï ×V|KûA7ÓÒÏO6(fѸŸ†Q¥òLâ­6_ÈÜ ÈiÃ,wk³ÎR£_¾ºü"£« 5=÷ì1N+ãltÇV%MŠÎI@_*t±.;m[½ ü"–ªhë ‘W²æœTË#‰¥†öm«kOœ²xA/-†é7€ßŒìEcãþáã’指j*r¾–¼T¢³VÁqÎ ´ø?ä žäcüF~ÏboåßäÑ‰Ç ¹á<•¡¦I1N)®0ú¦s÷mU€=J½ýÛ­Œ3@ò]àr8¶üžIïÑPsÑlK~Gb…¸öòuÔyÂ÷š‚®%ƒ?–˜Ûž‘cÿŒ×èX62`ˆXšŠ¿F®8Ž_)ŸÃåZô¿Í‡y‹žÚöÇm¶9ÔÀßq¡2¿»¼$áÓ]jÃÏ»g?ÂG»æ;‘]7šÂyZ*Ðïù9õ.lcÖ˜»äw.©“ØíYâðˆ $&„7s\ÔÏ=6˜Ø,ï Äö¥¿Ú]—¤é"[g'—+¤ "å9÷•\S'¸½Í¹©Â_A_öryé˜K”ÝÐPæ$ÊŽèð«óöˆsùsA°é!¤sN¥Òr “Пx펔°ù bæ<©D_\ŠkWÆz ðK…H†˜Èù›j~ŸµÖËñ­™*íßjoŒ€ÍI¡^m«=^Å*P&.lÓˆW|•1:&>–ÓÔ˜j,å^éÜDÅvÓt’¹Ñ¸¹U“)u'™ºãTve“EuºÔ%b­Tm €lÔÆüýºßl•T² m .©;d=%ùmlw +áþ*èçdA0ØlÐ%;ʵÅ|眢 ¡î›I™ r¡“S4¢ïÀ ·ÉØík>%ñÑXÄÛojƒ% Ňr³—…Ÿ4ÉæoôEr¯½ä)0d^÷Ò(‘…Ÿ½Uæî&_Õ»k/p À£[ÔK +c~Ôž©zfÂ"ÒÈc¡a= +Ð,aÈXK÷rq‰°÷S»`(蘃kùÖî}# z +G‹10}W¯hƒPT}‡Úž¢GͤÒÂ?7†«5V¼…á”:“©VÍ+i mCÐÑ nkõ1~V~±º‚(E¼^SêHØbކdR<`1^1r¥Ç¬m¸ßD„´ô=„ƒ™5¬L£I*†24’™\7TÆd~s'òjº¾†é»øÒýz ‹]ºBL·ã`Å-Úܳá†èFžhÒ™‘f£¼I<æbÉ® ªPYe¸0Àõ¥×bŸ i|®P‘4D|'†I`”yÂ-Jr$xv€Å+o`DH‡8c‰›Bʇ¹æº‹7$Èd¶3üÂ:<ØGÖÂä>9–7(z| i~”&^D"Z“Yð›çâ,Øl¹Ó‡^nbÎ ãv$Éãf2JmlOÞÂ}˜dU—Žâ†¢'¯Oãè'.Ǿ&%§O*)ôÎa[ò:ÜÍ „W +A¦Ïs_(ujõŽcsg"qþÓ¯VÔŸe³"NkøÉκ2¿®;«¬ŠÑÊãY`†S~”ê†Í8µÄ#y¤ÆË;Ö×ç‰ÁÜT¨¼5¥EÌVd›ÃkÒÚKHh“ +"Þgy3m)T¾møMÁÈUø«ì>îâENϳe·Âr|Y䊪÷žº#¸)|”}ô=7â—üM±kú2È^O¥›ŠZ·%‰;|Ñ\Dlçn¥ ±Ž%³j!`÷RÐt¬kƒÑY#BÛl1 Ÿ<Õx­Tò*_z"ø/DƒÖdã JdZ®"kÏ*n¥3#Å¢ÍÃ< °Ò’¯ÅeØ%qü‰["ãÿz¨O!ÄÀuÑ^µžÃ9Ïy%ª#ß?½a7h¹h}ýŸÊ YÆŽú… [îýDºÏWÄRm²°Ç4M±¥aøÂËkÈ\'pE*ªÑ°=wl™AWsÙÐÖZb¼ç¨´Ì ÐYVÅó4xEZ°î6Í}£ z8Ó#Þ1ÜÎKï3œo›ˆ9L‚HøIßO–i³£ªâé\T‡ Z"©Á€º¿ŽXÚåþyR:JÂpà»s+³çõõw[G7¶$ß’Ï™f1µbé0w(%åac‹døMÛ)a{©Q"lÏAóøˆWÄby*"Ì‚Î,·t)°q©_]›i™Û|©‰w¬ýü÷î^=;ìü÷‡e½ßýN) Çer„ÒÔÓeª jñRÃqÀ”,««¶íqj†i¾ká§ýi9ˆ € +©+¹´·Et ˜÷»®Î?ÀU%]"Ïp—NòÚñ×uJw×(b#4?I'5ø)Â3 ×zKa!ùØfLûÕ9Íôo +(î§íÇZ–†œ8ÿìš­ìy[^H~EO¶=ý:—–G˜÷‡ÙÖÅqì$]f*Âx +5æèˆ¡!B™ƒ¨+âj½™çõŒý¹qˆØ$¬àtíÊÑ3÷mF„‘’šã s!®«‹¹™Îµ/ºË1Ñn‡ëÉPdÀ¤,üº‘k\&¤•‚çQÛüÆ•&»”†mÒî£O* ·}mA|Û^$*ˆ”åÛÁžì¡rÛWjWøñG$”NYèÁ4¬P:Õ Üç° +ãxÁUˆ ·1 +yøïÐÃ-Ù»6·R—ûûéÑŽv/&8fxP`n2áí_ IlðŠ=Öª&­©ÛÔ)ƒFFœj·RQHEoñÁG¶‘h¥sV0Ox¤aÖip.‡Ê[Èž¤g^™ÏŠ[¥Q ˜.Áïv¤cÅ9Aw§X)FzmÄ>Ô€È_WºˆÉÝ÷Çe!÷Q*ß.Ú5 ZN`êÔ´ãÔ'ì ¸9ùÝeâT=Î;G0íhsjsß»»=Vÿ¢bà(£¯ïxO™X ÉÃÎ SSüÚÙOLÌV,ø0zthþ<ÌV! yljçæY¿Óú1¼ƒ²ÿîËeVœ±§JZ8Å ¹M¬ÆÓO¤cÊažÊ†z 3+æµG6V= /Öyë=—nÊz°B ÒMwI·ÃÙÆÃÜýî&’ýéwÌQÒ]l¯c/ÈÖÐGÍõŠ2ÚîêÓ1°¾+s²9bY´!K…Y±‘µo Ÿï*Ñ>·1kì”MŽ´]ê$É8ËÆ—Ä¢0›r¼HÓ»s sLO[öc(=喷Єz“΄z¤áÓd,p ZùªÑ9©9uÒÊ¥µ»­Fu®$úŽŽ©|e¤OˆéEV:wƒóŸëÚ!¯ÄtA€Û€føq$ü¼~Jú +×ÃßGDãô-2ëàaM̾§O:ŘkÜwô÷&´»­ +ׯÇÀ­YåÔþmë1¡–Ý>Õå-›æaûœ0R<>®‘ªž†JÂÊÛ£HÊ×ÐǶ­uxhŽZ¦uVØÏêÕ–¢zf újffd?ºð鯳™f1>Û•-$ØMX~Iƒø©«6»cÓ~>Ñ÷ßÔŒ¢ ²eòº*Ì7¸4JgM¥V2]n8޾t1~×tó1pT©ÔórG2ê„|É¿t˜P¥˜€f¤9â–¼°7X0PˆébDöZ™ƒPÚtæÍ ƒ‘pM"°xOÖŸØŽÑÖã7ScRØÖ9_ÁÍ]å:aÕûÛŠâJÐx8¢*¬[»'»JIk.Ý#"|»IŠ-j4¬]«™gÊ£º°«Uïò^]7×#Å¢âýž1®×ûÔÌÂ…ÞÝ:˜LLšö©ÒÑ4ÄÜù}1…åvÁ¥}Ï›™‰ŸÕ.xXV¤.êû…5ŒùH¥òø†m—Íš~ƒâ¹¾|Y½C÷°yñ ­B«Õ唥9|Ão1sC³Ã.³Œ +e¤7$» \b¢`Sˆ‚fW¦½ÜÍÛÖÚž7»ÏK‹Ñ¿W®Å]zØÒ-ñräÛU#AÞà`0ʹ<¶¸ˆ6ýj^¤Mä6*7„ÅfõÖm%*¡ÒÝ|€oæí‡Ÿ†Æ4‘(¥,ÆLŸG„Ù¢¢>¯ò“0(—Ûÿ±bY}ý³¥â+p鈃­žd4a41\ ÞunÐüÕÈB›éx—âQ‡Ø $2<’LÆÀ¿®¯Á¥nÕ'‘Œ‘ðe"Ùé ) ¬ _¶€¦ŠõðOf ×ûmúÕ Ý’Ÿ¸¶˜B i2 ùèÂË.dÎÛEÅÞWˆ8»~ö+÷ÙÐ…§§‚‰'Xº¤Ýn$ê´zONxØœ+7úÀØY°A¸0#­2¬Z?»ËŒr•Oy|¼ÀÉnðN£bÙvaÔA4_ÍC ¼šmìD¯%e*o<°p8…a› úͯîAÖ˜¼0Ü Bòv4èc&ìÕ áÝ:ç,XºsçGÂ%°¿ ²R¨ƒ­mq‡ŸYà?«ªß51ú&{ã^9@*?‰À¼•G†´j@ðë#PãÆÓ*T>@öÙ< - ¦Î²9X¢W©Ä¢Pïá£ýÐZF$†Ì ^⥻ íW_é]U¶­]îj¸Ôá¦OãRÞä w®é5ä8ÝÝIç_üŽš{ŸÈ3•b4ØZW +×eÍ„ÒÝjùZç„PNJ xó•@/¦Œ¤8¹Õëz-¡tOž- àySÈ]Ü/2Ž&ƒ—±ŸsƒŸ#" s ;Ë{“Í>¿¹ žEOŽ Vµ„Ô£†Gìc/‚¥|åæí C^ü‰ÈÝn®˜€%˜ö–›¸ßwž^ùJþ)_â×ÝÂr¹É£Ž0!,Ç9œfœö€-ºVâ1ÆFlJrùÎp6–æ›*Fc*¶ÜÚgœrCBšèi3£9îO@‚J¨ã&bª¡ª¹’ ˜[Ñ/.× òýc”D–#ô•)]_˜éµh€Ññ½˜Ot­Á’1|úýø\ÊÏ+ì‘Õ™/(!Æ?úöÔMD}Y$1ŸáwÒÏjn„~‹,mw8âc°&s(MdçŽî-ì̦”îÒü†Jˆ6xàØ´L/LŸA)‰޷ǵ*™¤=mŽÒ`kT»¬ö¶@,¢ÐXgabN´0‡ð #¹/ |;m£¬×õAi5hÕº8‹'T†7µµUU /W•þîhe9GÔ Cº¾]9æþYNtÔÇt>“%yÂÈ o63¨¥!—~á©åÅïÄ6©µ¸h1ª¶Íö +/çÓ³³ l¢‚N^öb]Ó„kYù•8Ø!$!€íÃòKIDÖ{íü9ó4•µÙ¥óOùsÄ/ŒÇ•·k„­â°°Ëþùê¨o|1쫬¤6©³xkø‡bÖ +ÍúƒÜ4€Kcq=É LþîR7 ßÎ9‰0ÛêT—< ÖÂR.båF¸R·cŠñüs +é-zZEp8(<ŸOʯp¥‹ýpu‚PÖ¨Úâ¼æ$@›8I®Ãê¡k%Yµ iâ7£ŒµãÈ‚º=Œ_œñ:y>R¼G7o¼  Xæs%Ù‘j²Œ`Ý%K‰(± ÏWa~ËpmañžÃ8"\R_ ˜— l Çš†Ìó:ò:V$?^#†­´ zÀ¹`úáiðΫ…ÐS5èjˆŒ‰ÎbÍ +,½rDz i“ë%ŽÏŒTþè²!Mwpˆ[¤ÄÉ_CƒàŒ¹dŸî+ÐZ_ìõèž>µ¯è®Íb)¢7ÑÂë§Ò"h÷òütÒ¦‹l\VRâ%åmY.Wb ›í'ÌR&õs ÷Ü ]ºå•:ü®ÊØ$PÎÈŒ}®„ŠÆ£Å6"köG)ÿZæŸ;n,¨ôåö©çÑS3Ìqÿ(ë:8Œ@6XIh!¼º¯8UžÂˆ“k0Ž`ðùU¿‡õË”K®ü/º^ÿ€r>ó2+Np¢ µgZujúw±/~u›Þ„ãJ_Áú ÿiwŠ ]Î W2›Œ¤UûK‚¸qŠƒè6xU<;ÉVPŠ~§ë÷ò+!ô/ïÆÁDÉlî¨!v¬M>ø>gê>$Œ˪ò¶Èú̉êôpôZÈÕçˆãâ©rwo› +ºcÜŠ˜¨-íŠ4Û÷YI´ßüai¸û))ƒ§ž;k¿Á¥fçŸ1-b–°§Ïs„úÛ/÷Kx*âŒ%–÷ÎjÐ["$•aKôpMD±¯•ÛÛaêa–Ϫð/ ¡ÓûÑJay¿Yf—Œoo±¹F›N‹ÌÄÐ %ÄwsÏ;ÅåíÔO²T‰®(|±ôˆÿbLá°Y ^[8õ¾*+£K 7rÞš’2Çú­Q°Ù ú:¾Eû¢1¸€MÝJãåT^p¾fmûÙ—T¼(#–?bé=ÍÁK42vÍ¢2¯‚‹ô2 j®; +ÐÂFçOÏ„YBq¸–%¡UÔ§_"&Nô”20Þ\»AÁ1úY@¯«xNKd C”Ü߇P1‹nN!ŸèPWIeSË­Â0½L«þЦڠjõ˜¡ÚŒ«ý±džI‰™á‡h‰¹-ͳ²1u#ò +y_;¶§Í\:Ñ/D êúÿt»JqìÅ{0íýÔto–•Fç#çã-.P ]Câ¢ß¦¥–%`ðMü`qè¤úñ9¾ŠÌì§ïMX‰„†Ëó;D•f¢†^àç‚pûe +ªÅÉàOF0=æ1{ÛbÁ÷—†mMÿ°¬ÕJ%¦åEbHlQø¾ì˜n÷o•dh±û~·‘«F:ôŒ/枀m\–äø\Ã!E¢MþY€ã,”m”S»ïdtjŠõ\/ºä­³è•ÍÏ µ(œJ× šBá}¯´6-$ÌŽ–9Ó•j錪ãÇ—¦B©}sˇ!P¶Õ¯Â½¿;N ãÒF ñ½ï˜GÆ‚¾TE—‹ ÷$˜ ˆµ/tª|z©(•Ƈè2J ÌO [ù­XŠšüîï±VS>åb†Þ÷«‰p¡½€ aÚ"ž”¦I£3ík*‡8?]0w¼ä`} ºMþŸ_Í\HËCûùs +É÷`éÅ€#I°Q’¾qùŽxHÁ¤µŽ¡©m†µ¼¡¥$ÔDîŽ$W\Ž…|Î_ Þ°ýç‡EÝfè£þ©_å-ç¡;«j‹Þ¨ ÏJØeçñº`ýt,âûÏ:05 g©âš4)xˆ¤ñ/CH»nâT²†ßÈ8Ùñڮȹ~ÂÀ*ÉôÌ÷ãOR*{½PÇÃãv>˜ø<¯êUžDÌ$qóâíaÁi”k㢠ŸyÝò0¾•Âé±¼ÌG›(éŠó:;­‰Ï­rI;^º1ø°W‰À(]¸4Í|êmìW¾ëýªö +…šU¤w%ȆÒò×öº÷üêȉýã Uûå<1å‚W†#©qL6Lír?r×{NÑ gÞ1s%ñægÁÙ@O0œ\⼎Žý1ò1­6?Ñ^J“¡ dÃšÐæ9œÃÌò×}ö¼(ôèw#M>5K˜8§)Ú9V¢Å +ª{»Wi„K»íwµjººj¨é´_f-êevv žA:¹”Õ°†yèìԷ²Ò> dwÁO×â"Afðž3óÏBRJl¼o÷ãŽÙ`o*m¶‹ {*ô’¤OÓÙ¡tršIû¦ô –Ñ&g=H[€ÌûUÏ}`fß>‘ü‰FpºVç©PP t< LôôÿÍc>XOËü +ÍèwÚª‰—HœJ7%¾ª[•†;2 ÃçÒuúË“6ËË ÁÙom!Èe1?6HÅÖW1H GÀýà‘ºHÿÊÔ4AÍdµí:ìØßršH1*GäåO“¸!2Ö°›Šfç|8}ìn!j‰ç¤y¤Û>k"%Ðüùý}£~'sêÓ2çGåaUù€3Öq_ŒÕÓyMåC•C¸'¥ã~ø³ü"²$–Ggâå+"º˜­ÕS‰Êè× jO2¾k®·•)øžs! *d“É}Ì}? ^D6+Ò‡„Eõ°ü: g뽑Êf˜Xo0Y%ÑŸ¹“Á`Hˆ¹#vy´¿îŽ}ÿ8þùÍü‘øtrç[ßÁDÝÛ¸>$Š¤ë”•¾†¸ì}f»÷b®˜P¼ÖÌ_ßÛhÆÈØyƒqWZÝ’ç­ì™´¿AJœ\)ÿ0þž^ÔQè…Ç”mŒ$Ö¸7¤ãg½xÓîg8¸”NÄΜ·¨®Ü·¡ë %^4†ZSa ^úV“àP¡+@Õ(²GCµ°¦(Æs^-ÿX{k@Xª4´¶Ó÷ÊFé9ÅlÛÜ5 ‚ÃUÇ£Nø™[ãÿ(pU +endstream +endobj +710 0 obj << +/Type /FontDescriptor +/FontName /CIYFZS+NimbusSanL-BoldCond +/Flags 4 +/FontBBox [-139 -307 822 975] +/Ascent 722 +/CapHeight 722 +/Descent -217 +/ItalicAngle 0 +/StemV 114 +/XHeight 532 +/CharSet (/A/C/D/E/F/L/N/O/P/R/S/T/V/a/b/c/d/e/eight/f/five/four/g/h/i/l/m/n/nine/o/one/p/parenleft/parenright/period/q/r/s/seven/six/t/three/two/u/v/w/x/y/zero) +/FontFile 709 0 R +>> endobj +711 0 obj << +/Length1 1625 +/Length2 5831 +/Length3 0 +/Length 6655 +/Filter /FlateDecode +>> +stream +xÚ­TeX”í¶¦étˆ¡chn ¤Trfˆ™afèPJAR‘nD@:$¤;¤”¤»AZäŒ~gï}®ïì_çì3×û¬{­{Ý+žÈah,¬j´ƒj!Xa1ЀÜÕÎc Fè «!]ìu°`"ÕÑP0ŽDh€±Ð;s¨=@ +ˆ‹ÄäääÈu$Ê w„a|¦Ìù…þeùí°óþ‚‹ÄÀ܇Ô‰r…"°8Šÿs 1 +À ¸  ~ßð‘Ž6€OÛÀ  E@Ѹ" Ýí\à€>E` ü$àò×A"ìá¿KÈà¸T10ƒ‚Bà¸0¨Šú PP´+ƒÁ}à€#ŒÀâz€Eàˆ‹»ýo8»ò ‰ópÅa82C$‹ á(,—ÕPCë/Xû;7ŽƒHœ§=âþ»¤?އbÁp€…za粃ìá” Ø—G†BÃÿÈpÇÀŽÿR @CÁh{(ƒ£ÁqÿîοêüêÁ(”‹÷Ÿhä¯j€c1Pr1q\N—ÛŽ ý½,:$@ ô—ÝÞõÌŠþÓ ¾ß;öG"\¼öPrQ$—À÷›²ÈnÈÿÿGüïÿo¸ŸÑÿ¸Äÿßûüwj-w°+nþzd¸WÐü~g¿8ä…€]á.Þÿ&èïŽæÐ¿„þæú;öµ*Â7a1qÐ_f8F îµ7„c!0€Ø׬?vS„=íG@qCýÓO\˜Øß0âŒøÝ}i¹?aÿwí¸9ýQ.jðÈüñ}-Á÷´þñ4Ä­ÖÄü·4ó{Hû~ó¨©!½¾Âb22a @L $“’ðÿ79ÿ‰ýë|ŒEý H €ûÿÇï_'«¿Ñh" HûßKcŒ#ìq{öOÃoâŽFãÆûçêãÊþÇùÏÆC¡^PùÔ"â””šŒ-gÈìаho#ìEåW™äæ<-E¶tžä£©éû` ˆ°×žS»¡vÒEÙ©…ŒµBR)“QûgG–°~î4Üm”Êž­PevFÍu@~8¼0.oÖäZ£TáiÕîšØiîÂìù4|'ÍG.¬Dýh¤2ãϧ¿õBÑø™“|‘1k_B‹,ÆÍ|xć=%ù>SØ›×)5)gË$\ËÌqqr8¶ÄK Œç¸ó,ºc†ñn0e—¢ÏàÖlT¹õW}-‹›ù$YÖ dlÉšÞ½I±áODC<ùÝDgµ]U9ÝYLB³ø9½tÈŸ-SŸ2Ætòä='8n”_ÖUv6³^²‘¿âÄ'åw¦cŒÿä¼Ë–ÄšQûœXœepú=ý;€ˆÛ«šÖÖ @‡]èêÏ5fXô‹\føNäG®J˜Š6Ž=¥4Z,Z˜t^>Œ¸m:[iU—⤪ª÷™}Çj@€—œÌ_T4Â;”¯˜¢íNª˜P®•êROÒü¸.dRïÄ÷€ò4u›Þ¶z™iêM“èv¥°•»ÝêžB=Ðq1nÈ\i§kÑ!O´ä¿÷‚¶÷”˜¿Í@r€^_ï×=’ËÍ÷AoåýÃR2³dà%éé¿ “6UvDå]Îf +Š1«?mýU©>gòæÛÅã"Íî;îý¿ºÛÞrJñ*“ ôùÉgì¤?~láÄçL½3[óÎÑUŸÓ“g¨_›·z²ß&ô~æsŠH§ûøVòÙõk…¨[3‡®5€tÛgÊNäLÆ]yeùÚ‘ èÒÖGôX–\ôê¦`Ö)QlyÇ:ýTR¨ØJ°Î9ýÊS[Çð©Æœû#„­’‚›9å·Ç ™ÆTj½h5Óבt¯óT³”ž¶ƒ +ÕÛnFíLÖˆû¬½ÏþbÝJâ5ËHD·ãú~}lÓåUäÇyO©<¿…ÛzFD~…µ¤¤4ÚVcþ’Gµ¯²¾dwj%ÞXŽÅ›}aö!¬‘Pº;…T¤%Zdj/¥7eµê/Lcx‡ÂY“/å•Xÿú´~äõ3èâæÍ{?ì˱‹/ª"6û¢¶«È\¢I¬ƒw òÙ|Òó)*?‚xëãoZQQžQ‡ÌŸäðD¢‘× a…·„Ú“¿w¶;M55ÅhF|Í;oj.³ûvCº c¼µ¨]šÁthÓɧ¾”ÊOçKê?¡Í=yk¡ å(¡?ÉÕ‚Ë: +¢‰w jÒ—›'€ ~+J¼ÔßlŠ÷uäI[`L»œï6äýB™‹•«3ôŸ ê-ÑØ!(8ßàêºÈcORž Å©GûœêÚuç +ßS>ºu)¥Èò"»‡±†Håé§hºNðXEQÒµ\ªšŸEØ(һДôéá­­¡otΣõˆ™À¥Wý!N<‹G7ŒùÕÕ<^°4m˪†Ë“Þ°Ц 'v±~µ5r³í騤QM_£“ î=@4Ņ먿P”¢‰¸“ÕfæÛ³ûf3ïbMlfÉlõ¬}94#W£î-¦L+Z·ÃÒ‘íåí:!Ë@óNɆ`Õú$AR¯úÔjU_rÁk"Üí}†”™î;¤V VÙëÌ¢“ÚÚŸ›ßïR寧ü ¨ìðð½Ñô`Ùy!ñl9}ÃÛQ¶û‹ Û2ÕŸó7K¡¿.Ï„èL’g¾ÿÒôh“Ÿzgü‚2NýÚõŽWˆ÷s}ª/+Ô¡ÕFãwcAm¿^yjåšÇϬq?"åx¤yƒE6XNïݬóB­'ŒÒ£39% ê<íÁóÝeiìN‘ƒíÚóŽ_´-ÑëSJÉØ¹NÆcæê› I­¹à g3Žè'ÆÐ@IuiA¼Mt„ßÙɆf¥®ó˜{üõwŠšëC>:îêŠÌÃSУNÎʺ•­džÉ*¡!LÄ"굲ʹœã*öÈ>RoP¢ßžôG9‚ùíÂ÷}h†­ø—Q3QÛ\/€&Ùê¯fj'V¯©·¬ù+Í^έÛöÍzÅ4¤F<óÝg¢¯YyçèÊÒ2Í]fû´¯Ò5UMT&‘˜îO'VÃÌØ¸„¥vl¤ÆK®Iú§»¬]G‚O{.( I9Äõ¢Þ÷Ï¿šl5²¤´O눫Üä”y¢sþ¦ýš°Îí°+®Zbº1=Š*·ÌîÓíßaü +ñ˜Õ-Nq±WìW© h·Ý¬¦êõ0J¼¦êc«“[9Ó‘?"ȸH€‡û=꣠)'=Ï_çrc.’šãËÈK¥«ýhàƒ¨ÏPq@Iw®äél;&Xÿ–¢lÒÇ„Œã Â"wý^»2Ê(/ÂüCo +ä¸ÒÒ'I Ì;¼åT¼}9‹9;sÉJK91ÍmçJ^!7ù75t ½œëž÷D¤kg3^i,1²&ˆl׊*/ð,L"'ö(qI9~̬Cäg­®—r6–C(4. ‘ý0 þeê&Ù¦ªñÖ¤›Ìéwç]ÜOîzê<æ•QÎ4Æ+'Ý Ø_„æûÈÔžŽÆ¡ï½zC~Ž 6ü`íGmÕ «¯OnÜ +˜#¼7 Å#(iÎ>Ûbè¯Q/E×8G]¹ûE?›j7TâÍgô LüxE§Ñãrë™ø[™Í^70f¿–pYù*Ýëûözi4Ö&ü™‘}R\ž(QWžÏ"ëÕ¯™´H÷øo+y?O} ÓÎM‘ê¥s¹rçrÙN¦’<ÖæžßîŽ2p;¾'ÓIªÐhDnF·V¡®vI¨5ë§Ä Ìzì#ˆ&Ioäaè7Ò@«¶À³Æ* +^ÏåÅœÓ3VËI;y¶ª“Ë=B«žæKo¶tåŠÏÑœ=ºm¼’\†xÐ¥Pã€á.o¥ŠNÓ¾ðƒ¹ZѱW|ÌçKH°z¥îÚÑ¿,ŠŒd'VŠŠ’§\/˜ð6nó[Ú‘,˜¶d5Ý2~Ÿ[Ô•¯Ý—~¾+\ŒeP0ØRQœ) +“Ù†;ë½´ìóDQnµˆYô·½oÅ4Ø){Wõ@†Îœý €u–Òª,EŠhËREª]g'ˆ[š†ºàÔÖ‹.U÷ÜÄ—ÆjÙ!_ßn›k Î0ë-s\͡۴ +•¨¢2¸?וèƒ7a +ÕX愘®ŸžÇ|l=UøeàM|ЍӛvZ¡{ÖÄ|UŽl†Au/%WÌ͵գNÉRé)9m²´YnÒ˜¥˜\¿´Ó}™b³{g +Íé^zÉ•˜4mã¾Ëax—rÂódà`hbx’Ë >3}²bÎó¼+gê±­l(ù~—âH5µû:Ÿâfm3^À­é…¯Gç —Ü[ÃO–ç^¶Ã8íT<6Ïõ1~/ÊïI›¸yR[2!"Íg¨Š¡½Çîî3¼v<ëú6æ6µh^›ù”"p_¨\[‰·÷|JHSÔ»Îô4Â÷{t£cËä«ek¸ÊæÝ¸ÅÁKÞXMV×õH~ ‡ûµò›ì^l +Ñè`›åŒ­‰?®Ú˜(òa—Í 5Ê¡\ùdmt ëj"ž ypl·¿õ{²í.øÔ¶ß#èñÌáµÓæÇ¬ +ºÛVh€/[ó[,ÎëPuÜØbÅ0¿¤Æ$W¯™¦Öm:èÿ´¬y‘O¥2>ó€ZIï–yË™¢DŽáˆÿP+Ç86‡§lo÷g1¡õ‰†ékáVî9zNšw+EŸ~Ä$½ÕUá“’g5cÝè<JoTyk:ˆ¯_2çÆn4iF} t­¯.è ·ÊøE´ÈÚº^ê~ÞokÀ4ξ8YeݾVÙ@H{yƒOê<ñJ¯5XbLcñfUî‰é|ÈýŒ_ìd„¿Lð³LY*Åá—"imžžIÞ—D2î€}µ>˼†ÜÅ­4úÍ//=Xyr£§‹æ;¼\ŸKê§{_Ïmg@k›”? `g•ÿîÎT¥ÁÂ;Pì+)¯<™1öD$D;¡à˜EÖg}eb·ú‚ ýfÀªy,V¶~ÿ£zkaD•:_µÎ.à¥_ÙM’õ”ˆµ;’¾»>m)òeOÖEƒV#úS´«<€¾ƒ·)ÝhÉ—úÔ´ûIE>%?\'<ëþÂõÁÃ=Þ+c +´;k!±÷eùo±¾¬U†RP‹*Éà'®êxGvz1HJ;±xý¼ +f£„6&að§ +³WŒU¨¹M7úC('dð¦ÎKfrIÍå,Ûæb¶4éþçb=  +Õ:²p,•küáU¿xýÖ•qZŽ>E/kû·&ÍŸYø>m²,*×èvΚVc?ÿUê;Í|y$&pPËnë¹È‰/o TÏR2¶Þ'6$½¯ÞGlýtnÌ~=çS…êZ!×iXr‡?pIðèIïuµ†PÒmërQÒÀ×¹¥;a¯¥Iž-q“©Ù“Òæ,¡*:鯦›Uy¾\§oø’$üùõgVÂÎý5†û®Iq!1i›¶uðC{e +>©åݾugooî¹mYGM¥Ï#¶¼dÛxíÁ ‘Û \û;JEj¼‡Ùj܉K% àn·:î’ÔŸú×ØÌ ®Š  ¾]Þûj—.¨%—¶« ­I¤ç›{œkéî¿czút‚Y×ߢTÈ·ïbÙ«ó5!a€Ä­bŽ…Ç1%Q¦×3ecs6¢CHC„ÎÅï5ž!ɹød6üÒ:™Ü¨Öо +¿{žgdõ͸ fÊá)3÷¯oÚÐdyí¹Çù¹­(ZKF¡‘‡½E€ëW€ÊÄUåzïÃÛdçƒw,Üóçœ×ËÂWCìV‚™•íÛ)Ÿ-z?n¼¬3øl, >~:¾mÿ`¾0:Àf&•>¡ÚÕ8 l% ÷å-2Ѩ+uÍ÷r’aÙ»Xà1h°ž­õícòÿ&\uèÑ£ðbŒþ6—Ívq|š_÷fœ\â)õŒkíý!á ÷j0ƒŸik4I¸ï8OÆÝÉFgsNLÇ/elŽßäÓhÿçcÍy&…M´/¶>­~®é)5aÏÑÖ C! Ë´7ŸqˆÔÖJ"CErßeQ;[&¿»qwEã;3Äõ(Ä׺S8 ‡'³®½G7“=fùgú˜ºéIT9®ÿÕ‹_ÊI·˜<µzEoE9p$rÇ×Ãê~xÏ-"*>b8OJqÍ;ú¯1ãœ1Øy]iyælÒN…z!¢W( ž•øÂc)³ôš¬}a¯}ƒ³¾Ouo •DPey/¦sûÜ”66æV‹ ²ÚTT9_1‰Æ¦ ‰0mÈL%xTø/WÎ44þœÃñ¹€dòö¶¾£³ðéš_›cÖêcXšÐ@›(µ‚ϧÀÊ…´¥Û€ö¸Ì)Îó¸Ì¦C×tå©o0Jª&øn¬ÍGß" ;ÖGŽ0fwÆo‹Ù-ÖèÝJÈÕÇÃu5e®ð‡è‰áTzýŽZã]MK +,¬‘Äm1ø`q%nø© b¡@öÓ»ˆd!•0øåCËÙÀa§B‰*çcø¼ ¬(yãŠýüD‰z9X>\8 ÚVàFŽ·è닎“qiÍ«\ì#cR&­€s>>×ã*Wkòù´qM~¡Æl{”÷è7v+NIÁö-ÓžŽkÙæ¯l4íÈœ ÆîsÑC< +á%6×ã^Ïë7FñG5 š¤F%¸¼{Ë f73ÚmíYµûzÊË6uòˆ¬³wXÏU+×¥\—_tãí1ÕÀ¤X§;§N«bË~8zžiNjœ½<âšJ›”z1}W¡iò 5x)@HwÉ6¦ôé‹eš¿bŠvE~X-{(g;µn\990￘ã•ìé¥Yëy¶í’ÙÁ-Êðó +>RÐ/kDpSrdÅìži00'C˜TMvq¢¥5õÖienUI˜+òìNGñ0Ë$ƒúÚ·æqóˆn1M {OÕæ4 ºJîÁB¡qç“ú'°Æf1ʱ\Ú\z*ñ]‚0PfV²F=U>Hí'mEj?)^¨jy†Œ”Iü Nx– +endstream +endobj +712 0 obj << +/Type /FontDescriptor +/FontName /NYWZOF+NimbusSanL-BoldItal +/Flags 4 +/FontBBox [-177 -309 1107 953] +/Ascent 722 +/CapHeight 722 +/Descent -217 +/ItalicAngle -12 +/StemV 145 +/XHeight 532 +/CharSet (/A/comma/eight/four/i/l/one/p/r/two/zero) +/FontFile 711 0 R +>> endobj +713 0 obj << +/Length1 1641 +/Length2 6434 +/Length3 0 +/Length 7268 +/Filter /FlateDecode +>> +stream +xÚ­teXTm×6Ý’ÒˆCwwKƒtw 3 Œ30C#RJwHI)ˆt¨t‡”„¤ˆ„tŠ4Â7zÏs¿Çý½ßŸ÷}~ì}ìkkë\×Z{q°š(ƒN ÜK@DPX }ää2ÂuT0°*ÖöÂhP‚ˆƒC zAp5 D`Ô €¨(@DFF†ˆ ŠððGB]\½ÜfÆ<||ü[~»œüÿ… #QP8€ýá!<Aà^hŠÿq  ðr…œ¡0@ÕÀÐJ[_À­©oЄÀ!Ht†ÞN0(  Aà(ÀÀþ:@èJ¡¿KC ¢¹”Q åAÑa?Äã7Äð€ AQ(ô7Џ p/ôx!P8æ þ-mwFüäD =¡14™!å…!¡^tVC5¿tz¹½~çFAÑ0áŒö#@Þ¿Kúƒ¡iШ +G¼ ~^¿s9A`(ÊôGçF“y ¡dx£ p—¿ð  ƒ Ph4÷ïÛù»NÀ©èáóÿøãõo P/æ,H$"ŠÎ òBçv‰„~Œ6ÜþËööøæAþ¹ îß3Ã#à0âL$¤ðB§pÿϺ,øŸkò Åÿ‘ÿGÚû¿kî?{ô_~âÿíÿüOj oLø=-zÓ º€ß»ð{Ùü ü^9PÐÿ |…ùÿ7áÿt´€ü%ù7ë?±¿¨•á.èÞÈÊüe…¢4 ~°!Ô ä +pÂзöÇn†V„„Aátwÿ\,@@DXø˜©+äÿ݉¿ üOéè†ý.¤£¡n¤«Í÷ÿÛ³¼ ÑóàeêïüßTzð¿¿¹TT~€@q1€€¨Œ4@FD #-ôߤýÃ#ò÷Yè…„úl„……Eè÷¿ž¿Ovÿ Q‡ƒàßd℃Ñ3÷oÃoäD¢[ýg  +ÿ×ùÏôC ~ÑÜ4$î–™åUM›ß7¬fÓÕ!‚ÝáñºÎ´¸0¤Ñœùì›L¹ãuU„`ý¨ìÍÿÏÛ¿Öò~è qµ§Cö ˜‚Øx: )9›¥ø¾?²}'kÇ"6ð`Jw ÇZRØüûò°‘±ý«k¼{£ÍbH‚ƒ3ž6ŸÂ»ì§¤O@µ Ô-äõ”ÕEÛ;œ)›g§\=ƒý}½íG¸kŒ|y „r>8w8cB<ó•¬ÍÊckÚcG:¾Ð¿}¼s1£IëX 2`¶;6 tÜòMÞG>@¤AùXŠ×8E#€Á:¿Ú(ìT寫‰Â„)FyÕ:+o)À +ˆ^þ0®WkàiÀ¹ô°ÑpŸ ½#ëÓ󟉅cÍÔN_EÞžüLjçý8~ç[öúaÓ°m³{ßlKV<Þ;%€ò¨[ËœBõ{ézoǰó*JPdÇsãáàÙ5»§(_m×ûfÉL*f„wÊ„˜›¶o:`Öbˆ¶iì}3+ÎÆÈ[}µÒÝÓ$¶YAìÉ_8qC#_-ãYm|«t¢ïÑ à;f´-ÿ¬Â¥8Ä•½Ü;Eº(Ù'Œ.*´ò +]æ¤Oª ]%x¹~v¥Ø ÖX#î`ë”ïwrÒs Œ7§¹9i'C^æ‘J>Ì)è¤å 'ÿšØGxó§q²D±BÏÑo·q–å[q2ZÎÊs× pßbLbRH¼áGÕÇÔ[>>÷¾ñ\‹Õ§O¶OGM›áíHz­Åœ®ðLî×'òFŠ¿%1?É~ö¦·&xT$?seš»ÔWºIaØægyâOü•í' P‡C‰>`¾ùLtÇ3›!DX<”ï4‹#ȵӆ OqßM·$¾äª^=#µ Z!qz×^w%;cOª7—6Ýn©g_UšPùÙU#”Õ÷š ªü²åðS¾™1)#“xL¹*‡ÿpQ)r<અ¶LÁó¸h’Åðn* ñõ.އwé:³ /8}>cÎEÛù"89”àÀqŽÓ¼`eÌÇó{틳sÝ,î¶ÆŒ§|÷͸hê]¤Ñ6>µÛk>ºsB7¡ +…ºèéú7œä­hez–Sã¸Tôé9M 9ÏöéÓá|s·¥pÙþæ5ÕÅÙÔOíÛí1‹:5CjÿÁÖuö‘“5*—Ì×÷¤îb®8ƒ³ ¤;$Y¢4#bn»»>WïÚ†°e°òr²B5Q‚ÏËÀ ú»Iw©t®ÈÇG¾$0%ɇɈ +y®fÇ[çˆ:+#׈…=J½èô®¼h•P_‰ËÍŸÆëQÈž(„L òާ?)MïHOÞÂõÃü¡Z'ÑPç©+BÃ!¥t&Ã1ëdl[²ž®œûÉB"ù"?D’}¯džlæÞ–)×:c¶ –J<°Ú¯Å¾›ª‡‡ÁÓY¤ÉÈîø&«"`þS2?ãö›¹:©ôh¬ë—äùÉ„¾qÒ(܇‚Ä^?X¶´Kî¬qJ;¸*äq‹-žž¯Úë_d™¬¤h5¾æÁ¿ +”2Ò÷«aˆ¸X¸yà¾Y¬Q«þS?UwV#Êòõ9ïQ®áØÑÀú˨f`§R›ƒñ–uø£5É6ÙÀÇQ³ÆÇ‘œ·b¡ÌÔ¼û†Ã|ÝP•ЏtôÃŒ¸¥-PÓ N—ãSêc˜ -Šô[Ó*†ÎÈ!o­:`âÄè²Ò>šPI)à,v™z¦¹Œürg=£\€Nåqc¤j–#M:˜øa“FYçp¬@5†šâÌQâ<ì c‰÷µí³Ù›¥žµÁMä0b®`á3^5÷ApN®¾ÖÞ8¹´\†RŠ*ÐÚŽî—ø†¶ +¢pè~ ûœ©»eÞüóŸw³V7ù줯~¨Ï4È„²"6sKµ.~íö9êiÅQóAµevÆhà÷¶üˆŒJOϵn‡ Ôðø2î[×4•›9¥ºGÆ%µqzgAÓ£uNÜý¿ŒÜ²W>Mà\¥_’øº;8rm+}†»ƒïDK©Fp©ëÌÜ3äÅ!©Ÿ©¼ßsž\x˜\´f+ÙÚÔµŸ*á|Aûnµ¯qÖá]¾tˆ,4i¬÷ízè$(ŽZfêÃÞä%¢bpñ~­3+®Ø/;Vz;ªiŽ !=]¥÷ŒÍÙèÎÊJ6aÌpqTL¼Æ |ê\ôb–"ðØõ½x ‚¸:29-ëå9£j¯í³¢*?ÃëuàÅ„Y–Ú•ú£4Z^Ž»c$Í-FM\éwá*Hê~¹ý¤O£5\Ý¿ì°Ê†oäÛ°WU“ É+ÒÇx™ÙÄþ²§\±9c4/Ülêå?=.hüƒOAûefyV©RèëØIÕŠ«öõd±KæÉ…w¡Ÿ&mËúÚ§FW«@Ŷ£ŸVC®•~+ÅHtNAö+HÔ6•á€Ñâ‚ÁªæÈbá(Œ~âCØöjÉ›)ÙùýÄãU{†v ’å!lûÚÍÁ¬Êsž”NÏWÄLYF³ÅÅGCâj¾3¯Œ€R."Å¥Œ§æ‚£Q–pìÁƒ]$ÜξQÜÓØ¨&¿IÂ@{÷ôÝ¢ä@bÂï*œ8ñùÖǦãU•Wጠ+Æ8*’óiÇþ<ûfÕ¢%W7VIM]fn[y±ùsk‡l5l +7<ð¥V>&‘ÓgÞ\p±Ösõý ñ'oÜÙ¦Ô#O…q&àDBÝr7¯gýA?›zõ¿±£<çà”ªdš”w~w'f +¸g6¨¿Ðlm—¾‘X·~ oŠÿ’·éÂÐ…nyÎ|™CÛ£ßãëObí}@ ¥ÙhÑY¡ß›;o¿_¸àëG(ù%)!bñiòÇRåÒ4|Íâ'ëÑkç·çz­í^]•sß,ƒ¸Rm? kZoꆜ|€¼,³º=±Ûÿ¹ +þ¤̫ͮsyÉ6“™–JE—6ú>nÃSI)†zaÑoŒ{õÕú±yj~ò³‡7×¾mJkÜóõQâP®(t±¯1€<ÍCN—>0ÞÉÛ‘×_²§øHžySñï]æQâ&F1‘ªV®îËWÒ²Ðôûµq„’-s4t=cbÁ\0K¢ªõÔËJ9´9zæWc¯rÝgÎI–¢ZÓQåb Ùò増¦—åÁ¼)¬ê}ˆà}Ž]¶ïKXE~ Éêæ¬Q°@Rö3Ð ]ÐL¥qÔ!`Û¾a´:ÞÇ”RSX¥Üü^Üë™ÌGdïoƒ"¶æÂUTžb”ÍÝþ¹ŠE³\I~ò'£lF'ïžÜ« ÁïztÅ{‡E#BzúÒ-yâK}~X&”Ur ÐmÇ[Ñòkú}ˆ>¥´s×=Jfö½ÛeéW+9‰¬‹"–/ß2j"ïÚÖß”XxÉ»Z½DÂx¦àŸOG´ûf€üeæ†<x[ +]·}üˆfÛ»¥en¿Ñ3fgÖÜVªDðxXûn—ÔãÖ¯ç'QзÙmF¦íÕæÛLcI&ÆrH}Ln‰oL“w„8ËþK,n/ðˆîB­-8È Ân4·Xeu0Ǹâ2wöû\TÚÁ@jÓöxÎ2rÞ¹õòì‹,Ú‚D!“5;kÇRE£‘#v6ÑàÜbáu­RèÒ÷ÄBNÜ”E+Êr™8Æ”o§ýí B°¢G~D§S~éä›-n¸WXáP©‘jñ2ågN<¦&Aê$Õíð‡ÕåÙ2xØ÷Z¨w\ûr¤ME%RýŒæ#oÍçuäJØÑKáZÏFi§‰»]8RöŽ{VæS†ÃXÍ»Rx”ñ¶pé>ˆÁ’Ÿ1Ó^™báGïõþD4È•p¼N—S.F¢ôˆeý*ìT­¹o ¶ªä’5bLØÕ5嚢uMH2ü 2÷ÿ/GÊCU”ÜET»ü¹Z63át P¬Žiã úÆçˆ)êKŸÓúôË«MþU¼FxƒG2޼Y©)~­D|¥dúþ¤Ò^ª +1çE¡»£7Wc™ïå§÷âõìPߥ¤>#&I›I~ÀömP0¸Ø´|ÏIlË/ˆ©ö46Æ;Àµ½Wv)áÙÌÏð‡ ÅÊúÇr,…C~H¥zb';/ºÒä±[ËJ¦OG<=K<µBϬžuãáÆÏˆ³\ÌH/Ì|˜ÓÎÇi™¬¹:éˆ$Hp”Ú¹Å~,½¯-ù) ª²6ÝCôTµ«˜[Þq û ˬ¹Ð³øÀ—û†«·,W¿ž«ˆ¸Éãi +A½Œ$“íÆOVÝ¢q·Ûïi^ôجìUX’aàÚó¼"0q1ÓÅWÑ›.±ºøº£Xà¹õ¤Pêkc ær¯öYôå;A0M$È/•{>˜H’ºÒSúd1ûÑ`ʇ+©åÑ­ñøÃC‡„÷7CWßãØôÇ6ë#FñÎï9Ê–.÷0}ŸŠ»³úŠ’3þ;»­šÒØeŽg4fƒbO‹¤9&Ïj¹õÚeô ïAOü—KkLœÚ[OäðKU@þ”þk­L¾Q¼ƒvƒÇ¬,^'¦ RöWàÍPÉ0¨¡åMÄñIà]y¼>^T°]êU‰hF¸î 9û]ÇeB½—2ÃÓŒÖòèL +"óžæ“>-°ÛâÛgmÏýÙ½Ç|ÏË[»9‹»%>ì,RD5\¤ÈÛó¡„„Ÿç–ÁäGž+YQ?&`þTf-µ q:)Ía—v?‰1:Ë ò˜Ø°·N¯3o;¾žx¡®<àö¼Á¬ C]÷øAf¹£ÈiúSÑéúî&ÝLsPÕ.`Åý¼S¬› ™Á]”…¥Ìaë¡/£€„haïhˆ\B-zxÒ!Òzº>ÅT·ƒpïΕËÝ´?—Çô‹†öćêf¬ ³’`é5(64k¦iíØ(Ñ‘? ìÝ.å,úºáªjåm§°X}×Y?¢&Y JŒ7h:/2©dH³3{ úVÓņå±Qn2^aéÓáùÒÓg‚\K¤k~„ÚÂä“Ýnÿ +îŒÍz0Bç^y+Q¡HH¸\'çÎË\ã”Tü½w£Ãj3á2ƒñ¨T¡6«"Íeô0é SGntÑØ{«5aÖ<'œ7å†f‚þ >,cжsŽ IÇVüö4›¨š w“'|¿œ{ü£®ŠWåbñãT­Ã6ÍJÒ”çQñé47Á£&±<Û_¨PÝME×ï\Ú®!MsoÞ¿b|A­y4z—’£ šÎ<Ï]"Á¯ëZž“9ÆP¬êª‹Ka5ÛD–<‚T™ëùaQs’±Œvg“Òöò=ŽJÔÆÂj·…P^/%“KÏœ+mZ3é…Å"«ì1=s’š}Že1y§¶Ô–{n{q€õXšÇ52ŸÎJ® ¶ŸU6žß 2„.>ªãu\º’sn–›¬Ò•lb°,ÃÄmëÀÓ‡÷Óâ9{_|M5V[mVgȪ¥Ø/gɼIã?„ÜÒçA®W޲,ªðóŸø»¾¢oQQòÝ—€žô­‡wá<j²÷Ò¾ËåÍø‚º]€éD.¢Ëzº…TWÁ³Á<ãm'þFE‰®·$³6Æx,ÀÏM:`bŽ:FáùF©Qrz¦Í<èÈÙÿ¬¾å‰Õë¸ü¯“¬EU)R÷‚Ýò`î3ä3/Pè7X¹Á8šÅý¦úX{긛B…DÝ6ªä3(|7n¾ÿ#¬¥ÚÿNJu)¡ ­ÛØ@o1ö½vÆ€üp"é5WæÇÓb¸îýAie4'*IÖ×»´~ +jÃÙƒ%k²¼(Nâ¸Tüå• Bˆ ƒ—äˆ-Œ1ôQ~3ʯ±ÅŒØ_8ÏÛã†(MB‚&jL˜FÊÝÀÈJ-!ËèRÙh1²ð¯g¯Ïäm¶r75ãnõ°†¦™JVH™®qúëo’½J„ïÊiE=Ú:`b¯ Õ¥³:Û ¸÷;ê…K‰ìŠã~Zã“pSá·µvÄ?ºx”¹It2@BÚNÎ<ËÄàc²ºžÇÏ0,H× ‹(áÌU%e®øR?Ù;Ü’ÎÌ"x†U]ž„HúvaßN¦œ&°ª0'/Çâò/ötc¹ðˆll DÑMy ݜڶ*6~}YôäÎSìûJ»ñFl—m3q¹þ„¸¶‘G½ñ‰Ó–„áë ‘˜ý,á'ûƒÚ]» +sܦ©´çÐqòS≾\>ûµ ;.­wå+ŽS…Ÿq¥øí5™¶CåH?÷í]~¤¸7úƒï×.%¶‹³N©«=‚]è u^€§ŸÊÁ€¶`‰Õr‹ÙÚžlQ×ÕûîniI8‡6gÃè§.µÚƒ•n=ç³ï\šjª-BšíçÜÓñgé¿àuÄ.^8òÉàÅŒ®4hÆ)Á3AX ^e»½¼Dºo6`¦H gªÖö<ýżÊ2>¨ ˆÜ|MWDÚ»Z1“ Wª^/cö§”j“Å"7YÝJ'7C—|Šô' `’_³¬L%ÑW IJfî䎡i>ÝåæÏ ð !ìö·ó§ìÉ6«óû¾oB¿\źò²nâ¨5—wîrü´6œ8ÎÉé +&È9ü fÙbmaÖ’ÔU3ƒÿ¢‡ÍHL¦"؆žæSðËÖ _£oôCGmZ$í˜Xã+³oO×,m+±…²>±Zà…otÚµ\ó-"§ïkY'º›6ì50ÄÓ–ÓzXÿ`R‘t¾±=&— 5“”´!‹!4óO íÌ~ úÝ©z„ts¹MbŸ×õ‡&Ÿs­|\Nº© ÚܽÅö~³q,iú}މl* ´Ý›ƒ vH÷½ÅÈ]Íâ?¯Ø`ÿvÅt¾ƒ™gqCèF)V™@`GÚÆ8}2:º-iŸ(ºQ÷Œ™„üä$Ÿþ|±7=°`8ùZÒý¶sŠ::Ùg?~'¡6+•1 ˜e$à§ÆÉ Uoõ]±iµOÑXqSQ˜Á"{äVýºØm·JVÍáeȾ“©I»%<‹~d–l~4¼u½µÿñîš&‘ǹ6Š)ÊšsÆ1=-ª=âýX™™ÉpX_i,sj)¦fv<$•<ѹÓBSFä´¬¥¡_Gà}øÙß Sþ1T¹ŸÍ$ô\ß·X «ß€š8¹[•6„ê¹¥-ßÁ9°»Œð[}ªëñó‡7sMÛ¬ašÍ~ù2ö)x{] úÔ˜{Mr–Ôµþ‡‡‘¸w>‡=æ6‘$.x%®T~¢AL¡¶s{8Dµ/ã]ÑVó‹ÔÁ¿Ö0ºÙ¥Í÷ãrÓç䇇j/°·¶Cã@³2ðê62Ëu|7TýV×b#b¶ªƒVWõ›þã/ÆKª»/Ú©Ycâ>›á‘ëZs}WV_Ûb‘ïZQ\Â^ŽÞÈ%Ý=jÞ£¸¶m’‰šIH7fø%ÿĹH.îGâÿÎVD îT´QÆE‚„ø;ñ›jÀæ… å]2"¡I›§ïzëAl\Óα€+ .츪w}gü™îŽ–Ï8‹ó£ÔR)?Uw, ¡IT2P0o²þ:D°;åßøŠÏäÈè°Bp¶Ô 5¶0+L®TI|‰ûÝAk[}¶ÄÜ âd⊱óP6)ÙÏ~µ½Ï²ÉÎЀgšŸ8P&ÏÌsÍæSQÓ h%3LdEý?Í ®Ç +endstream +endobj +714 0 obj << +/Type /FontDescriptor +/FontName /KFEQLI+NimbusSanL-BoldCondItal +/Flags 4 +/FontBBox [-143 -298 913 989] +/Ascent 722 +/CapHeight 722 +/Descent -217 +/ItalicAngle -9 +/StemV 120 +/XHeight 532 +/CharSet (/a/b/c/comma/d/e/f/g/i/k/l/m/n/o/r/s/t/u/v/w) +/FontFile 713 0 R +>> endobj +715 0 obj << +/Length1 1166 +/Length2 4511 +/Length3 0 +/Length 5274 +/Filter /FlateDecode +>> +stream +xÚuVuXT[¿V@i$eé:%†î¡%”˜ÙÀ3ÃÌÐ%5RŠ„€ (R +Š€„t(’Ò]R‚ÞÑsÏ9÷;ç»Ïþc¯õ¾¿ý‹w½ëy6/Ô\TŽr´QHœ¨„XdŒðröÁš;! EÍW”q¢àåµ@à<ÑB8á(¤¦ŽÀ[¸ù€Œœ0 I0H¬–W”‘ ¬ÁR¢0Š (á… +A€ñD ”& +æã qæ>h´'€›X”`A.„Îþ]¤B`®n8€¥™µ °°È߈„‚‚È9àO¤ `®Haá x¢Ð¿*RèHChþ+êâ¤Gà~ pÃáЊââh'€€‰a]ÄN\Ш®òú•KñK3M€† +ÿ§nH”2è_°  ÿ=Ü-n‰DxûzšÿL€(þÆ\H, VK‚oàsÿUÒ" ü&%~ÁNHxH…¹8yb„ @xQa|ã„ý_â?w 8†9®„cø;;\þØ9á0X –=­nŽBzünìä€ÄõnYèj ÿsö¿¢ !¥¨„œ4HTR^†àBF©füK‹?uøBÿÛ'øï”zHHáq:þ9’/€Á¼ ømcAÐæ7Fá0$ð·uìÁ2`‚k/‰ÿj©ÿàÿ«±þYCÛÇÓó·*È"è‚~)âé„ùW¸“Â3à¿|ðÏ@kà÷ÿ?yôpNž˜:ÒÕó/™Xm„?‡"p0·?ìò§Êðß÷€¢°ˆ_7$*!#ñΠó@X,á,~Sþ’ZH +Ž@º‚ÌqW:aà¿h˜Cç÷¾ýsï‚ 4þŒblSŠrõö¨RÍOt±_ªUÖòà§§4E‚çùy1¢cfglÒ¿É?ÈÑ„öº©”ÛŸÇ'³i%Èùy(@ÄHé¢é‰tcY7Ī”©vÈ>|·²¦ÜeNÏ]ÕèÐÝæz~`ë¢ÑGoŽG1†qÙ.¯x›\d»ú¼ ŒÜdeDPé$bËD×3ÔTñâPw£&Ø=âN:¥~ÓëÇüú¶”¯7Êè‡GÚ Ô2aCx +ÜËg6›grŠ}M’'n%õ.'•Ýè}©›è ‘öPüëQ·åWwÇÞ +{„Ò]¼ßþ4Á“op–Öä"}¾–J$z…䤸5 „^Ùü ­Ø½ Œ/²mÄO®æF)ì¥u=¤zn;×M +NuÜI/¹ÓÀøŒtªL«53.ùI+„~ÔxÐ&•Ht¾£òÀ¬Ræ,èØ ì‡Ã–sºŸ­îÙ +dT;£«ÕRTt.ŸÅ"‚Tl¾5 ç— ¸€y¬ŸÏɱ!Áæúx’2¼ ñîߟR²Ù"3K(¬&9GW +²ÛLuxv+RÝ`y*þBŒ|üÐ*™DV›EqL”ÇmOËóüÀ ½lÙ¡±ì€A*oöDþ6‡SÙýüZȳX2–A*›µhöÚG±]wNÏ…Å|3¶{gý™Õá-‘jgëàõ±c±§,‹à-Ú[›),­TxнíÈpx“?3·ø#”7æXõ†Š±8rX+4¹–¨RÜtØ —²’²tg¿8Ÿ¬Ç¡Ÿ*WéDGBl\Ù\ôzßY¯ÕÏ%Ù‰‹qGÈS?!q¬ã´ëMIú–„NËùŒî~Aß.Ó Õ/È õ¦Fê2ÌFÓ&÷/jT7gÍ®ÊAÖ2Þô¼'?m´¹µ1¤Ý Ù*"¢; yK×ϱl¢ +í(Á…¾,©z/ÚØ-ÛmA57‘"©${`‘=‘^¼3É~Ö{-¨NmA]Ôö°dÜšlÚ}¿×"¨Ïú:\w’¼)l÷ã ²çBå ©™…ª.Qtð/vE®ì‹&dv%¨óèˆs±'ÕãŒB¯wðm6 AÌ–z,©–KÐs§†»ÊF„0$š>g +çñd²˜¡—X #+£ÁÖÏ6²—y)Ît~+p,Tª2s{ŸLoï£56œkÊ¿S–¦_äµ:Pˆ¯Èé‰h¦ÕÁiT2ÔŠ‡xä;õ˜DÊü©8X¶ÀLñZ|“cÒè—€ÎWSkºZGNÑWBX=+»€¢šg}%“/~¸.…»~ûˆ®œ\ž²ê#äq·n¾Ÿšt¶çõy9Es3ï§Y1øÒcl¬V­‹ KK}ªnôs¶0¡ª+ÞO˜øö“…÷½ÜÚ?¬%Û/x’FöŸ=ä(6ÔÐyÜÜQýC:{¦JŸ²Ø:þ+oLp|Á7æÀsfåny‘=âZë'gRÍjjó›E4ùJ‡Ît}xû×4HëidsÍî ½õwë•"Rj‘Y8u¶ }©èqâ[V®\{ü°> Àø‚õعèÏÍ(*†³xUô—¼~v/ô=òÏ‹J½¶F×4ÖI»štÊD¾ß§˜Ô¥·À.Ÿ j 6ë-ÎkÅ唲°%’ŸÊ{™ô«ÅSGsÄÆÕoˆÈ2s´£²ÎÇ$Ý.Ü[ªHHK-Û^gò2x›D铤±ð‘r;õËõ¬—LlZ©1¡î%b?ùÞô½ÊwÈ ’qYÝ3ËL©‹¨Œ§­¦fY’jqõž_‘ÉõÅ`—$@fÀŒŽ¾ÃÖ7øfðî\ÂV­jWø9÷©ÍÑL“ÝÚÛ¦ ©w'œÎlì¦òIA¹å¢L µþ=™5}þ{Ó>Wú š?’¹íĺhy?º zÃ@4±úøV"u®ªZ²Œ±• Ž~Yø`šüö”д}éŒTc¸k¥Ø5f%yYìkßÈLæ»™Vx.ÃÈñhY³¡­©•fÃÖ—ëÒŒÚ@ñXŽçþ×4ꈜ‘-#ïÍï)F°âæÝ\Xv“³Ñ`o>î`åúYn º$íT§æI³«¬jsÏÒaç`}wN^ s]šY. ,NÄvZc_ëf)”Œ)ûÄ\¯%UŸ¿‘¤'ÙnÀ¯,é ¯|$oKuA“Ýæg[Hܶï些ˆÝ`ri)?÷‰ÉÞÄŽRAa_2öǸ¨>"¼®ùN>Ú:6ˆ·E‚ž†m›ã 03gTKŸ,lµl·3–|ÐêrŽØ]åc˜Ýhµ‘~`>¼ÅÜ~Ù¦ú[UóƒÌ4?¸°û^’ÚüZ¼Æbذ[2àu\Dù0‹T;×ònõ÷bˆ²Û9‰¤ë-(0ÙŒ#»Ø­Ö/:ª ›§a›£]9Ÿn}™B¦ïÜ4wçEw \&ÅæE%N‡7Ž(ÓÜ`êü”1Êh˜Ëæ²a¥Ý2j’Kÿ¨ãê6qË©ýņa¢–F⪳gdvÉ@~–Ú’W‰Ã3þìØçäÝ÷ßk¦­Ç`¬o¾èŠìHiHYZÇEF;Ów`ºh%&2iæMâ/.4Xè»áë}èènSѨ<ƒp2·óØÏGûAÛ9XqÛûÎõÎ3ü˜û͆_¶:ìŠgª6£¿1إѹe:•l¹6p^MÊãÞ4LeW˜Hàv†ö-ºOY6ÚÚþœíù²™úïÕ8 ŽDrcX’·O’|ôÖ>ººKŸT£9nsÈ%Êœ©\Ä8›¸RІ];ÞÉ Ô%bμ}‡ëbîâš½îøðžGˈ ̂ʡ½Ò.w ^Ùo«”|yÍKšÉçƒ(©Í¨š`Ô­ìeycušûÒZ¯M¿¾æ^¶iìOAXÏý:óñ"ã3޹Ÿ?Æâò‚ÇÝN_|y¬_úÆË4-3‹¯ÜtÒØg¯BÄJ2^óãȵ{Ù–(%a6/‡†´m[÷ŸrÈ¥(U‹±ö…Sõ±‹ê¿ì}‘ ]ÆÌÿ‚4cíwªšˆ"ÒGÈEìq}Ü!kI}ÚH£‘A©¬Ù m÷*fè•{Rÿ( â]ǘ³Ô¯Tã²ìGµÒ…6Ó·äàãVOÙ«˜Öb¾©’´jžŸmV¿oÁLy"D×=Ù_€âGøCGu¼oJŽrÞ÷¨;"ï&ÈhL°Øu³sŸw†]xô$VÓ›™±‘!øÓøð*žúµ¤Dx†Ä;A¯õ€‡3³(¹R…‚K¡|³r%¥”¦4º]² ï£Œ×%1)±·~J †­BçÛŒûÎÂÍŒîVO^_ø!yÂPC¹ê“Ë Q™1 –Qæ1ÅZ5OÇgOÆœqµ¼§uª#Ïëï=Ù<·¹ý´__Õ'¥C„KAæ˜$4`eô§SÍ0?¯uÜvëTݴøãÕ{]:œÓB5Úl0’`H6pf¯<ý¶Ÿ$“¸ê8a ÄõÓ‹\±û^gZ—œvE=âžpm\⤖‡Ö~¾JUpól¸QDP[qsŠ©Ìn˜^o×s‘ú¡ÍÐuãx ¦kSb«Ý Áõ;Ô— +¢>’ƾlº¼Vwë»x³‘ç0}!|g£wtÀ”~¿œ§û©Z7Ö$­¡‚’ÂTü‡9Þ9ØA“ 17[ïvö¨æíŒe|per>qHùê€ÅÔ\É¿I A6“jTІðÈÐŒ0œ~âý1j‘÷U­ªk®8·;v˜‹÷î`oPº;ù¬äçø–‹4#•8Ý­¯ä«Ræ¾òÅä d[øÀ+´yÎ}5N ìOž—Î997FaY ÂÇÛ£‰Þ×XË ¬iá»%v®ë,y¼,h +^Ó>¡š 9¬(4äà¬lÌi5ð"¾ZšÏÈBD“ô×®³®<È<PA|©Çê'Qd—†¿2’œróÔHû(]©&Þ¹åÙ))ÂO^äØýånœõÉPëQ¢‡}»:¾4Bô*Uó°)å‰UèÖ9ŽÉê9VagÞ½(wná¦)¼ú&îsF\)Î +}Œ+¹+X hÌÌ@SFöWY-Iô›?‘L¬2Èãi*¾Q`0¬PÈ;†þ)$ŸÙ%ЦS[&è=çjöW‡<™å Ïc‹œÒ¢žM.29ÝáýÍÎÖÔa>+¾­2½Ä×ïD²ŸhD^šÞ)¯e ɤM¹²¯(•_ )Ò[ëhñOö+Ͻ§ž¤Šª/«¿|Êïú™*vàªèRÙÕêt;Ó`G½+­WU^ÅÈ£wêû$jŸ=Uuˆk£º›.\)÷ +ûzŸïüßÊ[$ª/½c—ø¨”X²½kÇÝ£¸Ã[C¡ò›º"üoå¼Ü/èª|õÚ”ó«ÄÆ[fžCª)†Ÿ²ÇÊ \”ˤÅFݘâD‹=Ö…) K8) +æ*Ãàì“G¨wùAÅ)è·7Ï–é¤YdϲžÞy ˜ŒáfbºËgõõþK®Ûø‘Ç3†þÕî=W5…{ãv»BMÛ“ ªBS&¥àE|µ†yãAŒ烡*v öÂ2”š/fƒQd«}X â5éB¤h‹NHÏ`!{¬Àà«w‰Ž¶=Ù:x+‡ÂJÄ\¸\Õ×p©Q$@“å¾ëíQø‹\âçém§ôî®íØîX“½Æï™˜šÅFHÛîÉ7ãp2[õÄ1](§¢ðž«œ;5ëØw,'îCŸwvýS´ÇöÄåXýäí9¥·N¥¢&chÆÚCÚ@¥}r#ûÅÕœ:6‘²'fGN¨ÁBÏ&æeÓ3>;­i_ðbä‡÷n«æXîf×<ßǘ¬¾³[hA·Ä+âfòÇ8&cW'üo¹ƒjK¾íF>“ U°7< }pû˜Ÿ¦w˜¦®ŒQ ðÅù~Ú5:ÝÓÉ!2¯³÷aܶΗ3á?•0wÈÚÕ*yäËÌæð6ÚðPí(WÁÉÑ[#NqåKÃÝ™ª ê;3¯ÕÝP+ÄôîíÈT°Rˆì1âdÝ”™¹×>™¾YZñá)_‘j~]´…î6&Þ>ÈÀ.Î×DÚT­JÌbPÞ;ù¼.^F£?„†¤$8L·mh?6/=52Ò¡™j«›7¾¯0 <Õ zÑR³±^wEJ7à¨?!nœgüÔ è𱮓K¥›Æâï vÕG\,hE}üK›*çÔ8“Ù‡¾4XÔƒ*w›HÝ^‰V©-vÈa5©¼U¤Ì׸æÝÑ÷Éœ´B¡Šâ°y³k =€êÂívCý4lÚ{[͇h<[¯'E’yuÛ ’[┓S“n×I­².wFÆbC<å\†{`RHì·Û©tCõƒ„2¥¶˜o€·Øøÿf6 +endstream +endobj +716 0 obj << +/Type /FontDescriptor +/FontName /IXMTHF+NimbusSanL-Regu +/Flags 4 +/FontBBox [-174 -285 1001 953] +/Ascent 712 +/CapHeight 712 +/Descent -213 +/ItalicAngle 0 +/StemV 85 +/XHeight 523 +/CharSet (/A/B/C/D/E/F/G/H/I/L/M/N/O/P/Q/R/S/T/U/V/X/Y/five/four/one/three/two) +/FontFile 715 0 R +>> endobj +717 0 obj << +/Length1 1626 +/Length2 12707 +/Length3 0 +/Length 13550 +/Filter /FlateDecode +>> +stream +xÚ­vUT]í’-îî×àîîîn›»KpwwwwînÁ5ÁÝ ÎåÿOwŸçö}é{Öë+U³¾Z‹‚DIõ‹°©½ HÂÞÎå 3@ÁÒÖÄÕYÅÞVÁž[î‹<ÈÔð!gG  u»XÚÛ‰»€xš S€`a0sss#PDí<,Í-\Ôê*š4ttôÿ”üe0ñüO͇§³¥¹€òãÅ dcï` ²sùñ¿vT. €™¥  ª¨¤-­  –TPH‚ì@NÆ6%WK @βsÑÌì6ÿ8€öv¦–•æÌðKØ` pv-?Ü@@Ã_*z€ÈÉÖÒÙùã`é 0w2¶sùè‹=ÀÒhãjú€¹™ý߀œì?,l?tÁ”ì]œN–.€¬JbÿÀébaìòWngË5ÀÞìÃÒÔèúWIë>Â|h]Œ-íœ. —¿r™€¦–Î6Æž¹?‚98Yþ ÃÕÙÒÎüŸèN sc'S³óG˜ØuçŸuþ[õÆ6ž{Ûÿmõ_,]œA6f Ì,9.¹Í-íÿši;3{3Ó?䦮ÿ©s9ýÝ ê¿f†æ„±©½'Àd†À¨`ïò‘@ý¿c™áßGò¿â ÁÿzÿÿÈýWŽþÛ%þÿ½ÏÿZÂÕÆFÁØöcþ±cKÆØð±gr€¿«íÿåblkiãùÿrúWkMÐ?ЊØÛ˜þ«NÚÅø£%Âvæ´010ýChé,aé2U²tZÌŒm>úõ·\ÝÎädciúàõï–¾031ý‹NÍÂhm÷ìÿPìLÿþUƒgÔÓÐÔ’¦û–ë߆JCà¢æéðí?J‘·7ý¯Ã_aDDì=Þ_˜9¸_XÙ˜?îÞ n&Ÿÿ!åߘÿy–7vq²ôè~ÔÍÄüwõÿñüó¤ÿ/aÄí€ö¦ª‹±éǤý—à/5ÐÕÉéƒà¿/ÿGÕÿyþ{æA amÙÈl•ž•áR›72%¦;ÐÇ 9âPÖ¤V\è_kßë—¾Í]eôRÂÐüç­ÝséÔáu_†ö`¬džª7ô«€Ð‡Œ¦¿}ƒ²““î Ñ  9ãL3ÚûrQn J‡ƒIã`gJYÅ ô†è{'«Üå2·B,ò{_`ZcvZ3F}ÑéeÒñŸ{ª¡ñÑ‘áÞkèþýOt¹qð¼nPÈ”Qþ޹ŸuÔ«¼cqÃXjP0 ÝI±O}[OÝ„°!v:Sê]kO À0ãhëdBCG*Å&šÍÝø1Nü½«ÓebŸQ¨Ìnï>bð‰vÙÇÌd2J[%86¿†Á™¬ÅÍaT+Чi}‹3>åµïKjDâ¾VøFÐñ‡é—Û@"…IùtŒyjJKŸ'‰fç’žæˆ`×Qá%i,éÆ ‡¨_ן§R›ÜDíÐ6ª’U××Ás&Mïgµ«xR£’E• ÆË»ÛPèr¶÷˜f9HyÖ@ÍÔ¶cþ…˜à!ÓU}ªÃ”Iß•ÔýTä¿Ndmë¾§¤ÕÜÍ ±ô!!"ÇLsXèÊÞì¢éF<ÙŒ†µºq’‡¥Ür95õŽ£k0üp”®‰`á@/$›F]PøBÅû³Ô”)];yþaE$4Xûf§D#ÞÓpnÑ0ÚÕGFz¹l9@Ó½3;Ùføh>[Ì%@£ù„¹H$%ïœ+å#ísºzo쥸â“@’9cf§¡’È%I}K ¯-ÀÖŒYZ¢4”Aë7#j)×SnŒÿ=DÙÐ`}oZŠ7ÿ†Jô¨ Â!òjÒ¾£‘vì7Ôûù6×—$}1Âf/œd‘8 +ìãõ¼þÏRϽ§ ¶"¯’2=úH*S8Q×jLúª 9I’{oàW.#öÁ7ŽËÔ·ñ‹=Ø•\n0‹4Ôí*HNõ±ã íõíJk¥Ë@æ Ú;w¦'ߪ…Eùƒü¯eïcº5ØÀ–×Á{šhIêñÍ4ã÷Ü‹¹%Jº-ÈÁ{dø6_ó•ƒ}Nè…Ó&˜ý~Õ.Ô¸(HCÊùͯS(‰¾VUO8CQ§þÄM3Eê)ô’Î×Ú~"Ó:;Á%‰fˆI»Ý(2ÓtÈÅ„ ¨î¬¸…H…&\’PÛÏé$½[AYŒÌÚ  RÜ×±ï©=$’CL0 2}§SoÊŠVÙæ[r#¶øÅÌ_ÊvµAËþ‹¼£|iw£UnhèËÏ<'¹3ö™u©¯½Ì’ÝÈ$Ñî­âñ¶¼¹Ã~[…ö0¨cA¡"¡=}°AåugmÛЂ}«É€ë$<ΫC?JÛ”â>qúî\.¬±ëÁ!C²€¼ä,Æևçã¯LdžÒ-¼0à_K…Þ ËÐ(úï81ImtbÓ—*hÈ©Û9ƒ/¦¾%Ú—ÛIŠk°á ³"Œ‰q<Ÿa%Ÿ4TT˜=CÐr®µ€”¼¦ƒ3Òp¬¤¸À¤y[€È!ï±B¥Ñ;3\Vßøä|©xÊf¢@ D‘ÿû‰¦a‹y„ÚEK©ÚÏÃne¾ŒEÈ^Wj+±ä9¨z&xé¨vQØ×A[´,ƒHk©–íÜXX¬h <ÏG.y³Ã³¸ãOÍd€SG**_Í™<…8ÿZæ B­œ^)íFš4xøkJ¢_PÃPÉÅæÝHnÞ”¦ú^k4† +bÚ­# ½v,¤¿¾º–t (äŠÖhtXë&èø È“—QØ:ã+³X)VbˆB‡{¸sBh^©[\ýë,^ùBŸ²®áùw¶šŒã8Õçû¯ôl +63àÆšíïF²ª&)S!—Ê +z![xÞ@ÀTœ¨öã Y¨èúÜE˜Î©øÈU¦çyžWmàš œ3{q`§qÆ}»ˆÖ¾ gNU9ƒî‹á¾¥`íÑþËY8½9{õ¶–ƒ°U›Ö¢²½0»ÓL‰Ã»ˆfͲžgú¼‚©‚Ìå9 Ú[N!⩊GãwØœ)è«ne £” 7mô0á€xΤǤ$Œ_ß°^‘ðÑ1 +ÝÞ5jëqA¬±±ÂT Ïæ )53oï‡ÛB²ÝÎE;í+)ì¦Ù·t¯ùÍʉ`΄> ÖÚbb™ ^[RD|±¨Øœ}4ìíÆ%n'ÌêêÅ­ëñ" ÅúÉØéîh¨AØ»ÅÝãç]WMË»ë^‡>“bµm^Õ1|Ser¯œp§£ºÐ‡-¹¢Ew‘jG»DýϨ[fLÜZ©Õèë?Ž­Ô·½!ä£éÏ)t%¤?ÉK ñ ‹Âwf>’Ùd 6>‹m¦8KpAKÞSHýñæèŠ’–Ò$3Yˆcïߺ/Í’k´0·I.<`a¸Ÿ‚ó¸™toT‚—ž‹úfyŠXâ÷²ÙuK± î¿í¥ts€FS3“kâAyÜ™Ét¤rm)ºö QsÃÂÌüh*¥¼ žû}’ªNlIÒs'g—Mr<ÃõuQÐùËEš·Ö³}±½·®h”»îSÙ»þµ$J;û úºÝÆ7÷.‚ýÎYÑ­m­†›ÇÙ8®V8+jKµ/Žï{™þ‹8¶±*LÔŒ­ËEѾœpr8îĘýÞ3D°Ö±_/šõWì&²èZ‚Ì ¡µ…”Ã<އ›çWP¹šÔa–DóðñùudG(|æ&Ľq^ó +lû\PE}î®›Œw« s')¼ Åäçê/×ÝBtßæÊjxý¡4>éå_¼*|vü„Ó‚>h~–G„í¾ìkå…›æY•Ž£á\µpZã¡`Ü ð/îÆÛ<?Èœ$Pï^׆½*ÐÎÓVvé·R6ŵ_aÁš Û&„1å©­®a¬hJÄ’¹ñö\òŸ:)‡]r]÷¿¹Ý^äþáÍÑÚY8ÞJü†ÕÂùÙ@¼Ž =4ÉHRî†éÖWŽÔžá¢·ÚO˜ß„ô!lNmN»2æ «ÿ^N)zŠ·ye{LëR2’*Ǫp>º´"< žYYðˆH˜nt +œ%ê€KÍæPöFûVuM*‰Ý}ˆåé†=Îv¦OHÓó¤¿ÈɸÍNÙ¶ETbd|Îȼu‘<œ*¬3ê„_üá³ |Â’船a`‚©jv(ïlNê²9Úì" fk¶ =Yµh³– ,Ô¶ \”n\\¤9{f§)À‡lo”n%íÅ™½~cÿ¶µëiü½/þ&¡¤ nwvÁˆjÅÖršÔˆCüÔk×> áð-[?ál Ò}ûs}­çi`Ä ç÷|Ñ£î·Äø€©EÿïIC¿¡C½'’0»ðoÚõk‚ÑÔôÃ/úõl².ö^2ìßóHZMÏ~Þ5wNH@U°·ø¶‡£–`ÔÁvY†}[:þ*’ø.o udYÁF¶¨aÊrŒ‡ã Ì?r*¶|´•g+$%¿Z’ícø&ß +ƒ<,xæxýM™ýÊ·NÎpføA—–Ÿ—KSx#Pë\Š¥J0¨¬ôÛJ˜É¾À“i¥Õ‰È¦zß8C7úÕ)˜-u€‚Èv\5éÕêÝðyðjDý™°0ªS<Þ-õA|âj#«ÉÛR@g +sBÐc@Μž-§„svh¥ï·1;’¶T¯€S ¹ £Â5!ž7ªqvòW7ãçdÝצsÜûŒ”Û +¯äTµDÊwOW¤9·ÇÍ“ì"…úþØu®›ƒh<Ï9˜]¢Lu ð"¿­ ž1ØCζ5à‹ÌÊ×6Åfèf§/‡“Ý¡×è€>2ÿ„§,B§ÓÞ2Ö|“†9o‡}‘ë(^ šFD ³kºÍï*ý['¤¾dK}‘“Á0†Ê¸¢›–™êïG­íR+3Ì/ìÐàÅ~¯| ªé/•[þ_C²—kÝ´Mc>4D3  1ùÇ0´-pEèfîInbqéæ—ãÛìúdŒ¨DþWél¢Ùt\<lK²nœ)¤o"¦ƒÅŠ¿6ÐG¯²6LŸmiF¡ç„ÏsëyËÞæšÛíaÐÆÕ“¯¶óbáy‚ü´Aaž;w6ú‘Ø*1=Hµ_ÍàgYW§¤>×8Tn¢PºM ÙÊ”#0q+]ÆÆÀÖ8”ÒE‰n8ÂQ9Î+ùˆ†¸0Å‘Å+ÿ€û£üp>õ%Èúì=“Y«¸k¦’lÀ¹%¹ñÁ¥y½öˆtÆ@êöܯ—]ëJ‰Ý1ÇVѪ'È3gÔ7Š &„Ïœ¶a&4Qzã¯C‰|ð¼m³Ö/°¬ÀRÚ9­ŽÕË¿ÜöÕÀÖ(»Þ´oƒŒ²Iù<ÓµjÎHÔíÓ•_šp“lÁˆí¥ÿô¥](™½¾]Ör3òÈ1ïgæ’8ÌÁ>íxZ¬‘u7+-e៊—ÒÝŒâe*ÐkVI?sбz*H¶JNȶçúúfù°cÃWÊxÄ…ë±=’Æä=,gô:~‡ñÞúÞåßJÆNyÎ ÞÓÀè náV<œ¹¶±¼rÝÙñÏŽâˆbë°e•xZÀß«êoS½tm*æè>8¯¯‹*¨µPÀæ>NË%jç'BkS€Jó¯ NìSD€¤à÷}­þJ‡Â˜¾F~±T¥ò-ä·ÕÝg!®P ÒÙ¨šàÆ” aC¡†Aù¼1|räi®ïµçã"FzÒ2W³¡¼éL$„!TV|+ƒßÎ ¬I¨RT®Ó~ÜSh[Œ"ë÷#ZüÏW?¢NÝ<ü[aä¡kÙ†!è嶈›ù‘2O!UìE‘Ñê‡èYè\ÀKÇ´÷‘û+ƒƒkS¸Šh<Ð8f¥Z5|ûIs5÷ÑpÄ¥¦mÒ•«Á{N&\­3O<9¹ïñ–ð©ö¤´¹-½ã“íu9NþU5Á‰ü̈}ÿìX! +¤Sãr§µ_}É)p!O­¥Ã¬ìfb&R7— kGß,nøÕ¨Ó )ršù‡ç—ý6lI~Rn¦˜‚DÌm9ë†2Ji+\ИS°ß˜¥GBªUÂe ?ÃH½Ú†€ènCšóI!£ÿG`5¹nZÂsÂO/”|ÔR¨ûký~RéŽÇ{8)E=Å…ïš¿íËøSRÆ(o ³ZZç’Vžú˾¶£"8Á­.O2A‰tfýEï°ÛFåȉ µ? ¸óŠréÀ>_ºÑ-%MD×´-¡ù#À‰1tgM¯â{ûMjƒ÷ñZѸož3õ<(«·Ðê»S¨ä}¾Íoaí—ÓßXÐÑ:%Žt¿ÛÙœ_[9HŽ3Xp\ epYŸ‹Ö `(¡4Dz˜Ë›ìë¶2{‹D‹¯vÀ˜ËçTœ¸è!»uãÊ×J䀿µ¤½ÔIš¦›Ý¼å=žM²]&Çé¹¼f36—í:­O‰‹©Jtqb0B<”âK ˆGâÍ¡gµ{¸¤n-ªld¥|ŽD}Á÷¼Öª³J‰þ™mÇ`Ý4&©Ò‚Ž=Ö±²®‚š¦\ìÝ5H~Ö¼œúåVê5ræäRÜB'Vv7:ÙXe…幨¼ï½Ï< ]Ó7C©WÀørÌþå€'Š«ÄQ±‚5Eø}Ì6bƘŽûÑ´Ñé¯xäšÈ[3Õ ¡¡­˜4«ã?…Å•…>®ÇÐm…5ñÛIŽ£…ü[==ú—¿d%ÃW€ðY‚@Ÿóm¶®ç4âo|ß!³£|²×O,$óÄë…T׳/,pÆúÆ8ò]{r\ˆð„`…ˆ Ü–˜ÜU&ð°|-.){œÅ9Þz)´;,Éš„S}ïˆ*Ûí­à§BphžR›Ž[ZP8([ÕWñlyQýC®0%&cq§iW~ú´÷>æ2m!âàŒ‡~a"–.ßvº ×?!v’[u.*³Ø –Ì kêY G¡ o„n+àýÂ4'ëw¥:ÔsÎ ¢º¡`UþyêñÆú;Uùñ#H‚ë÷B£½êe÷RüôF‹êa!T^*äþï|ÚäÖìÿ]ÞË ,×§²3^3¡Ó‰ÏÒ!S\-TÀ#qªya¶Î'!¨Ô9ÍÍ>“<‡_#Ÿ³ÖÅ|6<>*GˆB°4Djˆ)ƒ! @U,ëmÍLlÏ x«Š,ëo: Qqý+W$–  ©3Úž3Ûh¥Û›«x¨ò®f_ËãŽVi‡òjÒ®SqT*—!w7bþN¹@>â5ð‘±!X’‡±{ņ 9a ÍoÐH_`Ê©ÓÑ +÷¥‹ÍcŽ®7Ôcá kpÿCްpš?öIã³±å3’ÅΔÔB´$iÈ4/˜Ž#ÿ ï È †#tæýšÏ§Z´E|]Ö…“0EP#ŒAŤu û9%`Ûš®¿ˆ7š³“s1Zݾ­©pãuºº Å\i€¿1&”XïñÉ8Awˆ'ÃËw¿÷Âü'”X].ßžŽ”ŒønÌœoØÛò²ÛŸ™Fv(…î`’¦ +ÿg’1¾Žê¯AÍL[cŠcâ•‹äc§©³Òädµ2j£¸IKá}6#ºq®Yõдõ*Ü lÜ´0q{~§Û¼­‚©Ä(žÜWr$Ò;3ËyÆã˜8·LJžeä”Ç\p‚¿óaŒÐDN˜2ŸªlWB[G.Rµâ®ØFC97£‡Ed`W§?뮳Øp'+±C*ÚãÚo¢7}1_CµN03H˜ŠKæ/[oݼ¢±‹Úµq;“n>WŒö™ÖÖ¹Oö¶BÿQ‘ýU†½2ö¡DÃdÃÑiЙAÛJ}€ËJ×t`“ØæŠ[Íq'Pw•@|£NÍpøÌ¸ˆó3ö±ÓŽËp>îñÊÚ°¿ùÙÛÎ‹à‚±ÛúøQPùoI®¦(дù’á ’©O´ˆ´“­Pø)À¨n)¯Ù ÆÜ½åó( çk­â zÀRÂm˜zB'Z˜=íȳò´`×L<_£S,=Ìݪ6}>‚1õ;ïç•Ýù.9’v¶ù«^¾^[ïåÇÆÉ5Qå\<Êà§X­I>‡ö¯É»®\e» YqÖ«cÝÀU±ÎyãÂ|àŽ ã©^EZHø†•O<Ö(,²üSöðËž9{á|VÝ,¦ð÷+©[è:N‰ÕYy¶,‘ì¾d˜–¯'–5êÇXÕ‹ â+šõíçø2 ýúºy¸ 4_n·LPOílÚý/º+%HÕ‹¹²ç=] +1bâl½mÓ å4‘œçð´{V@Q³1†ÿ>ô Ý‚ãûG¨y‰¾VÂÙVÚAm0FÖö}ƒÅÊE£Q0B :•<æÓeQÌÛ²ü®¶¸ OþJƒ€g(U;îQû:YõY÷÷EB$㢠)ƒÙMGp×_ø{—G<¾ÒZàjäYºÙGzüvN:yõ$Âc–ûÑy&«`:SŽ68H„|¶í‹ä˜,÷™ýMàú扉!¢¿«÷¢ X úèC©’.œÐ£JvÚébýòQ¦ã5IËô樚k}Êik’J OrÚ¯ 2.qñHÌñÄÅÉ:ÜHw÷¾‚8] r’’Š6Æ5•ô[R擌(ø(}á›4.V'1ûv…Þ“lÂkÖà ¾_0jR¯—òyð ·ŒÄnüE¸Ý†çKØù@îCTI-t6 ¥àfaü¶­rªå @Çü8ýÒC«¼Xe]Ðþ¶Ì÷b9ÝʇÇ5áK=^B4꯭a—w¹¡Íe´øÙ±Q†Ò—¿ü˜Ï9‘bf•_FSè,ÖCÔý5.7Ã4»…–ˆ›qíŽv/ã(dá/°{'‰†U) ¨ˆ(Ø>·,Å{§Ën¶l„iðœ‚tÎϧž~Q¸9Gåƒ3-Âá‡_Æï°äú;̧fèõHr<屟=%ºY_yKt¼MŸsš„)Òá)j•߯”#ì› vI·"ͧý †•)w´Ãt‡ì?{)g¬uùžÉé‰^oÒQá¸D‰/eºÒ°„j½¦ 'F56l p˜JÜ×çž33 ÅéHì§;ÓðÁ«ã¶¬qIÌ5ª]'¬ãù´¤Q´`Ê'à'ïky¸~ü½pOtrß“ÔÁ±n ž˜GNàW½OëjùO ÏHvL@£f!ðß#<(ð1šrõMœF4Rñ«#4àë3R¸Ggä+6ôÄp9ÜïAÙkz ‚1w-SæM*œßà~b¤o…?‘Œí2á·Ò×»¶ÏbŽSZ“òA +¦g§usq1ÖÆ%Õ¹¯IGTZòªÃde{´Nÿºz:“¸jn Hì´jp²ÒË@€xމa}š½<Épëç ½ä¿x\æë"|c˼7û¦-pÞ•á˜Ô3¸¶ÅN<Ûúm[ ªÐ©,C"æ2;ù|öhCÞË ¢T„eNg§ƒ<ŽI>Ÿ%ZóΆÅàr§ÈG¾vŒFFt¡Úv;ªº”ˉ^ [NZðžW™BÍZpoÐñ)¡߈,»ÅU¬¡±øjÞ9J¢Z/s +Û~4ËÞÉZ‡º–A˜Ì1ù³íØô¹ÕÏ:v´žºÛ€½Â‡ û:ñèÐö¬5#{º Çêÿ¸q¤”£HœúÃ#vžc°°Ê”ø3ÄÊ$2 ¥¢.àÛŒëZn¶Üú ;tîRj•„~—#c?¸XKÇÆ W¾aF±Ÿ½d j¹8›HÓÞ=ÚÅ ðžýËë†ßíö÷ÃØ&¸/ØñÊR!i]^j“i$k0 ÙE×ÃDQ ¡ß¯•RÊœ +x¤ÈÅ9#´÷ŠSXÖúü Úê» HôÇ1ñIØg=f$)dà~B~Ã\èjòƒW¡¬–)åy&Qʵ¤HÏuýL6¢v“Û$|"%Q^²)Q»Õ‚2*ØOÛz2ŠÔ6,ÅhÙÔš˜‚²pg©òCÙ´„ë‹rir†àš9ØÐÔžp¼w§Ž¦NprÄõxÍä܈ U‹RDAh9 (@*.â+X¶rJì}®'óà Lmö䀊?Gí…r|yƒ¢Ká ×õŒìÜeMwäï’»ÓÙ¨þs‹4»©Ôâý&n9­ˆÑbû·n!КÏ„dD}„Ü‚/Leì§×ôSWѺ-1 „‘qÏâGíÒTá9·(Ðgl6›ÆºßïÐý[yzR¨bO‡vWk*Æ{²‚ìyqdºhì4ÜF‚œb£­S¦Ô±IÝùá}g­Í™Òž¬Ð’æYÓ—Pßl•é2ùw: sñb¡ÈK‹È¿¿HsþΧfZ¥ÂÂc8Ç,PlÔ>åÊ©¤jÀš9.}Ò]δßý}S‘Ð.U=Ö$“iH–Wÿ%ÊÄå©Eã‘(QØ[‰„3ˆ3X m™º.Úd1\îÝoÍÆ-±k_]ÑÁ L„~,~]'í!Gîì*„ùî‡ecz“wê±ÉWõ¤Â[ÄË*Ü{þ»3&D­h—!Nˆ1,¤.~þhëŒeë=¶-?—®uÅ!×Y8A›ùªvΤµ–›*¨t¾º5cNÎnp›ÝJ,œ(l_ÑGÏ€ë÷”5JЃcÕ´E)ã§™¾O¾¤ÞñßÉHòÜœ?¾~oÇãÉ}Ê媋ª¡10d`v-¨i˜ŒX6?®MeU+üÞ‹mÊä@¡u1ôݾ5X-¡™I4á*QcÕÿ÷ö½û!Å’3ŽÃvý³þPlÅÜ>îzÀžÀÂH¿úöÚEKP!Ì]ÿšaþ³Rç*Œs5s›JTRDýOœ×Ïjd‘SÑŸZ.œƒ=‚] Z¢¢ã(%t¬øYúÈ-5÷ˆ µ‰NeØ‹RË×xNÑäÑï3î ¯«t!Éð4Er¹m²f!¨Ht*oQž&Àðøx¾ü9ß&!w³)ç76Ã[›ð‡É@]6Á‚ý$Næðc +ñ‡ÒÇu&æRŒ¿nöiŠ,yµ`õ—’Ó¾A8’e[£9júC«ô0$Úɶ‰…ºØitÃgïç…³KQƒ\êW &O¡L9 _q +­¼®M~´¼¸­T|©‘ìÊþH`¬ó^2Kð9܃l”;e+N¼#TÀÖþÇÐA¬ì:!]<§»-ÉÖ×ýÕÐp@øöh¹çòd÷çý»w0ìSTFCçÛ)ó:^Äm­HºÊeÕ®Ìñ«ôKvÖç¤ÊUp(Uc%·yIR á´Å!öE¡H°€OÓyS§îOÏÛÈIÏ#¡„ÏUßÃ,‹ì’bCbE“¤¢`ÙÞ|ŠÑcð²'EÜõ45àæuÎÓ¦ >©ì‹—·¦Ötñóà=ü +j¯ùslVâ@ÉGÔH»g‚çªç?¿³R†Ü"´&¦~¨Â¥9$P1€7C„îåŽÓù'êèü‡ºñ^š°^†ø·¾×Ÿ«lIý@¦ÇÜS¿Äœ€½år¾M;a®ñÛyV°Þ¹Ie¡þMuø–® d´N:²ýZ… ì8ìÃâ-Ó=iËP63)ÑðgdzªWÓkDOãÄØŸÆD³3äÍé¯Ã-4‚׿øe½¼Pòñ‹µ9µ_#âu¨BÌàˆìU¡\Q¯ñ¥Y"ùú¤ú.„dç… ]O5忺^ÝXúPU<¦3Ò²‚=hÔA³âSA§D‰XK‘NªYލºlœ#K„Lß…çEžÂÕãsía¼IÙ[cš¡ð¦¸£løƒ ê©»Ï寳ÛÝ1;%¼ýí?sZʞͳU»J†ú†/é`µ£;Ðó°ûþz‡ð)ÞU*Db鸀*HF0ºârg[g¾Ç3é^<LŽzõ€cÏ#`<úŒRa‡R™«‚+6˜*•C©Ä¯:¿â+E½ÇØÔ{-Þ-Ã}7jwñçÈ×㈓³Ö´‰íiœ°¦¢áPë5ÇŸoŠ‹ô)å>û¼@3g]BŽŽì]ÛÄSpD€×¡B’Ÿz’ä=š€¥I”ïÓNNÆ ™ÑuüÒ¢\+²•¦Cü‚°5KóÔa|óæ[MS©÷Bx\Ó©Ãt~HÓZÙ ånNÞ|þTʾïà-VÞ¨Zßþ`mpÉX`‡jl¾ $ã #ÁÂbÀs:û.KEýN-pRKÀÁk÷SzLg*…?BµøZ@, !z݈Ú1±†=»»Aœ;ºé‘Àc“ÕC‚ÃN0Û—#>Ž?D2­éN2Ô½_ÐÔfÑ•¯n]HÅ^ò©º4>‡§Yú$-íªÝ­rN /ºîö¥†Ù8˜–Lñ‘¼9GèM,`h]••({@o=¿¢¢]y$5–Œ‹¸Y~¸›zº÷•ÿDé°ÔiM ÷´!ô];Ç÷öD.½Ÿè¡:Ý[„÷í ¿ú²Hç[A€ÔtfuU‡ÉŸŠ…åÒÛjJâuÌ3C¦¥ÜÎfÿ¢”¡ÔDsá´e%ê>2ÈðxŽj½6w¡7'¹%œqòöÝM§£xp§ÑWÓ½ª»ðýÂ<̧ܠBonw+ίu\˜[V4CäB¿K^QËÜ„®–½ÕSm#Ùj­+:íŽCŸ¥ý’()yU1'$ug- 7Sn俢ók÷SÍãMOÕ ¦m^ Ç}–•l7(êÐ7©’ÚíZjDv®‚g1üò'£üĬ µYÓÑî±Ã=ÇìÓÜlˆiÞ9§ÚèŠ9!á=Yº±“¾»šÈ ¤5¨ooѨ 3õ[L„DyÿgÂÎÕ¨«ÂnofÓ¯@¥ž{D}±A™§Än ¾\.¾u?ÖTF!ÙSèîÕÙï +ªøÆÉîɆÍî(t¡…R\ÙþgÃ0XRµ8÷¯ök¤å¡ÜuÁ¾ÑÍj4>_hÏqàx^Ù~ +‚Ó,æúf¾TT±ÞŒ¬.Ü׋O =œ’¿Û† -g;P™Õ7Ç¢_ŸÖt|:£_J•G$lÆ­åÂ’~™+¼—‘Ü·,Ð ÙëÀSßó‚Ä<ÇœÅþun-^ùU–áe\%цæ ]‰ "! ï6Úå€QØÓJìNòبÒyæì9óI˜Òð1éäãK½ tèbˆíQëðn¼N·O1º…ÜnË–‚þûÞ.t€ÅlÁ3´üÍBÉ$JÒ\íw*JB3 ï>®m–hÞ„†ø¯Ù{±V(}‡†ÊÓ]žŒ•Á]öGušìo ?¡µ˜–t†˜Å\´öœºµ B³ ¦1¾5×sf ›=&ð¯I°ÀHÜÿðõ¸[¯o¶XPI\¦À‰U,¸(_ñóíšó¤],|zn8îpù­&ã‚¥°-K&—HÄîÉyÍÐJk·ŒWU¸™ðüÙ{…í",êi£Þ~¯:˜¿@‹gÞÊ+Ñ­GÐAî~¢Ò¹ï¸#쌄ãÁÅòƯ(¡`tãòÈyȸ¿6J{lÙÖ³*¹Š’åwñó)Xpb5{Oº5¾G²˜®ÆÒÔ HX}=ƒ¬9ÿ0MÞ0›V¥ãTYm¼”9J“oD»ŒêK•ý5¾y ÂöÓj"ÎãçÙô“•*v ÔPG=2ÒÇ•K­v´X)¡Ì³Ù ý+Þz6ß3Þa%qãÕK& 7ÌéŒó2ê/ ðcÌÚá_ƒL_GN#³ V˜g7sÚºÅâ!ûS †“ì¡z–ökwfbìX‰ßî.Ý{öìçßnÄFá58ˆÔ_Ÿ%GÖœ7€…d¿QüâÍŸt¹åÊ)ç­Þ +|=”]?‚ó‚oêô8»<ç0]NzC)‰s˜|™V—#?øAS-Qñ'¡².²t± Ëå³¶*§¯å·àQ”¼Æ¯ÈQËxï˜ÐðÏÞ÷rP5w»™Ýu«ûŠ®†!¤ß¸ T«²2 ÀS½~b4ô1fÔ•«2Âå\ˆ%¹¤“ÅJk7ó¦bbÄýv†4‰­îåB÷ÚÒÁF¡sÚ{û•‡×W 'Ðó¤C¡©ü¶ê(ß6Å=2÷36•–¢ëgâcô{^›óGÝ,ÆF­r¡àœ™ôl"¸ìð¹S ÙêÞ\PÕ‚§÷C¯¨Õda{/Å~WyÑi<ÉDŸjpÛ´fœ.Y¯N~ *‡£˜uîÖ 7RmIÆAAVñö«¹'Ss¢³TB䯨È­fž”-ß ç¤ÑâvŸ=ô æ0½)Žéa´[õ79ý†ñS61|¾H3$ÅÜxí‡O–oÁ‚¿@«g=O'ä\q(8õ/Å“æ«Æ\j.ö‡¤ƒ=Sa&}8Äo,‹¨³ÆúslpŠ–FaöƒE¦q°gŒ€U'÷GˆxÕŠR‰%®@¶tEŸ”Ã0”è“=ó¥(ú=øéû$¯–²6DµÌ^‹F´ZVkPNkqBä…Î0ë§×Óq°ídb +ù¶v«5~ ‚É«°5 ƒOs”í£4þ-a[É™?j ·³š,³Ò%EŠküþøH›ø€/BÊ¥çˆͶäßóØ8Ÿ–Bw2›rVð¼#§Õl¨ãË@ß2´®0Ýz>–B¤ÞBÞe#vð3œ^Ïì‰u¥ÙV‡"¿§§¦†V˜E¦&l2\óC»l˜Áš´9ùïGL¶„ƒ±~}÷ÌM¡Ïfà‚Õðn›0K8;‡pHz“?teNf»w(Ü[jE÷nùã¥8Øh +ÒwsZøÃ°÷ßL«, ûò •oíšãtâ) A ˆ^j½æôãûõÒµF ¥K?ÞÍ0 ‡8í‡K/Î=œÈ„)}N[z©÷SdzbúÄÅ$Í<Fü²=.j ®,àwSѹ̞ո—°û‚&“PÀÁ_Þċ¡€5MÎK/ÝÏ·1q9ió±0¢ÎL: +=ÖÜñèæeÕà>A¬ù'š@©Ι# b_Qì[˜·, Qx؉HRB¨óÝ¥* ú|÷g*øü³o—XjŠv€[7ÓñqÂD— IÄ:<.Š_‡Žo û€¹wEK”;n7ÿS¾Lj±Yé¾Üó?ç dæ[þcM·³ÊðõÈhxV>j4~Ô ·žÞ¸Ä8¬âËh× Z;dªLÌbW€P[sÅÉh–L» +ÉKwðžóÜž‘ËÏ›Y™•!b Ó+~Œ-vM ;*ôBF¶,eI †IÁ†¦)œ*iè̃k oÍ)˜rD˜+lHI^Û¹85¾‰W°<á=—kû.Îhf<¢Kƒ“X| çp2ª¥náÒºÀÁÑE¸ü”ê‘–ÁÒR^à³ôúô0d½YBÊߠ儵œ‘ŠJÌV'\m|`–o‘Àõ×A{) e „ÂæúA~V'zz³’)¾w¤([ŒiV7™ä²b[@æ¥(¤Ó£rlü™ù&IXöVAl¢L!†&¬ò<Éý•'rH¸ÊØÌ4iRt]bÉ‘Ä2çþ}jt¬!ùèlŒV°/Üb8urÉØlÅ6e„ÑSŸd`B³œê‹l%Ã'(¡TOÚ +ýXÅþ~”k>mÿ¶Åä¬ +endstream +endobj +718 0 obj << +/Type /FontDescriptor +/FontName /ZDVWXI+NimbusRomNo9L-Medi +/Flags 4 +/FontBBox [-168 -341 1000 960] +/Ascent 690 +/CapHeight 690 +/Descent -209 +/ItalicAngle 0 +/StemV 140 +/XHeight 461 +/CharSet (/C/D/E/F/H/I/L/N/O/R/S/T/V/a/b/c/colon/d/e/eight/f/five/four/g/h/i/l/m/n/nine/o/one/p/period/q/r/s/seven/six/t/three/two/u/underscore/v/w/x/y/zero) +/FontFile 717 0 R +>> endobj +719 0 obj << +/Length1 1630 +/Length2 18441 +/Length3 0 +/Length 19294 +/Filter /FlateDecode +>> +stream +xÚ¬·ctf]·&œTl[wXAÅfŶmëŽ+¶m;©Ø¶m'Û¶óÕó¾}úô8_÷Ÿîóc±×Ä5qÍ5ÇÞäÄòJ´Æ@CQ ­-#@ÖÂÆÐÙQh# 䔦U41sü•³Â’“ 9˜8Ym… œL¸j&Æa#€‘““– ´ss°03wPª(ªQÑÐüøOÉ?&C·ÿÐüõt´0³Pü}q1±ÚÙ˜Ø:ý…ø¿vT218™›L-¬MBrò²bJ1Y€˜‰­‰ƒ5@ÞÙÐÚ madbëhB0:¬ÿ}m-þ)Í‘î/–€#Ààhgbdñ×ÍÄÕÈÄîÕ€‰ƒ…£ãßw€…#ÀÌÁÀÖéoœ€ [#kgãø+7þ+!;à_ ›¿º¿`ò@G'G# ;'Àߨò¢ÿÎÓÉÜÀéŸØŽÕ é_Kc ‘ó?%ýK÷æ¯ÖÉÀÂÖàdâêôO,C€±…£µÛߨÁì,þ•†³£…­Ùfðà`bfà`lmâèøæ/ö?ÝùÏ:ÿKõvvÖnÿòþËêæ`áähbmJËÈô7¦‘Óߨf¶°ôÿÌŠ„­)ÀÈðo¹±³Ýè\LþÕ Êf†êoÆ@[k7€±‰),½,ÐéoHåÿËtÿ}$ÿ7PüßBð ½ÿoäþWŽþ—KüÿzŸÿ+´¨³µµ¬Íßø÷Žü]2¶€¿{ øgÑX8üÿ| l,¬ÝþO^ÿÕZÍäßéþÀ$œ þ¶EÀÖì/5 t ÿZ8ŠZ¸šË[8™L ¬ÿöì_r[ck [“¿Üþ«­ZF†ÿ¢S6·0²²ý‡Ö«LlÿkéúWþôò‚Jr4ÿ›û/Cù¿ƒà¤ìf÷7·ÿQ Ðøþº¡wŽã–)¤Óµæ +¦MiWØ-ýi§…I2°±ƒ)>•¡õ`)óŽ%Ï1ÅÉ}×ÙsåD¼NKj¨º†Û­¼UgU!B 0Q…€¹GÈÐûEIî“$AOΦ$""®*©^š?œå<ºâ§IS9Y°÷É\¬ù3¡Ã½ÜeÃRץ̋j×|³O`,ŠIÝ›ó(Ǭ. *´ƒ£®<"óíf‘!°éž÷ŽMœp 6‘ÑcägÏÎÂèL³÷±wbñK2íÅ÷•㘧+›V¼¸£ˆ×£NóhäúõôaÏÍc±2™‘sW2B ^Šsw} …ü*%òe¶“lÐÎñM µœøËs)3µËuãbe•vS{jDé£ÖŒ»£%`Ì{$ÚËrÞ—{–ÞS…§™Û ~H$s>8¯x^h #x­ Œ™–Jf!ÃÂcÇÌždÒn9¢—Â0:‰â>}”–í¦¹Ì¾œáïñ¿W¢_b²Ú’á“•¤93•ƒu˃‘ò·—†¤Tø*0œuÝìœdÄâ¿ÞÖß„L:;¨LÚé²WÿlŸ]7Ö4ÿø§”8ƒÔN‹›|ÛPf$y Z ¬“lwÐúï|de'Ñ…ûê)‡U2)MÇíø‰'˜‹Aã4s)Çï¶Ó´$~•VžÖA€6ôÊù>òµ8TiØi’“o™–ìa †û"·‹)w†TZlºàúq£Qs!è$'¼Ô Fy6¼0Ð#+ß½–tÐé°eæB¨ªºEQã*Ø–¬ë`]ô|v©ÑA¯’ÒÓAr ²QÆ«{¢zÃ2j3sn0§4Ðÿœœ@CWö䥋¢4`åü¸ƒAànã‡oÚ Y·1s«¨Í85÷Ì‘#¬{½°™ +Ô§*ìé(U‹›ƒgbLhF¥3ù~ØG,{‡åc׃È3FÈv€Bàt¾#}f»l3= Єª!¯ *ÉÚG4®ìš7µO‡. +ºïÍ#|E“©;…ƒÆF=÷øUV´ñ¤±NAþýަ½Ú‹&1êÂZØ?¦»;5ðçn…°â%aZf,®O«µ³KØï­ËRøq$“°¤oYЩðxŸ®/3žn,Úe÷kŒ2}—²Ì€K`t˜¦ÝÃ.ÚÇK±ƒ¤Þ­§eäÌ>¶Ö–0eáÞBA_Nv¹Oè(0VÒ W¬+ü×ôÇN XÑÉWˆ)VºÉO>tÇq¨å‹›và…¼¸÷]fÉxÚŸ÷™IžÅÀ¬Ïþ¬ +“Éš^Gá÷CþrŠŸ‚Ë/3}NeC‹©ø+¿óÂ`°Ç‡ÉÒõΓšyÇWû„´:‘x‡ìg\æºD™ÀYV8ʃìÿªš~M¶“§fç:çÒzð(>”V¢«ÍAó̺~µL ù#áx|Òw‘–ñ¼¬hè1$>íl¸¸”ÙN†§w Xµìú+Áp6øÚb°íñf!´¬7Çò£Í‹>ÞmßhuT‰Sò”s>3âH€M–Q×PZyÄ]¸|ô¶èÑÆefoL‹j ÷ÍíºÚ䉂7qÍ+¶ñú bÉ-ο™#¤êQ¢ùÀ¡ûˆíîÂs'¦Ð/çÊ…Å“QŸa¼œ^ç<ˆÿ)Lüýä!È5‡Ÿ µXÄJ±Ò’•Ü4`´S}}w÷cÊÖòÃŸçø“zseäjô|‡Ó¹ù§€We# :±=\Q«àH…€š1‚âq!õûð<ëyZ'jzQÚŒ°ÿI\l$¨„¤-o'½.™(»`M(™{.c-P~5/x&ÛÏ ü6/í$dfg9~å·JÇ Ø“~ýz-êÕo÷¡£dé¥úÁ;òßÊëÑsv«ë­KÓ„‰Mü૯5Uш໥° û¡OÝ£ ‘ Íâõò,|+çz’ò€Øä{›Ì…Üë5Òz!}|8ùí‡n®c=èÈèâ_8˜0)é¯8LÙ~‚ÖÐUøœÇ™¨Pz“FÚÁfUbÑ‚(‡¬Mz_ØäV•ÑŸm¤rl®+¶íƒä§W&)D™ ,߇Ã&Î5ñ &’}ÀZ!EæzòžÍ54}Ê&´ÜOµÑ™¢á§ÅBìúÇßb£Ÿz} #égpZÖØE²7ú×x»¾Éˆw˜Å Ú˜8Sÿ>O’i°ø§ >íIÕ¥PÚ€TXX.U7Õ¿ZfAZ|6ö⛌…¼Ìܨ{†úõ™eLf|Ï8)­YhÔf?…,¥¨îô2ß(z¾¦Êlª.JŠ`Ý9IàUÂ^Ÿ[Ÿâÿh¯z­÷ô)ì «˜UÅ)šÛŸ·þ‹ Ü‘0õª[ãmÕÞ–a€}Ç”¶9°¸#ÿ53Ç•c–äXC·©HZEã(ãKSoâ¢CC•‚´øƒlöòÇ—õ9©ŠêÇ£0Çycî{²¯…;x]ý]Ÿ×ªUà]d–IØÄÙÀ'.5\éc˜†‡Kð« ¼hVTJ_,zNÛìorñÝ,™›œÖu¸iã&¸ ŸXŒ\ýž¤o;þ§5G33¸„ŒH^Ôtæw7ê>b–KGAˆãíéºxɯ‰R[‘!5à~è²è”ò kø1ÙÐ:Yç,¢ÍóÑNÀl†/ÆîÑq‡&Ò,5ù^¼äDZ“ý(èÆ+ŠÞaF/Ë(©'Ê_R­·ßŸ$Dþ¯Çµ8èÓ³¬ªªÙ¡= +Eõå¡ó9º¶äq‹¬?“ôG¸˜ÁS¸ív +'qB9^û#µ˜ ½Wî¹$ëÝ›¶©ß"Ú¾ 3?ýfR» Äã­¿î{à q¼l^­kâ„ÿ(b[$ÊwÁšºšëMÑØ¾-’sö cåâÀ\£–‡Õ–†É!VŠØu‚yDåúÜYŠ»µR/=ñ,Ôõ'4—[¾wbÜÄ€Ú ö¡¯ðA®à,ú ¦³Ö!q–‚Bz”tŸ¤›[s)ij5!ÐqÈ +Y&}j$J³•ý™°V#‹Ê~¿Øª†ÄM’~¢Ê¢>.KÓXdOôú#eAp[a€'bd*c¦5…™ÙÉ0Z¨²#'B` dpeùw¹¶Åò| +ä2´]ü\fWJh·Ø`HUukô¢9ÙÂG̸t_Üà÷Î$k†tX4à Ì)¶ ÆL޶`ØÖŽ‚¨H”ò°ç6ÚL4Yt§ŠŸ +cŠëääa„êD¾VÄCN†,ÔV„Œè‘ªŒ KXO ÙQýZlå¾pËŬ/!ÍqÙ™¯—ÞE·ËÙzºîƒCù¨yP¤Ñ&›Vnÿ˜XQòT€»lÊâç¥ðÒÜèª-ŒÀH¹âc³œÝE˜¬7"óÿq3r­fÇ +ú3Ƹõ j_I­°Ÿm¬šu ñÎ'µ0× MõöºdëöbW{í@k¢רxMê«x+DîôÛ8˜‰y9“Ñ*LœùßIWa×ãæÛBüŸuc,™–Ë»œÞ'bÞjhh/éR'þâÌJŸ Gg–ŠÌˆ¤¿¬Ñ8dxKí£‹0Y߆DiE l«2_¾H®ŠÍõ(¼ öKŒ+Òïæ˜@ç€_y?>ãÅØ?I7DÚ'åwønË"¨Ú²ÊÅ[]ùr>¯–~TèW‘Ò¿r}š1»‚øH`\µ'Ò‚Ó)Òë¹-Nð#5jõ,sÛÖsn¾Œˆ‚Ñ‹aꌓüTøºvõûŠ*‰H¾D-kpdk+DÆÄ$ÀtgnŽnøëöËãÄix¶aÕFÌòfIWQÓg#‡¿Ÿ“[Ão' ªs3%…ùÆ®G`OÅôq—½ª;ÕÖç®zGù4HäÇšìKW¥R~Ç£Y<ÎŽM,u;›Ò¼jœîU>Tà;v¦•ð½À fKþ¼rØS@=jÛ”ƒû³±{D‡9?Ús”ˆôšrÛVeWˆ§6;|LrƵZ&þí%m™óq|[ ^óö4m‡{ŽÇœ[ݯ«pª×lÇÓÌ9«¹ ª«ÌóÅ~ަ„²i!kdå9,²O‚[Pˆ€zœØ]â`Ò†ÿl@j7[›øeH øm7hÎ ÇXÝ<ÿ»Oñ¦øjÚ–=º~±u›7× YQ"Õ)/¡ÏÄõ3¨èÃ÷±@õG8þ™±;þ.pŸ‰n²~mÇÓCE„ hæ3‚ƒ¸›Fí"ßâ›ÁÁ猜_X|zA ë™›Âë ¸Û†ŒSÛ¡ÑP…õ­FýÛoÄ6*+ko8EÉ;À<Ï®Ÿ)Î0,HÏ,§Äp×ó{2*.3œ¼ÕánH_Ìø¥û£›}ašY’x4œÙ®M6òtýÙ *¦AI^¢•çXRI9ä²k©ï–ýX±¿Î:¤Û*«%˜$Z;Ê;h}Æj‰ô‡jj±ÊÀ²IïE(eðÙYÎ3˜G&"…¬Ls©˜±ÊÚ _pxÚÔÒA¸Uš14`ª¾÷Ÿ ÷ö×ZÄÃ6'Ý”ê+# }B¾âv•\ÎAŸ¬+>2ñ\J%÷`No)KU‚œ—Õ½„#TEúŹÝ÷2Òq¨’{é¥;C'U³ÄM˜/ÛS ¡#ÒÒî9îÝFÐÉtä[’»+s3W¾µŸSífÞ²¸#‹Ûœ¹Õ:,¨Ï\PØLíî0[¿úÌ zÙ¢Îu.‰H{.¦v ¾þQý£¿ÿ­G`Nv|VÄ-9Ωä”bšxdaošé ’ôO½nå¡êVŸ ®¿žÍ‚CyŠŸõ­Ðp«´ ;8.9ºãóâ‘M„Þ·¯…Ý=Ê0ßQ`õâ€óªá4x®·B×PLÍÇx;8(ö~3¹ˆeò’õ|å-õóV´ã/4OÆ œHðÄ噀EÄ„`ÔZŒâ:ëf$‡±‡ùñtâ+_hsð‹Q»‹hæS‚kÂÎG±ëc¤AzÑDïJjWV9SG—­?êp Y¯Êüb×oìRʃ+V¢T å3˜—"u0¿¢Æô˜"ÁûC]Ù|jöœ÷^í†~ÁøÃklÅ—EbRöñ¡ÏgãB3s$5$jj™Tä:Jƒ,"Yšß{L9Bbiâ.ìÏ–Ô¤:²Ü7Ï[1Ӭ΅hp~'žÔ}ù»Rgš½LÔ+hY±z¿Å®åàK…ÄJ5¾UòMc¬Á,š™ðXz5çîEöJÚy„¨ NC*Þøîmú¾”^B‰í˜~Œ¯.*n°ç©©!õk(Ëê,$AèãéѼ×g¾½ +¿¦‡Áýcµ|ïhp¥UÆ=.èµø?èì30ü*n=à_­ßGàk}™{…W©Ú…”äç„¢ÑC6[i e¿aó1g¼jÁRÕݤ‰TÈåjù­Å o¾ž?ÿhò–’ƒtF‘ qŸûד¸S× Eº Ù+]—[)¿\玽tuÉ%Ìd9À Dª±Y¼/»Ê¶V*˜Lø9Ü“ÂüYÃLÈÜæ[œ$©­×Ã&Ì.¾ñÆýY‘ûƒ‡æ¬ÄzÅY®tòÓÑ.Ëu¹Bž ˆ ²äËv¾0Ê® ö]¡ÝD¢ê9'rYµVN¿û£ËùtÔ$,duGÖ-ŽýÜ…^"!3ð›Z‡6ºk’!ŠuF¯e¡%§s¾Å>£Ž`«R”óèŒy[®[wRà8bÆ‹"íLÛ²Ѥ¸¼ˆ“z9ª]\Si½-Ëó\uy€¨n¥N FE¨ƒÚ¼÷¹˜rñêj[v‹H/(ISæv½.% O—ßãIÆŸDsš˜GŸï&UÁ)j®LåáåÕ +–ŽÏc¥g¼žÇ?Uͼ¹õEö¿ë)`]|[4ZKæ#•Yµð¬#™ŸM }û¾¹w¯aê­3 .N‰k×|kGiÅéü’`œÇ€W"AXÀUf¡)­%sß„à’?{Éžø ìËâVqM&³—ù@ÐÄgô… +1'ñà +Ô{–iŽ8ÃÔZ3Ð#›ªù½Šž +w®Zƒgóz ~”Ž+1T&(|duà§ç“¬Ð"¬Pk?ˆ×­2KX{ƒ¶Y³Ô^1ò+²°’7ùx£¯u›bÏÒŠqïx9ò;¤Ùå!ÅA܉˜~rœzµ$Tb”õu콊ô+¼„Aê­.Î5¸/$^ë·Np³(T}¤Ó»–im›E,û$ARE÷E4µý5°†Æ–g%ÖÔ Y{^HÌËKÎs÷`¤C·ÛZûœ6ûø·ÍHHÊD‰¯ît‰¾HZ#MÚ¡`äÎ\Äi¶~$—ʳT’te·L²”ëü¬è„¡7E =ÀVgC–½ðÈ9Úö¸¤÷st£®Y#¡`õ3(o‹4D,ƒŠÅØü|‡¡1‚)ÐâtEYjÏú*M>ºƒVö{C2‰N*>¥OiG·E'ФÊÔ£Ã[E×Ð!‘Ô­:‘|,¨c¬c‡ƒkc“QI2mu)¦ y½ó\Ñ¿ÝþúŽ0Ü+C€×î¤#cÎ0÷Ó’Ð|YRùÃÍÁF ßþMF}9ö'Åf™""%lsêYÕ±¼f&q@FÍZݽÝnH}ËïÉO©Ôõ"‚'1L†e›{¾úg%-.9CΑÐmð[Mù Ú>}ZQ 2ßi¡“¦Ò9Ì@0‹üÑ4~Û‘ò¶DpC^,Rb¨¦¾M‰ï2rÈL±àº}%B^×Ô»l{«BX¨ìD„´µAO(Âèö)’†ék¨Þ?µ üÖ6ÃMó0Ëßy(C­«†Ú@Ï¢h:ˆwÊ&àóQ`Ñ 4;^îùÇ„±ŸOàXñ@•n’aÇÒ,w4¢ºdxÌÎ_mîçH“íÛ&…P–2¢î݌ũMÇ`¹¥™å%^ZJ4c˜ƒÈ¤:ÖóŒÐ®Qw9F,\´ì“ ™;¯Æ¥Š*½”ò>Æþĵf+tȕÆë£Œ¾ø;Èi¹õйçrãéÌ>S^TÀ¥ª Ûˆê„—Ö1t ·¾»¯È KL/ž`­TÕsŸn¡a4Sưb°†F¾*‚ +š”Z–•4ï<×âû–Pý˜zcVoþa6ÂoRäI6ÑÌ´Üo8—rÊ“$,KñˆX>Ã//çÛ¿Æ.FS„a•·È—“G!v¡雪™KÕ­Ï¿«|ø„˜Q"§o±"úlÂÝïsÖ€Y‰¢ßi›OŽs_•4R,ƒþö(ò×ç(ŸÅ ‘JB7{{§œvÌ&_Ž.ߣ*( 3 çUzÜ`"â{zs­L´(:­:ôЪHr]Ù¥ÙÍã7 IœßGŒ¨*ì·FÑ|ù,‚®!¶É_¤¼¥#zÕDÁE<¿š8iÈçU+PÛ'ÕzÝl½¤oë1(ƒý~^ˆYÎú]¤âg¬ý3ÄnÊžc2i'³Œj +“"¦‡ÅzWN\‡?zkšG±Ê®rÈ_p«00v/•¼ŽÚQc`56BÅSíÚO7ÞtCõ¦®@‡9ß#¯û¼íÃ(gÈÅ {^SèÜ"„˜<•ü´7•Aùn³ÜúîJ"‚¤úÚ‰@HÎòzs#ÔØË¹d/i(³Ü/eªmUÔ±úÌTVûDò˧¤ è#òàYÈ6">Ó‡ÆõÕÕÅ󳋙’ŸŒ„Ì8”žÎZbA¾7Ao›Ôajµ~‘iÅjå¤Xóéß­tß©Vq­A¾ÜˆÔNÕ)*Ùv#öXƒ*IÞ”- ÑŽ ”Ì#z¹·]]veO$ `äijƱ‡½¢ý)ø½ïøðÂÅñ¼óçu˜Ug5’¢ÃÔ[—…É|6Tœ£qå‡=.ó†‘G'Jñ¹xWË2D…Ä¿ì2¶~ òkØ‘03=âÝÞ¿ÎÉ83ÇAVß³E½ìôVåTHÞG£j tFȺ}š” +aòþÈå H„XÖý¼/µQâïXûhÁ^Ë=­y,wj®ûCÖ91Ÿ‡!‰Öv@ ÒKÀÜdµõ`º˜©FlºeXM†Û(?uê’G%×›`à<²Mqž/Ìú|pvʶ&“C:@JÔCE»·‡÷H5˜r\$Ç™¹Vf—ÿÎô gy›|­ ¦ˆ²ÔȶÒê%gÌÕ@È'›‹ö‰mVG0¼€µ¸ÄÌ2àÕ–ª¬òÃH]Z*—ÊMâÿ±jàv~IÞôkçÂ(ÚìJ6Ýág¦NÜÙ¢ýÚæsPc6h@Î6HÊ-)•Ñ“ÐibŸÄ\$æØµ˜Õ®í,_!û—ªdwtô~ÏÎï<¨ò°µ8:ôä¿"Óreýk»¢8ì÷ÀÊÓ}É(fhÚNXÓ Ÿž¾˜õçl6k7U›žñ¯ì!犬,±‚Õ-™ÞèHt1(ܪ—ôeúÑ)¨¢t|v»R+ó"áýòÑËÜ 0Qwm¶rÐÕ˲˜î¼Ü+@¹?Ü-­¯¥Ï0˜þuö:-¥Ô{ ¬êÊ1²Ü±&YÁf® f™#{+™Æó ƒ86•šxLR¦"w S¤äü‡Þ‰#¦ìˆo‰í‚©˜”Óµ¾ jû“‚©9öû8ø¶ÐN¿Tƒç¨õËÜU’‹ ƒ(¥S£`'åã–[dDW»ýÌÓÈ*¨¡Îfî<ˆBë·-ãѾ”°rD º*¿/’|thQPßÇZ9™<%°7 ÄÔ·ù¹ .ö˜x_sìæP¥¹‰*|~ª±û´rˆwcÕõs£â(}² Ía¬­ÆŽ½&K-±:*‡~c5AL¡.lÖY"C[ûêÌ3‡±V7\R‚©uÝB« … +gǦÎ(*ZÈš×î¯Ì|$ËݹùÉåÀ¾vLʰÕ2Ú«]Oš–È÷sI®±Évù¤××}ñPë‘Ù¡›.ò$*ç>.Eéz9s(¦ö÷¦÷³„ óC»s¼é»n7>~ØÕ78wÓ%ÊÎsÐ;s°÷áp¬/Üß(î»ì:þv·¯ ­?õ%9‘½Ó›®ú¢ÛŽˆRomîë´ ï +=ØÃYÐ\Ë ÓËBQH òþ”é[|œÂŸ’µÃ¸L5oÔ7ø›È­ñ£C.×|&[§2#þÚˆQ>ÃÀ%q·´¿[ðmà_¨”Â:›{z4ˆd×!ìÏ‚ 6ö[&ý•Á³²BMÈëM„“µKM¯q½FZ©¯ÙgX#SÀzU8¦‡7ò-׊KY 2ïu¾‘‰p'j.·vlþ—UE´ˆD„Kå³ÁøÞP®å£oN•†º|ÙOJ4µ¡næÞÿ÷76¥Aq#¨Œ©îT¡ß%÷ü³½MMNFµ!Ý£t§@Ì>½ÂuÇÏÍá…jÑåðÚÆËàgÞèa˜d|øÚµþ½âøVà‰k ¾”üï|1›}ÿúR’ßk+³úvÌלJœ|.íR¹4o«Gœ§íwQ[Åîu<>˜°™Ó >Ö¢¹²ä] ßWhãdYðe*hŒ9™Ñü]ï…1O *»ÂÎHRrɉ³à(Ô<<Í%Éú 5kå´Ÿx¾JŽ¿EM00ísX „[µñH>ŠÞù`™TwSçho&^âÚðrgOÆc39iEO<öëøh!jƒ“̨¡ƒž\&åÓ‰þ@|ùjÊ€Èß¾V¥ÈÏl"CüXêQJ?(ÅÒx{³o¿ô¤à +”nÏò~ö8Rƒò-+ÖÅš~ï5t=["It´lÄÜ ò Ë=g™ ŠW‚’†ÝÚ w}é—ÕOêiZê~È`/n›åü úMßAmŸ„XE¸€9ÀbZ‰|*‰ Q ³–žØ½„k›ÊHɪéè<ˆŽÈ¡0§S†DÙgsí…•­bË3T¥zw|ëU–éLë Ò¶üL¥>…0:M|aà‡ò›qÝÎd;â[Ógˆ¸ž®2?Dµ½§óÒÅödµ_Q SÅn#§ÇNØøâ¡]Át 4a_=¢8h=µØ$_p!‚êÐSñ_èçb}³([ÌØLÝzÒÄHãq'óUŒE’pRþ¥ "`×´6qJ†e«2óKní'"ɲÒǫ +K 8ŠÍ-9€UÙå£+8k`3|ËfŒàd”¹›¹dËŽžE~î„uMQ0=h2„Q¯¥”d(g¸ÙN1²Ã†ÝZTˆJÏ%SJQ1BÎÊŒ¼]‹O'Ü×¢c€z‹÷Á—©¥âµý*o8n8iÙù:|£6[BÚáBŒàZöO—¥’DcdZÔ’› *סþô5ØqR^}Ò’ !NeÞú¶sƒ¤Kr·Ëwïøo­r|GŽê9GZJ³Éo.xØ…:ŒsZMÛÈDUÃRf›}î)¡±K™£Q3¨]ùpm§…Iñ¢PÙ½¿wÄ„³þ0ôj5eô§¾áèÛÊbÞ4µûá>Ý ñ}ÓâV‡®“ ‚ÝG©¯˜ Wúhpe*åð[›öE«õæc‹óÐpw‹‘”Â…ç Ië®_ÓuÖ›+½zo¿ÿÕä‹DwªF2à‰£òZd»šGt7Kø%oÐjãYV!nMXâs1@8œR)¸vö ¿‹±.Ü­°ŠémdHŸÏrDÈ-Äö×™_sÐ’„‡›ãã˜Öý ?‹ò|á$\ç5þmÕ–)Ó4>IƒŽñ|‚ÙBiÛZ¹K·æ‰å¹¬è\"‹¡Yÿ[Ǩ(Lµr?–„í. ÄãvèÒÜw kpÒƒ¥u‹ùGj—ï«ìwú“F‚’C^:§£;?|5¥»v9Ô@Láþ2³Þ0'K +ô„¢§´u¸¹ +°ò„7¯¦-«@a¾"œk%Bññls XT®6祱 3ˆ~0IDËozêféAD’“p¼ÊoåÒÞï,f+=)is«}Þ5Þvš€¡p?Ò]Ôá[²8dËV ›Í„Yº<ñðitBŽØ)CØýêU šý—ZÍSmÇ©–y\—î¹ÝÁ¤-3¶_g6F·xB¯§é¤»Äà]µFþ( MùèN ‰&Ä,ʦõv˜Nþ²å•óšÁÝ¡;ϽœŸsùE/‚ûÈ¡YUŸé×Çy;Ý%S˜HÖs›[^ìúôg$ç+ Î휮_ƒÔ´,WUº5[Ïá#l¸¡©o+äßd¥_ªôì’åPpÁ¢Á#(b0+X5 ¤±4îÜQ5ùs]ðÿˆVÂÒ‚¢7ÿÎ,­?†x`œ}LQ—ë +ƒM¨=,:Á0¯…ý}Ä“WÐ8¶ŠœŒ‹A÷þëC}Û úٷ٥P‘Н¾º”ê¹Ýk¸â[Ó»Päe ÅÙ=ƒá"Žp·¤"<7e#¿†§§ÈCX¸µz%Èoh44~ HÐqw—ÙåJis¹È\Õ:Dïwg©Ì¶—Ù7›Ëˆ;­gL_I¯,%Ȇß@+´Ê¿Ÿôˆ4Ù€qµZæ²Ñ?™QqéO+†ÀíGÄ@ÔkÚ!Ÿãs+t)tZÜßhÒKÔˆ«äWKü¤ã~hj™ccJZ+«Ç~ƒÕ0_,2†ÁÕ<’àáÞî…BdæÓirˆ1öa|ˆQ÷˜UáåÓWç_®/7uçàƒ–%.}íf%Åö7OiÔ7‘’"öð¦áÊÜP ñöÔ µ„ Çú³­žä,èl|@:_£g¾oEKÕ¢Îå 2G#`½õÑ^øÕV^ž•,ç ±§€e-ªŠN•Ëìg÷ "pŽ@ÒÍîâUŒ(Ù¹Yð^ +¦4¢¼eÜ:Úñ_4pDŠã^Q»å2 ¯[ØÅµ¯Ž)\8x 6›Zä*¹"JMüjl#?^ w>=æŽr Wöì9ÁV¤+C¯Û}f^wô˧ª2ºb³wæ«ô>º¨[ôµû Õ…’¶´(ä\IàûºÍ°<Öé%v-5™‰SäÝL­”D–PÝ»y,*8™NÞ›Ç2²·w„Ræ7<Ò‡A¾%µ2³<˜ ýV,½â$Ârßc=U!Up»¹F9ÿÈ%VíñnC~zRÏ;ÄMƒ&‰a lwœŠ42;‰ \®p–ž)ÃO)PÑ co(¿ê°n¨÷)D¥ïèR|ÅŒE}¾a¡\Lj×,ø…[fÍ{™Þaú¬t>Æ)£ta2ì‚j¾Ëž›`9k9Øj*«ò,ݶ1Ö+Å¿|B×êáX 57¬úºÁA0¦Ûyøl.µI6Ïf.m½[ŒÙ -é¨}§™[ýУ1êHåz›ºÅÖVAw”›~V˜íÒØ‹ð¹¢~Õ¶·‡ô¹-œ¦> dÝ ûWöì96ŸQ̱ÄßNŧ„Fã6f˜AªZÉ)W„¼/ý82'õ%ÕO. ïêMŒŠ›ÆT¢*®Êâ¿Yt¯Óò"ƒ¡ã w ãî˹õ-ò :{zµ\€¿só¸M]DT(ÃÚ]j)Õ]¿1ß÷–GŸÇŽíŽÁ‘Ýù¶P妹Jí 5ãånw® ƒxÙÖy,r~½mÔ/Øð^Pˆ`Wû4Bæ¤"1/®LN YºØ$<ñ8Qd* OĉÒ$e[§Tï̼(”²^‘„¢K¾ƒCK¨A:œýî´bÀ­Q 5þ :m^ ©ÂbÄ~JÎÜW¼tÑ” DMyè¯]†QÅ”95ÿ=ÿöÔb<ÛWû BÖ³I? Q;׺@·Zz¬'±÷U³Ó¥Ù± +Gí^&Rw»Ñº͆JðÖ_”à6ƒ´G–Ôó{U„"Îî†ÍÂ%‡”nø•¨âÔ´÷&˜Ì„°Óß_]4~’(?={÷>³Ðz ëðÁÓM*ÅÒ\q¾#Ïs"'äºVϳf£Îrup¸²N”“»ú¶„…oNÅÐ:(´ ÇKè2´)Ç`I°0HóBË££h¯Å¢ÆaeøxèLJßN't›W™ïÏñÔWkÂešžë +¥/GÛMÜÔ0ØÅË›vR´z$Å~ÔÚÁE¨©™GEHCÆÓ„ƒYìScØ[VT5¸ñ—qä å<û Ã’ rÜàÒµ¶¹ pT+ßëBoI ÂP4o¤ñWða¾,jô ªXg~¼'â +¡4§›{Aþ6 ¿Ã\RóÚÅ«+„qºÞäWÇ">nþ±õ Wºdö¾ s ;û|¢€ ²‹ªKeb/;tKGC Òl›©`Îõk7*!VÞ_‚–;f5ŠÝ›¡û&æÓßb^=¹€2§ reßí½F­â–a„IвE"2’õ¶[çÓæ&e¥|Cõ—¢C+TRµ’Æ‘O¸M´òÌׇïÑÌ2KvFÄÆOøä ý3Ø®ûŽîˆa™WŠª‘ì¶2*´]Œ__ôkbâá]œAIhÂ$ÞŠ‚¿ÌÔj{Îþ„¬G¿®tWÝœºçzfD¹«Ý„Lƒ¦B’Ò“-¥o"Tž +ÖµzœG{îâ“¿…L9–½m#”01›Ú5ÊC”K³˜\4UY ƳRצ‹È‹¶Õ%ÎLÝ]oRŒu ÞwJŠŠî'yïÂïǃ”ìý¤nw:2z½ÏØÔ85œ!IâÏÿõû+¿eFœ7ë7ûR/“åAÏ(ØôØ‚ú?Æà®µÄìS“uÉ®âÜwÌÄçì“Ö®\¯¡khñU¹Ë]Žªgÿ¶—áßþƒ6Ž÷%>do .:SF6ï,–òì?Ô‰ç4iè‘£E¿øœçäÊ/ÖE{Ý´ñõÒ3‘¿í÷c…ó’±úakQ6â <"Ð-Ÿ>“\à#vÆ-÷:›MŽRôÊ>_ý ¦±"gú¶'5Vœæ¡ëß|c¨V亲Ùéƒ|Uèüãí,?æ ^Û—0)$:UE„ªïX:o0lÅâí·N˜,òÒ¢V>s›÷]÷ÑÐô*#%?[…&rp°´L|F A·ã,c.®¦’ÉÜEþÌÈM!½0‰+å»K­‘*ÝP¿†Øéܬyã:Ú"›‚9¥ý¨Ú9Û !¥>ŒÍ¦¾¥#ZËÃZÒÀB”d»ŸPBÌvHÄ&°ËX@HâÒ<¥J ßÔ&‚Mñ’’ܶ­y<ûõ@ãˆs@†øp£è×üyÒÌF>⬠+MN3±"˜|4€cZìu.Íà²0‰ÍöÀ…>™Ï] i Ýâ¯á¾h¬Ï”(°íÝÌ"©È]œ¡jTœo‚‹BúðUõ¥§Õ­ðÀ¤´Ìõfù´#ôÈê’TA ÊÈî ÆOÙ\¢¤Ö§¢Š8š<>¨ß°óÞhÆ€cì3õ~ßx¢IJnHœõ„¯³ ó;àÓÐÂåí8S¨=¦$E¯Í)5`Xha‘ì@„6”Ò«Ƥ%ý¸çoMŽATm2!ÓE;šS¾dV¶ù1°î¾¿Ðs>g"u«èÙXÈíIU +BK²&„þhlRÈ|÷‰Çð”j;¬Ý f9"øÎ•ÊM„Tí¡TZ*,cŠ"p<ù¡‚oidŠŒÄ>5†×]c +q]bdSæ!CÌàŽ%d"B’›É²äËú0Ë‚(séÑS×2³YPŠ}ˆ€Ê;¹û¹©(T–|’ïS?¨5.jA_477æøð`¾Í©y„¥;ÀÊBÒBƒ×ÿ0,L6™kqÔCëYû´4%eгè!lâ²FÍ꺼[:)Ž„„ nï>³!_5,^¥ +’Ãdy•-Õ‚g0(6Øù;iÌFˆRúÆ\Zã8 ‘*¨&ÀLž».¹ßˆæ wYÜO ÇÞ‰t²ÃÀØšd +qKõèJÙºVš]3m0Fƒc¤Á¼ß¸ÑúR%›2ŸH_RñÐ=ZÉŒD?~sä6V` ëNGw'"èC7WëppƒùçªCìÏÀ0;ÁÜ”ÍÅqÇï\÷¸îß_´€ñ4òûŸ”!èMP¤Îr&Ãù#çÖ«}¨íõåWÙdá4ŒVJ¸™ÙÛòµ±šX״ؔà +¿‹¹ç¬¤Zá{¹]—'ð’à q!Q£?¥”wŽlJ‘ˆ'@ÍŸûœÁŠ×4^«`ë+W°U)L¡7ÆÁ˜51Þ*¼I_€ºzA¼r„tÓâŸLœ¯Œ_Á¬#’ùsOŽì€°Fp¤1a—Á ,·ì朦éfŸ})*D-v |ǃ°Žà’« ~2‹D¨Œ—†A„©Þª +âgèÎK/A뽫"B~ ÕŸ2 ¢¤íj[¼¿7…¸Mçljݭ˜áŸNïx‘*w…µk°¶/]U†FGaì¹²@¨#DŒÖ•¢­áÉ­ÁòÌ´S´U;jŠ&Ã*Ãgëk4³T|”N»æì…ý ÄV'‰ÄÉZ#V=ྰ4NF2&eœTUd Ó°Ò–:W­S—¦C8êäõ,Å;‰Y?ºüž&Ñiú¨ûU,‹pÇŸã2欬ænÆ­ÏQ¬²göF†ÍÔ)èi^žã¹Ž'l—Ù£pYŸ,¸`ÙJó̰o.DŒç]éÚÍ<[Ù5"ÀbOØt2÷D!goQaÈŠ–ùs1Ç”ü{eòN½%žM8ZrºØÏ¥—)Ñðç/\äé‰O¯/cÕ<}) ¹ý~í=gnùÄcÒ‹-ØNˆOTu¾x ÝfgŸ¹ò+Ä}¢.¦ÕÃQDÌ .T;YBÓ¾£×VÿÌX÷UņyÓ{‰ÿftã‚ã°¼.ÈÚ^@Ó-qžøçy|FÒêo>~5ËéËWTf6~ÑföåW¥ØI¬÷@P]M¥ÙÞÞ}`À/Cp8ˬGõ³Èð~c½èPÈôüËœ0×õ åËe…¹÷fŠžq{¿JR΀¸=¯>å^FÀx(N¬k%è*„³眮–XtüN>W3‘J_+Ur,~€ëî@m +AOyôV”k£\åF¿~©=¥&Ä^€ ž)ŒüÝÖ%çsõ59jg:É‹û+‡K5Á‰”2硳MÚM¨ÒrV€øQÄÁÌÝzÞéÛa„¥¨aþìÙF|sng +dÒèýqj¹íìÕG ×´ìŽ<óRDLŒuð–ܶD;]õKs”éOçãGƒã –¤2ÞARÓ<ÆeBa.Š…¿ßúÉÈÞÆ~™0?4u¥K¼ÅØ­rH²ÊDþ޼””}3-BðeÛø(‡ 8éàhÁ!·­'ˆa™ÑÎ\yÔ[ÞÖK¢‹^Š×XY%¦WªGmUçùI®Té)Y¬ßÑ%áƒ*4À%âPêöhn öµ­zç—¦¬£QÍïK9L…º€JV•– {8ËTÛl¥”Š'|`çÌ<â¢]ð.ú§)•¶„~Ürgøx|]§Yb*Ø´I—¬w/(”ϼ‚iÂw/ô‰=Í<à5/*ßìõ•tGÓV«u“J¡LH#½èƒ³è"z\©•êˆTHø»ªSëž7ƒâaù©™Æƒ(kV³š·Ÿv÷¯E`x6~à … ªÒ›„Î WÊòzÖîÖt­å4 +µÒa„?š¡äK`sxÂØlì$ÖEäߘ7Aèyrñ€J?Â,)oö*«"ÓÃÝÔ\p'Õ/<¿"þžnÆt0mØX«ñ,Dïÿ<×€‚6s¸w¹_”™À}än뼟ûy+€0vsl“½ìGâ.rÇ„Èð-¢9Úo|­|ÖïÍxåºùÉQT¸Û½âö\}a1`³‡º/£0*’ìêú£À¥K´ù„~²•ìx»~‘¼Æ±LvÅiÉž]Ã’Íq„¸ÉãÜÛX¼žíÄZhÖÃ,‹‘»  Ã!^Ù°)‚ì~E'¯.Wbû8±c….wK’¦¨4Ïol½ø‰“×x³ì‹¨„)tùV“0“{–R4H¶it5®ož)Äý|®¶q’ÔùËèùîg¯Ýb¶MQ=ÓD Ÿ>|Cß`êä0‹;¸ûãÿY +¦õì‰A;"Œ§¡ÔÓªC%DûsŽiQ‰î›Öÿ_3ΊÙvÓÿÊÁ²ÐSg‰Å‰›c_Nj¥{ðüv¼Ô •Ñ yY°Šl¼,ÎvA»±&¾€ïÛ̓k׈ÇY~Z¸]£ZJŸ€÷>·\ócT’“VhòB© +oÒ':뎨!uß³Qœ~>L|Š%ÖX¤‹"ŒöŽàü7KaµŽƒ$9y5(ø—軀@9[T²oê]\œ¾3ÓmÔ§›¥hž~$ ¯=pe°M­Ìz”ã=‘Rb°üc¥©«bIלh'EˆKüxDgŠ7—Ü"œüTî€Àæ8t#…‚æëåSH×B;„…šˆƒ­Z¸©Ê‚˜AþwùUÖoƒ‹Š>íà¡C0ˆàج2cÚÀí³¼Ñ¬|ŒÐ¼ò§w ”Ù Y¦ ¤Oxu3qñ5¤LØ£[þI‘kJR•Í™ž y,«”Á'}A’âQÑø^#›6›[ÎùôÖ¦s"³6a.?vá|M²eÌ;L»¨ÜW±õ;ûê0Ÿ gv»<Ás_à»VBCàhéO½›°Î4ÐÀ]¸£#W" ©3jRÏ^´¹i™¼Ð)v×ñÔÊlûA#ÂZÛiP­¯`Æ*ä„_o*[l,´TkÇ…JÞÓºäç¥EnM8ÅezîÖ ÁÈ*dìeÝ7PÍMcÇ]’Y¾ÖžQ”š ú–Ac ”H +FnǤîã0rûß{'ߎ›6r”‚üª#Íga +…iWÄó¾3 g€ÿ Á<ô‰öFZúŸ8Ð2:ðel‚,$cnÌ3îD¹„Þ©âèÙq"éš+Oa~ÙÙÀÐp¤ýbp°ßÛ¥g°¡ìYz\°Yÿ¢âj»ÌÁÈ?ÒÅ„ö”³°—f–8A…A>ë w†¶*к½¹³?a\ÁKí<:ܪ /`8ž”øjBUS1:ÿht@=]0ZÛu>¬ŸÐ‘ᆵ ¢ªs$9_Ñqù³¸Æ€á”‰Gµ%ªÑøÑT—±¸ +çè´ç&S%“ŠÞß’ö±â[ÃXúÕ«H*Ìö=.¾À¶ÐJ„¿"tÛÿ +P¥—néƒm`rM-\*Ø}(Þ×ÄùùÞ¥ë<Ð?(§×²÷/mú •ï%–}dZ­‘¨rÍá]DXJwxí{ºÎoEexòO¦ú½@®÷儨oñô»D9—aÅiÂÁúZ|>Æ2©‹ÄO4sôe ¯“Y9ù7-ve¢qöšà¯¾z&´ò” ŠÅU–¯«…8DœÏ3¬2;WK1!ãc½50èIŒÑæEí¢Dð$K8þë÷ÞØ|øßë +© +´›ÌèÜ?b ÷+~a æ$ +n"‚"Rô{í"”õ¤ôØHa^ž!ö§[LÔ ß'“é—„'ªùã²dÞ°ñ2¹Â_̤«È{€,̽ÿÐôŽó ± ŽG `‚-ŒSïîìr )FJw­ÃG e´Y‹ô.ÒÄZx7Yй²Üt⸡ÌàžWGAbѪVdßcóýzÞ×#~RÀ(S0ù¬„s¼såΆdnhÅ8 èÝfi bj„ðjƒÖB®+ 5Í|K W™ËS§j‘†¹«¾åœZ뢟Œ~„Vøƒ²Ú æ!¯˜ZSiîçÚ³áõL§tb&G®¥†œ¯l¶2•ŸIwxnä% +ù$1Dßî<¿ÕÛ-Fž/Ë¿W·’Íã,a¡ž•½~û_s\ä´6r­Ù×Z‡«çŽ­’©üPù=þuDI`³]åã8ÍL¾Ö™¹®'µ+Ñ ëGà+MpŒþJp¿<–°gÓ“ã/šEŸŽrjŠz €&dí]Ò¥ƒ×²*¯G×¾ÆeQÖ7Tfúr¶soDpÙ^)\¿ÛÐϱŒl“Α0,vbYTÔ !çÌ‘™YbÈØÚi‹0µ?—ø YßaÆß-/&ÍÿD(Ù™xWö¼jJØ’nBðtJ°#nt¼w«bƼ}YŒSК{°mUº‚U}†Ç%8¬­æíIðUêú7‹þ{âV‚B"ùçÖô2`©fzù¨-¿Jcx`=™£ôÞ¥•`LrnN 4´äa$šgÌÿ°|†oÝ%»Íic°A=òyéõñ_æHëI"Ƹç/ð_Û¬Hµ%|ÌÀ>5YÕVMs?ñ(‚Å@kŸŒj¬¡ ©h^O±Ì§ãp×GƒÛ&Ô¸¼Dc°ŠªÅï~̧D¥4( ¡ !î…‘†Û_fM®ÿõç’Mv/K¸zš, ¥ÂG‚kÈ”\ÞÐJbͦï\Ѽ‘^p€Ñ@*§e†Rò¡3ì«(J’”y¬Ve³Bßî°ös©!“: ˜Îð¯ì»¾«­Û àõe.ü0é€]? 9¬’þÊ×T³øõ܈Öv‚°´\®l›#ú©Z.lÎ1­6Î_½ªÒ ƒEX¢½”TU°Þî¤r&¯­Ió›ÚF)Æú¾¼iŸ£Å,3±±Æ….t +ý¥ ÖÌÄ ïœ uåÐóýÂîàßL­6†f 8¦v*1ÑNð<Ú8+{Á€·U¬%胩ÃZF!K6O0?\§Íý,GÌûÖU臑\õ¹ÁgšñÆ?=vy&‘~°¬œ{®‘åO1.—ø,€/-ʺh²¶Ôí> endobj +721 0 obj << +/Length1 1647 +/Length2 11596 +/Length3 0 +/Length 12440 +/Filter /FlateDecode +>> +stream +xÚ­veX]Û’-îîÎÆÝ]‚Kpw‚o\6îî.Á ÁÝ%hpwww‚CÐ`snß¾ýÝ÷úO¿þ±Ö·fY£ªæ¨Y{S‘)«1‰š9˜¥ì]˜Ø˜YùŠVv&®ÎªvŠ|òLª@ Wc[ÀÆ…@E%î4v±r°—0vò´€f  )€ÀÆÇLJ@wy:YYXºh5Tµèÿeùk ÀÄóŸÈ‡§³•…=€úãà hë²Ú»|PüÕ€@€‹%`ne ˆ+)ëÈ(Jh¥5Ò@{ ÓGÊ®&¶V¦y+S ½3`îà°ýÇ`ê`ofõWiÎÌ\¢Îc€3hjõáô0‚þ‚  “•³óÇ7ÀÊ`ádlïòq.+{S[W³¿ø°›;üÈÉác‡ÝöA¦ìàìâlêdr|DU–úGž.–Æ.Åv¶ú€æ;ÍL]ÿ*éoìƒæu1¶²w¸=\þŠe˜Y9ƒl=?bœ¬þNÃÕÙÊÞâ_0œ€ÆNf¶@gçšî¿Nç_uþKõÆ ­çßÞïúϬ\œ¶æÌlì1M]>b[XÙ#°üÕ/2öæ6ÖØÍ\AÿÄÜ€Ní_=C÷‘„±™ƒ½­'À hŽÀ¢èàò@û?S™ùOäÿ‰ÿWþ_‘÷ÿOÜ×è¿\âÿßûüïÔR®¶¶ŠÆv ð9ø4Æö€Yü5ll +ÓÿËÕØÎÊÖó¿sþ÷ÝZÀdýœÿÿ#„¨½Å‡BLl\Ì\ÿ0[9KYyÍ”­\L-æÆ¶‡÷·]ÃÞ èdkeüùïóýpbeý7LÝÒÊÔÆþ/5¸þíÍþ½†Ýþ®€ERRZJ]á¿™¶oVþè +uOð‘´Ìþsñ•˜˜ƒÀ›‰›ÀÄÎÃúq?®#;§ïÿ#ìßDlÿZ+»8YyôX™YYÙï>ÿZ}ù7I{S³¿úHÍÅØÞì£õþÓðlêêäô¡øßÓà£ò®ÿ¾@ ÐaeÑÁT Ä:=+Ã¥7gp\B¯·› r0TÒ ^˜PíÐ埱ÍWaôRÊÜ8ÉÿÖê¹pzÝ—¥?îÆ±¥éJ^äùRÐõä£oP·ó0±” gœjÅx_ÎËoAér³j쌫¨¿ÀO¶s8Á]>ÐP¸å`QÞƒPüLÓêã±¢5‚aÔœœR=~¸§é躆îÙ'døO%à…LàøPXW£Â;SAþGÅä\æ ×*IgOzÉSë9m©Aæ6ÙÖòIA»€œüþÀWH +ï<ø7…x°º‹zîÊRïœûÓÃÖäb„»EŸq±Mw:}NûÆA†u’æmßòÚ­fN«Äß”pçf¬­.¸–ü7^ŽQØöÂöÞöJÌîÊ‚ËLk·^‚S·ÃÚÕ^—ç¶dùÁbâ6)BRÊ?<Ž òŸ"OíÒ­ ‹I ¢SwÚ‡Y›%¬°Qk¤—$¿ÌÀàdÜ˔95.]¸Pì„¢óBOužÃ€æ5ŽDû¹ÈZ_Å$Žz^¡é/áó¡a‡éÏ &çÙQðgB儤¬”5€^aêü“uM*ÇÕ†Dâ€:šÁwi˜!(›vz0ÌíŠä«^O)m^ÇY§.%ÀŸãl—/Gí¥¡ãðmNÛw¬çŠ3ar‚`~+`´b\<, Œ]’P‚çG ½Ø'Œ p!RDNO‹p[ËjyQØË¨™kP¢ ¤¼9Ÿlv¡åó :ÛžÇiZO}îsÕÊRwW²"ÎYá±äRý³^~ÊwöHqgÁ.†=˜a½gÙÔ ±Ä!z”êgpTBÊi Ö;#MâÇv¯’·™šf$’H11,£œMÑL,Ú¤=TW¥YÎɆLz¨n› +¯}”øÍhN·>"Wøð&uÕ~DCr¦_¹5øK©ï<º$$WÕç„£ý·¡/Õ;QgÚ_²nñ7 + /Iªƒ"ÙðÒ½O¾sêÓ ‰æ|Vk„æY&ßSºÞî ÅŸ%¹‡MÇÐ9ÎAÉ_‚[’âÕ.W tÍìÏ¾ÝØ¬‡Ï÷x3ê ‚«Ì½µ¦Ì„nRÝê"´°Ÿè7m@ƒWÀ µÓÜ`—×v´yƒÿlom4túÌÇߘ*ŠÐª‹±¡²lëX;c£’«ë¿±‡Öœkg|ï ‘H{óô.Tö}שּׁº•!x\°o•…Y4ÇätS29Å ÉÅàŒ80NÙts¤—ù\ýòƒ…¥¥F․Ù&Ú’.¿l›ÒÆ!eU„\ë ï*ßþ“ÒF@µ¥m˜^}fCëí¢»#Q ׉7E+¥åÇ•ÑÝ=Ä’3.¢ß½³‡º›9˜GA77c8™œ­*ôÒïð?Ä1“ª,±Uq±Ly7?Éó‚1í’ZЗœ]»ùyÈ‚¸„T²¸÷ÆÐ7îM.†·Ec(¿P ™±é$µÖ{EÒÌÁÊ.ccÑD ˜Q”‘»T^”Ïg¢4—K Ú$=!$Yɤ[… ¥PIfxèCòª¥»àsÏü™7$ð&$ú^Jݸޓ®±}Ë|†{€óÎŽ/XÖ嵤 *×Tqe#Α¡…žøƒ^çîî8 ¢€â‡ÞRÆŸto›{_uúTÚ"L­·`˜Ó¶¢P ì͸e¿I‘F> 6|žÛD)¬¼Ãy ¯Ã?†òÏBD…”„õ,Ý­>ï0ÃaòMtˆß­SŒrNªKBTŒüb‰Hèý _L?µZYH|P9ª—Òfœ’XXˆ4ƒÌôÐ B’Tö¼Ænú6%ù¥¯QÀ|ïÀ"ÇôÏŸÓ‚Ï´ž]TŒ2ˤ(…W<{ ­DinÆZn<¼Äçó5áǤ?Z† 0­É㮺[@lÏdj›‹­óz‡q?ªDråÊœÎì†Fö«NýD  Ñ~ÇJrë‰Qãu_<|Â~Œs7bÝ’¸ÙµRchwJNXgAdÁþ&ôW-M4¾¬LÜU[À Ë{™JÛÞ)²µ™y‰‡õÙ†çR•ˆ†O¸¬ó¯Uöˆ·ä…­%48ïymA¥q@T¤ax×sTõåÿžŸzš1.'&ñû&yCœ$/}ÿÄq­´õ’‡®i‡Áx5ï-@õ߫HI¿'œã÷÷²6 ·Å—µ:ˆQPÖÏŸòþgÏo3ƒ (È”LË-bÂd +a`‹cÿ¸Ã’7\‰Ö¸Ò%1í§¤>H|€é +œŽµ|HBÀçýJÍ»‰ +#îÕùH$ËÈöÇ_)2¯—éH²‹-õZùq¨JÜè80c”¦'8jiKâ8ÝÕ‘,Ê~¾,bn;Öi¤¾( ¾oçñ0ÝxÕŦi‡ "¿°—­t™Ò¨Úƒåpúè‡ a˜C¼ú©Áí ©…ÁŸé¹{©…˜~ÿi¤c©JÏJçA»ùsž¨H†,QÒ¡r4›L[=~Õ‚ :É@7Ò÷ãÉÒ]—èå¨ÈÉõUkͪGÄ:ßÈýè_àÁÜcEÉæ!„îBT½­Ò,¨[=q_ïuVÆû÷Š[+%荒YÆÍVawÚ¼Ða¯Êmò—Å’Wv Ü +©<Å€WC·5œÃe4,qÜ8_¡î–“Ä@À/yMÙw§]jO¼“ß?Ãá³›¹ûØD-ªß;³ïxùüìMZ +›vSC)4Ú³'§œÆŠ‘ŒvÑv+zÓÁ¨gÒ‡˜Ùfæ†<-¾IÎQпk·kFŠØ¥’é~ä%'ìPÔcî‹o#´3$šâBác­ªV•iXÝ%¤QxÞ®ÆÑD|×ôÂr— „tÂëï0Œ–AofÎõ4ÈûÎ8“9Ž+«í5òU^,¼Î_³ÆŽl*°\`E˜p;Øì€ w-ñÛÉÐVØvéÃf°‡ŽMØØÜÅîýxbm ýîh£Õ){#ó‚N팊'»¼tçöª°Í,Mk4 ¸“~ÜŽFcp¥R[^~¢Ì18¹1cu¬È;ss}wi[Žu#ÕÓ'ìÀd?X/‘Ô†¶òÝÕâ…ÍÓR»S±’3î ‘°ßp +BQûÌ‘ +þ§<)¢aw±È¼ì^ ;FIG9*°)˜ðÉ2nÉëyubKÊo—6åĸ;„Q™sY<´9)Dâ}íc—Édgïœêð‹î¾ä©”Bø˜³è„=©çœn´SΧR]’Ñÿ>ß­-¯H@èXÔGxYVNïàÈ;MòäZ“sü¥iŽ„Çûæ„„²éð%…ræ8öA'3Í`ƒ£á qé&¢Ö8†t^DtÎ×¶o &•î‰äF/‰SË+’1%GP•²ÆÌÁê}éä0âÕ<^x>9ï •ázÑ<ÄçÑ“¢€s )[0¼§H”ÍÞÞ»ãí:zƒTáÉ»B6'\ÔÕ6mÞºœÎÜ&c$jO»-Ð&à!Qnd|éªQÜZ§÷Ê#S Ä$ø¤wa€»Ã¡½›½lz”*(P7"øMó=‡‡(èM(Ì<ߥ9غ Ûj­êÎÖ¹í É¾ ;F‡\ß´Öy“\…xÀ ZiÉY^ëúÓWplcܨ¸ô¦k Š1ù¨‹ÝV=jÛ–&QèÓÍŸ&Ö¡<u Ž`ÙeÇŒÙ>iÉ-æÀöËZÓ¾Õ?b¢f«ÞPÔ"V/å » Nü†í@DÌsmÒóóLzø§ÌÕ4Æ)îÞ9Ñl&²Î÷ƒŸ]8ŠÑò“¢Vöø«ãÁï›~J»¦BŸzÂ*rãõNÔúhª}ÀÁÁ²7Å›Á“}fˆä6{#ÏFؤ:z­~0¤MÂïàÅKªßÅÒp=ïMl2-Òçö¿DàPÊök  WŸnÆâÐ.€¶îó¼*xµ/`F¼ûº%ôÙlÌ-˜ïLd„Š&ÔÅ"Acƒ½ è"Þ¶îÃŽÇo»£÷¿u%#[cŠqùB°Íe§x´)Q¶“l¨NMðÈ)Ì%"›>¦|y{÷úQ}‰„óuöüL“V¦¬ò–¶¸^„ µ[,úšŸãMæmÞ(¢žê]¥ot¦´-s©ýa+ç¼Õå‹`¨âçöãælâ4«‡×e½N–¤É¢ŠQîLÛt­<++bý£ÎBîך¸­†Â_²¸0ä+~o‹ËŠ@u3›…ÌOWØBHö&y&ÕúïH…nü57VdÔVÕƒYÀQß\°ŸÝ´2 ¾‚˜ñ&”/wηÐe ± ± +f]Üym̉±Ý^G j^†ˆ‡–ñûò! +\ÕžzН S„ê£/©Ë:õm2sg~]Dóx (rÐÆÿVŽêúÉû»f1ÄÌ“Oµ…®­dŒPyOaš3§Bº<=¦×<Ù}îÍæn¾™‰“h£ÉMG-”6²I‚§p2AÿÎzªð”TÑççe;øKðjÞG¶ÚOÎP¢åÛBÒ“v滩Å1tZÊ] 'uÀ)¸åveÇwÄÂWŠÁÚ‰ù- –é7„ €l{j£Û€~¦_Á]5“‡ê‚‡_úì¥æh!ôÞûFfG‘Ö+M#F)ß@þÚ:=̹¶a¬Ì {-iÙËóg%˜|BzP¥Ë¶öT•û°éçP=×å׊&™ØãZíµ3ªTGÏTS,IöŠð ÎYNL’bvãÝ"µÂ xéŠdï[æÇú@a¡@Ö=>ã7`C²uŒ6²ðøïëê½Ï¤¦j§Ý4sIzsL‘d™~:”Õ@·%/.59Ósž9Ë`: Q4ä%!Wêüݒɽ —ßP\!“D°è;A‹Êˆ +2x«¹&Þ E,;{&!?&¿ !3y$ð{Vìþ±T€øLÌY¯uoÍÀ8¡ŸÃ÷ò"jØ@aÖ­!Ž|>y/%˜ùê‚òWïoycöHÊϦ’s9—(uÈ™=>··gKšÓ¯všÃÐÓЯSÞH8èí”ôú°Þa¤r$O5zTƒ.ö]éö8ÿ_­ /ñäåðD𭇊#ÞâH¢È8Éé­9§ÀýæäTðŠ2Õš$iI™3.‘¨’/E§v ?à<÷›q’”¶fPÞ«ñŸÈ9'!Oì¬geGøíH›3åëÅ~ä;Š} +¹t;3¨Ó•o÷—W÷jט§$«7án1šà?O`Ã_W£&f,÷QžóÊÁÆlÊh¾lŠ¢jÍÏQ¦aH“„Çï»(— ê«ÉŸoߟ>L&ð+‚„U‹`Êä`D0§¿Êb2¼`£IÀì‰ê™kš;s%u8/êr(؇½`RGƒàGAþQꬓXÕZ"¨É÷:qì¨,M”j‚ö€~$]ÏhàÜíäù4“‚Jz\êN¥æ lÃm ÓÁ=!ÿî˜ÄÉŸ²°Íæ¿>éžSÂÇöô<Ó²Œ+7Ÿ„°pk›º¡î”÷¡JãJÁÏÚ¶¶Y:Új^Œˆ]š µkaGAy­žº;šiec„âvê&¬æÇM©àâúÉl* v°¦É¯]gÿDµu<7“øOÃ’î™Ö +–h ßG\N Ù1Pkõ|Ú¦«sÀ9MÿðÙìmÊá…&™Ü`9²€áî£å[ÌSþª$1œâ6ªàþžúº·Ä]'ÙU\¾?âàNº7çsóìãú…PŽˆF ‡¯þŒñwC@ó}øúŽHË­îg»Õúý;À0W9Qú ‡±ÉbL@ŽãœNáÔVïFœ?r¯üûVo_ëÜú©ÈèéXí(úô•Ú³ðøì1Õ…u $´Öã%¬—âëÏá¥ýnØÃºŽÓì·Nº¯Æ.çÇvë_BÙÙuûcˆO`ì’qFüýЊ°KlVZ;NëÉ‘3IéOkv¯ËÕé¡ ëYjâH€òpŸ†.ÐŒ^œü`Ë­L äIúìr„ФÕq±Tˆ†¥¦¡#Ým°ZviûÙ‹–ô]æë8èk—Æå{Èùe“ çm +Ê_ùz7ëœ;.AðÙ]&¤vñâ%ÔJa-ëâÇ('O¿qʸ ²ýOÔÉé6°ég¾±:âQ1ÛS†0V£{±õ‹;B!HÙS'± +åMŸL­ºô¤äÁpu³ºü <¼X“ú{³±dJ¯lpɵJÁį\„Ð'9ÿÉå€;k2…Î%!ª,ôh;/e”Ö–^ºb=^¨ÚQÑ:ÄIÝM°UKˆ¯`»eàsòQ¦gb»Æ4”ݬ3—HZ¶ñ:ùþ·óÝ~NÜó(òÙ*ãôBçë§“¸Ñâ“j˜ËCwOfðm³]*§b§œDÕûµT‹¬µ>x}÷M˺ˆBž NóÍp=ö“0Z¡ËExëýChY¬Iðƒ¿ýŒ"ø2ÿÚ-ŠH‚h$— #(øjV«UgV<ˆËŒM;.†àДä +‹­À“c%=¨ïTÈŠ¨u娬Ø&cD=å ðÚ\ܪúIÔL ­é p–Äh4ç¡Lzó–Çù`tudá ×ÞF¤iŒÔÒ^Ñ4 h fSFÆ`»\>õ%¤¬ÚÜQ%gumÚž'Œþ–dÊU&9%ä\H.ù6u؃Phå9Óäžy¾í4‰»ÇÝERŽ“ÑØL])š‚²{‹8 ɇôÌjì–¹0u[þ”ŒQqÁÓ)Q¾/M¦dЂ\»9 Ä HkÂ-ÃKŸqÈnh*‰Æ=Ôóu8 +Jþ·ðÞÛŸo ¼èªÎâSÃÙËÓV*É+5{æM¿A‹ZÝ¥’’N.òÝ!é•´èMk­À>dL!V(Ö«](¹‡öîóÔÛ-Ø'_º4–ÍsV!“½oÄ®=›=‡¶Ÿ’`ÎM¾²TÚRQ§á~e·€åÒP*>½Û§”®y–qPq¬…Ê%¡‡/ +»¸Ÿ‘¥í#UEº>-üù¥r¿ª7ðV˜Ã(3À{ +Ý3ÿðs3€nxs#þÛ±q¾'%yTä¶™~?.Å’\yªÛEk›ÈÀlšUýS“Ø ˜Ó1Ø}f†‘¾>3vlåü +˜âoa^•lü/Zþz—pu“£Ùœ~PP¤QM +º/N(Þ=¬¼À|L2œ·ù™ø÷޳ÁgÖH¼îØ«“¢¥írÂõOdc“Ì‘„eòx|¦åKVÏkr!Ef¤qû)mÔ)»ãÂFàÇqŸl]o¿TCªÅ§ °3œvëHcÌIž?Ï—âP;e%(ñ-R¾Lø§”›‹8 Û€H{ñ ÃcL˜òV#§râðÞØ(邦“Ÿ¹á%´Gu¢UêvONô±§€®ì·¨è×­+mK }8 +†>§|;Cò}UC›¥wìôQdéÈê•y2ÀüúŠT´ŠP¯;jX>Íß7³gÔ?Ifâ)×ò­pýóÜd!÷ç˜4*nR›®|{—àØ¢JNRn±ˆ»CsÁPÇyƒD@˜Wé:ßo[Ò¥÷²Þ7û°í«·g9Ö¼ÑF¶Ã|n»Y^M¨¨Ú”{ƒŽ¼©U4·l<¾ONâ«â¹¬ÅݳW!Þ:ô~ºI£:·Íé€LW¼np²ˆG*úæ:^lRqdä’#iò¹Í*w±¿¾X¥KO“ òÑŠÐQ(æ"hÞfñ–è=\Of„5µ!KÁïøÎ 8HVùNy‡!ߥëDÖ`¸ÉcC—p‡ ¼f­¨7f&Í¥‰NóqöÂ[» jéÌßüíÉ)tûÑÕ1,’ ¸% ’Ò%‚-½5 +»kÚ‰‰©ƒgÒð[‹Ùô]ëÑšõÔG×6h•gh¤" º[ùw0œbkh0Ýÿx! +Xܳ>E¶ÜHšÙÇ[„újëNRåiW/ +Äï%B"i}vÃTŸõNþ¹v©‚í`oÇEÈ"Ÿ¬jÉpá·-Çb’vmàgïý]Ì~íN¦AÏ8M]ÝÙäíÎË¡YµÌ‰ÃóP ÎtaG^?=R·ûè"‘ÌÎd„1×ëC}A™f©ÃÓƒNÅ+~(?@ih“")AÛõ…vÚÃé6þÜŽ˜¨µIfG$O†É.Á +Œ/köáGNJ¨³ö]”´L[èI/­qÀ»^”`ëôø!Ìû0„×s—þÍp×ú&}ú25ù0DËè;}ﳇeÉ‹ñaãcŸViư{ÞÑÝ ôð;—"O&FÚäHEì­àO½Æ’q1¼^É«ëc¨¡Îbéc3•¿ê¡¤ $­/ +q‚;îÇ4‚Z€$ +ƒË6K´¶$€TQþ–†‘ã¦Ó1Gø»Ù1 ¨ÓÚyÞl \8D7޼çìÆùánр̉BAz·ÄÎ(]ßGŽ6«C×½,ê–wÑîJxF‘¸jž5"|5†üxtˆ-c>©ÝÐ +ê§idн"Daª¢–tÔ¡ï5ПX +/ìuKVg`>®¡ŒL›`ô†}õËYèõ¶#¿pÏ­6w™)P&‹Ï}É(´ìÿÉÕ ÃG³‡Á 6/Y.÷Ë[oNÊÖ2 F]êÈ)uÕ¿òÏßòœ8Á¬%ɰQÔƒ„dvjÍtœ®Þ7Ê?þÄŠç¥pnp2¦ù˜%dø³Ÿeœ´RËÓ…ãä°Ì¸q;ô=DmÔ 3üÆŸ ?iwZ®øCÚ,"+ò€]†²—¦2_­Ç]´^Nv9e(#ó>ÛLÂ(»ÙÓ•d.VVƒq†öò戶òÉÛ«—‹R.¸/¹äãÎGzQ£ábo…’aHî†máCÁˆ ;g<°à:œ{Ì¢“£:ã·ïÂRÉQöß*i!íWIÃhV_Ûér¢¥X@˜–Øë¹wò¼¾nòì¡¶!M5P£o¢Ÿ<×¥;ò&q™B«Â'ûXs›C/w4nÐ[ðl‰Ë¡?“î' Ô-„7›ð'Özä‰X±žc×iûT£:dÃFçë‹Ï ôãRÑﯭ]V+°F^#¥Lb9ù"z,ÈüGní`x°ÃÌ̯‘-â’°ÓžeϹñr°m÷¼EË„»0^|%Æ—¯l0ƒAÛ+í¦x}8·*YMÍÁ“ãáÑã¥1•#UÛ`+ôºh8bE¡ºí’nÕH ƒ ¬žaUmÔ¬ „Tj·ÂdJJ<Ý]„ˆ´“¿eXAdùÊåml,˜ +ï}.¾‘‰Œ‹4å–EuîHðû9ê=JGš,iÇŠâ9ñ˜jsÓ:EH;Ü›¥Þæ7§, +BU²ü¤ÞËæßÇ÷޼‚…ž­3©VyÒàÈ|͆ÎqxœÃ ÞˆÈüªÏÈ’Üj±6ÿ:ÎØ¤mW|Z­–&™;ÂQ …šLÈÚŠËcê¦-ämÝÊ¥s>ˆk-¹P §õ4’FkdÛW)Z¨t ’mêjOÚ+]h©‰gÙ뛓Afw*ù„à}w lð¶éÁ’wÚΨY9¼ž½ÙcYOHŽÙšÎ‚í¯¿¢ƒÔ”hSˆbØd~Â(}Íô‚/Ž<ÌGÔw’]€WÏ⎲™ª©VŒÅ˜Û§¾TžDØI‡N†¿ š¾!¹wÖ®1‚2fU¨Ïì­q0‰òéÛþ˜ÜÙÔ"(0» ûÍXÓ¢ù:ºLÇc$Õœ=æjœø¶°ì‹†Înú¢¿š[TS†Ìà+P€aådžÒ-À>‚"È5aÓxÔ9ÿH~~@ NäF‘‹YS8i¿‹Áò÷Z Äל¼’µP©}r„ùþÞ}ùW°Ž{ƒ;µ]²14:sÉ?óRß©úÃñ5‡„ ûÊM™XÜÿs¡>–NNÂPU‰cIVý¦ë'üïÇ#m”+¦ãŸ«·ª!ξBÃ[ÅÈåìT­¨¹9<åj`¿CXÒ•ë¶yl<M˜&<«M,1Þ ÓC¥1Òö…†«5û®âK4n)7›^á\¿N†,ÜÖÎ-¿ü¾¨Ìè£öÍ…Ð=c'rlfÝÜõw§Y_2ìk±ÏnÚƒSñelÝW[¹W¼Ô§å’¦¾g‰ú2Y`3Z·X)u׎´ùìØ'l@È2¬ð=ð%iÁ +â(à¡ Õ!vöj8õå!Ä~}f £2y`‰ž¶ÜÝŠ­-ì\l»Jdаݘ,€sˆL¡Dí³7› è8Ú,êS›ˆ›hòŠ_‹gù„y¯7F)^B›DBJí…L0%U{ShðkÅ]QϬ9áxl1Y^4BYÈWεP¥$_ö0X#‰™#›? !~¡KÌÌ%”–ŸÕ§…£â¤#ê }—=[ÿõe,U½)ìToEz¯r¯$ÿdœìŽõ#¸ûº>@{âP­Ï€uß6¹å Ÿw¹2ª>À=U‚½˜xu˜ÈXWWó ¯RÅ#Sus¸ê¦ýD¦p2Ä|é µß©{¦;C¢_¦ñ¬‹WÜ»Ð4—9øì¶®²ù„¤n‰€TÖ͢ǵ—^ ¢,Æ­ëz‰, z‰úÝ^CH½¥ý:m«8zû Ξs›´¼m‚DÚ›°¼Ç^ŒÒŠsÌÎNÃÌÄžÒp¾"aÔ½}]9–Ïn#,çZ·mN¸K¨W]Ðʲ|YÊgI¶­äy`…I{Ó4²\sÂw7œh"ÈÃð3¤IYN›ÊÓžQôúщ® Ì„7Ú$m^Oì…Üi”Æ7Sx;O«ŽÅmg¨ráEýï:ßøØi÷Èû'>¦òI7å꽟Oux,zI)§R42nYÖOò×ìö©˜^ Ï?bÁÅ-®Óš¡îŒ/k©–¼ŸkßîÐÑ8]Ð^DF‡ý‘“¥endË’½c•8&öPš£W©½f›É ……Gné+ßwpXäŒ{µ|qå§5sÆ=ÐúÉ r6ýOÓ`;Åöç9Ý.£6’ÊþôØõ/q:—¤¨Ö ÷o«¢ìŠ[ªÁÌ_sœƒÞð'(„ͨÞ7¨¨ýÏËÈLûwT*‹ZÈ<ówZnöO¼yŸí•ëåÃÍmزQ#ïֻňª1¸ðšO×UDŽ,"+t6HÃz³N{ßKÅ$Ä …¾'ΡlbWCì5Ï‘)7v¾âó¿¶£Ëc )™ô¨æf Wt)²ã,ž"w˜è¾%ïñ*6©ªßZ„ô­8e(hJëfëN“¤ÿdvn;M1rÆìÂÁØ­œrk€Ð´Ç÷¡¬óÑ)ë’°^ßAd¿Ÿ ¼zê7„ÏZð?·Lyê ,ŽãËwsn³e•Ò34£xºrÐ-±“sf¯ôÌ + +rÌ Tò¹mÎÍf¤Y:Y[È®±!Ì>t×î¿ÅŽ$/…C‘øjÙ„ú‡«egHê”JIôœ½‡M8†iŒ‘ì’.¸ÍÝ »’n]íúRÞÂËŒ·~ƒ—oúµ©Y€]T.>­Ý’ê5å^…ãýɱ(–ùB~Ç( «,,ÈbJŠê tI<šúæ—;ŸŠ»Õ8$Þøuý¸®dJÅæò$c÷@Ð/žMìÁ6C/géf¨²ÅÜ:?0 ¾ôso +*&82þb°ÈFêcð½ÅPŽ™t ¿¾30˜WÙ$}í¨•2 +ãvií:Fß ³$[wBDg$0™Ã$: C¶ç W·Fæ"§™¶õl±ZcB×Ñ©ÅKzæh` ¯:1XOw{˜ëj–ƒÊ²´Lê|MõºèKƯ5~F°æþóàý§ûg(3Ë>T¾Òq+dêéAíÞâ°ÄóAŸ/ôÄCù¯0OE£ÄA8ÓÉ6›úų¨½Ðdò¸:kVò˜Ô§ÕÏ^%²î3H¶Ä/¿J­ã¹nÚò_ç/¾ÕWîI-ÀYYc P\îOjr4á}cY¬ÜÛö¢ÑJVße¢7NÙ~Qlf ä#ÁGæ§Ð\£¬T®wªÊ«pÑÜÜ4ªð]dWJ~ér<ʼnUœWÑÈÁËõƒsW®$d^ÉÏ$Ê qÎ m*à }­^‰ís`‚ µ¶þµÍ(”SF±úiŸŸkyÖ·µbe—¾zHú<Žþ43?\ësÖINƒ8ý`˜®Õx媾L~¤Èï{ûYâd`e´5ød1Î^·zÅX66eQ "ƒ~ÈBJéÅ—{qÚÜXº©gp°ªzß&Ò¬Ó¼šV_§)ë¹,GŸQbGtSÔ¦&,φŸø ©(â\TÏÞµmn^@}Èÿ˜-Trð_ ÒœÝ ‚$å‘õ©NØ|Å¡°ØÇ0W_îFè2T…üKéðÇÐ)ˆÁí‡a3Žš¯s‡{¯ˆ™Pì°QHªù<¬Ÿ0J´çÎcÌü à}!6dܰüžê ØLÂ/Qªév\µ¯Ð)ñn4Ç’þ è—¸`Œ›ú갨̞… + +cÕ)'¾GY!–8•RõI¹0›2Ï/>o7wê—˜iœwmpÙ[µkZº=uÙø¶³ÄµÞ¿ŸÛ ï ×ûpÖ–·žŽ†»->yÕ.æ„iÔÏßDÄÀx3°-ƒ¨”D`èŠ×Z>¤À2|mÓ­!é,Æ_PQH,ŠQ/:„RôìD»F¯DøêB¸éôm‹˜Î?Hj6µ¸G«±ÒM‡2†gà ǾI¹br™ÊÕÐÙî‚÷fù¹"ÀKƒÔmSüæi¸ëÌDñ•œ»†W^OsÜÉC†ÓÐË Ç_›ºO·ŽÚÕò¹ÓÚú7ÄŽ>x&H´ÚæôŒ!t¬f"yQNÔäeÿë¹FB*¨»íl™OX:¤.˜ÇLO?A}:ò¼¤Å]ª¡ž; v?1Ü㲦ïQ|¬ôY±]ÞÑÄP€-âvZn÷XpŸ´îBðµ?Vw†¢ü >gþê7å×ëÃŸÚ Úq¿ªCê Î7°GIÒ^êVšèù$ò’ ¨Òñăl}ÏiT‚8Õ)¥s¥r‚ÇÞˆ–Gˆ‚›¥2Û‰ó6û¸Ù–¼néÈß… hõ¶p +Ñ¿6Ý®cîsm>|–ÖŽ­ÜØL ]z‹™'R“é8Þªÿ& ²Mq»Ì†q„.[ÚW¬í'/WZ‹Ž×ªÐø½] Ë¤èÅ}ê²¼qÛ¡SâºaGKú'anð4Xb«8a_û†#0;c̈¡ê—âýjy&5IE‘BVµqh(Þ/ æ ¾rüü£µ-sµ^Ìbö¸ÞB–›;b½µ¤}AÜj2)IsîÞ Gi;6?è÷vhdQ`”§úµ^—>ruffLã±"ö« 5Ã%”„lë/t£ÅLÐÿÒ„ËéýÌ “¯¬ì^°b +:Ñú?Ͷ; +endstream +endobj +722 0 obj << +/Type /FontDescriptor +/FontName /EEGFTS+NimbusRomNo9L-ReguItal +/Flags 4 +/FontBBox [-169 -270 1010 924] +/Ascent 668 +/CapHeight 668 +/Descent -193 +/ItalicAngle -15 +/StemV 78 +/XHeight 441 +/CharSet (/C/E/F/G/I/S/a/b/c/comma/d/e/eight/f/fi/g/h/hyphen/i/k/l/m/n/o/p/parenleft/parenright/period/r/s/t/three/two/u/v/w/x/y/z) +/FontFile 721 0 R +>> endobj +671 0 obj << +/Type /Encoding +/Differences [2/fi/fl 33/exclam/quotedbl/numbersign 39/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon 61/equal 65/A/B/C/D/E/F/G/H/I/J 76/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y 91/bracketleft 93/bracketright 95/underscore 97/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft 125/braceright 149/bullet 169/copyright 174/registered] +>> endobj +317 0 obj << +/Type /Font +/Subtype /Type1 +/BaseFont /YQJSDJ+CMEX10 +/FontDescriptor 690 0 R +/FirstChar 88 +/LastChar 88 +/Widths 676 0 R +>> endobj +313 0 obj << +/Type /Font +/Subtype /Type1 +/BaseFont /CVGKQU+CMMI10 +/FontDescriptor 692 0 R +/FirstChar 62 +/LastChar 120 +/Widths 680 0 R +>> endobj +316 0 obj << +/Type /Font +/Subtype /Type1 +/BaseFont /EFXCJE+CMMI7 +/FontDescriptor 694 0 R +/FirstChar 59 +/LastChar 107 +/Widths 677 0 R +>> endobj +315 0 obj << +/Type /Font +/Subtype /Type1 +/BaseFont /JVDJDJ+CMR10 +/FontDescriptor 696 0 R +/FirstChar 43 +/LastChar 61 +/Widths 678 0 R +>> endobj +314 0 obj << +/Type /Font +/Subtype /Type1 +/BaseFont /XLWYJF+CMR7 +/FontDescriptor 698 0 R +/FirstChar 49 +/LastChar 61 +/Widths 679 0 R +>> endobj +318 0 obj << +/Type /Font +/Subtype /Type1 +/BaseFont /EMXNQD+CMSY10 +/FontDescriptor 700 0 R +/FirstChar 1 +/LastChar 106 +/Widths 675 0 R +>> endobj +499 0 obj << +/Type /Font +/Subtype /Type1 +/BaseFont /DJYPXZ+CMSY6 +/FontDescriptor 702 0 R +/FirstChar 94 +/LastChar 94 +/Widths 673 0 R +>> endobj +312 0 obj << +/Type /Font +/Subtype /Type1 +/BaseFont /LAJUWJ+CMSY7 +/FontDescriptor 704 0 R +/FirstChar 94 +/LastChar 94 +/Widths 681 0 R +>> endobj +239 0 obj << +/Type /Font +/Subtype /Type1 +/BaseFont /YDPBQZ+NimbusMonL-Regu +/FontDescriptor 706 0 R +/FirstChar 34 +/LastChar 121 +/Widths 684 0 R +/Encoding 671 0 R +>> endobj +227 0 obj << +/Type /Font +/Subtype /Type1 +/BaseFont /IPRZVI+NimbusSanL-Bold +/FontDescriptor 708 0 R +/FirstChar 40 +/LastChar 174 +/Widths 688 0 R +/Encoding 671 0 R +>> endobj +309 0 obj << +/Type /Font +/Subtype /Type1 +/BaseFont /CIYFZS+NimbusSanL-BoldCond +/FontDescriptor 710 0 R +/FirstChar 40 +/LastChar 121 +/Widths 682 0 R +/Encoding 671 0 R +>> endobj +228 0 obj << +/Type /Font +/Subtype /Type1 +/BaseFont /NYWZOF+NimbusSanL-BoldItal +/FontDescriptor 712 0 R +/FirstChar 44 +/LastChar 114 +/Widths 687 0 R +/Encoding 671 0 R +>> endobj +529 0 obj << +/Type /Font +/Subtype /Type1 +/BaseFont /KFEQLI+NimbusSanL-BoldCondItal +/FontDescriptor 714 0 R +/FirstChar 44 +/LastChar 119 +/Widths 672 0 R +/Encoding 671 0 R +>> endobj +306 0 obj << +/Type /Font +/Subtype /Type1 +/BaseFont /IXMTHF+NimbusSanL-Regu +/FontDescriptor 716 0 R +/FirstChar 49 +/LastChar 89 +/Widths 683 0 R +/Encoding 671 0 R +>> endobj +237 0 obj << +/Type /Font +/Subtype /Type1 +/BaseFont /ZDVWXI+NimbusRomNo9L-Medi +/FontDescriptor 718 0 R +/FirstChar 46 +/LastChar 121 +/Widths 686 0 R +/Encoding 671 0 R +>> endobj +238 0 obj << +/Type /Font +/Subtype /Type1 +/BaseFont /IPABSO+NimbusRomNo9L-Regu +/FontDescriptor 720 0 R +/FirstChar 2 +/LastChar 174 +/Widths 685 0 R +/Encoding 671 0 R +>> endobj +498 0 obj << +/Type /Font +/Subtype /Type1 +/BaseFont /EEGFTS+NimbusRomNo9L-ReguItal +/FontDescriptor 722 0 R +/FirstChar 2 +/LastChar 122 +/Widths 674 0 R +/Encoding 671 0 R +>> endobj +229 0 obj << +/Type /Pages +/Count 6 +/Parent 723 0 R +/Kids [222 0 R 235 0 R 274 0 R 298 0 R 303 0 R 323 0 R] +>> endobj +364 0 obj << +/Type /Pages +/Count 6 +/Parent 723 0 R +/Kids [358 0 R 366 0 R 432 0 R 460 0 R 475 0 R 494 0 R] +>> endobj +519 0 obj << +/Type /Pages +/Count 6 +/Parent 723 0 R +/Kids [516 0 R 526 0 R 538 0 R 545 0 R 553 0 R 559 0 R] +>> endobj +572 0 obj << +/Type /Pages +/Count 6 +/Parent 723 0 R +/Kids [567 0 R 576 0 R 582 0 R 590 0 R 598 0 R 604 0 R] +>> endobj +616 0 obj << +/Type /Pages +/Count 6 +/Parent 723 0 R +/Kids [611 0 R 618 0 R 626 0 R 633 0 R 641 0 R 651 0 R] +>> endobj +663 0 obj << +/Type /Pages +/Count 2 +/Parent 723 0 R +/Kids [658 0 R 666 0 R] +>> endobj +723 0 obj << +/Type /Pages +/Count 32 +/Kids [229 0 R 364 0 R 519 0 R 572 0 R 616 0 R 663 0 R] +>> endobj +724 0 obj << +/Type /Outlines +/First 7 0 R +/Last 51 0 R +/Count 5 +>> endobj +219 0 obj << +/Title 220 0 R +/A 217 0 R +/Parent 215 0 R +>> endobj +215 0 obj << +/Title 216 0 R +/A 213 0 R +/Parent 51 0 R +/Prev 183 0 R +/First 219 0 R +/Last 219 0 R +/Count -1 +>> endobj +211 0 obj << +/Title 212 0 R +/A 209 0 R +/Parent 191 0 R +/Prev 207 0 R +>> endobj +207 0 obj << +/Title 208 0 R +/A 205 0 R +/Parent 191 0 R +/Prev 203 0 R +/Next 211 0 R +>> endobj +203 0 obj << +/Title 204 0 R +/A 201 0 R +/Parent 191 0 R +/Prev 199 0 R +/Next 207 0 R +>> endobj +199 0 obj << +/Title 200 0 R +/A 197 0 R +/Parent 191 0 R +/Prev 195 0 R +/Next 203 0 R +>> endobj +195 0 obj << +/Title 196 0 R +/A 193 0 R +/Parent 191 0 R +/Next 199 0 R +>> endobj +191 0 obj << +/Title 192 0 R +/A 189 0 R +/Parent 183 0 R +/Prev 187 0 R +/First 195 0 R +/Last 211 0 R +/Count -5 +>> endobj +187 0 obj << +/Title 188 0 R +/A 185 0 R +/Parent 183 0 R +/Next 191 0 R +>> endobj +183 0 obj << +/Title 184 0 R +/A 181 0 R +/Parent 51 0 R +/Prev 55 0 R +/Next 215 0 R +/First 187 0 R +/Last 191 0 R +/Count -2 +>> endobj +179 0 obj << +/Title 180 0 R +/A 177 0 R +/Parent 63 0 R +/Prev 175 0 R +>> endobj +175 0 obj << +/Title 176 0 R +/A 173 0 R +/Parent 63 0 R +/Prev 171 0 R +/Next 179 0 R +>> endobj +171 0 obj << +/Title 172 0 R +/A 169 0 R +/Parent 63 0 R +/Prev 167 0 R +/Next 175 0 R +>> endobj +167 0 obj << +/Title 168 0 R +/A 165 0 R +/Parent 63 0 R +/Prev 163 0 R +/Next 171 0 R +>> endobj +163 0 obj << +/Title 164 0 R +/A 161 0 R +/Parent 63 0 R +/Prev 159 0 R +/Next 167 0 R +>> endobj +159 0 obj << +/Title 160 0 R +/A 157 0 R +/Parent 63 0 R +/Prev 155 0 R +/Next 163 0 R +>> endobj +155 0 obj << +/Title 156 0 R +/A 153 0 R +/Parent 63 0 R +/Prev 151 0 R +/Next 159 0 R +>> endobj +151 0 obj << +/Title 152 0 R +/A 149 0 R +/Parent 63 0 R +/Prev 147 0 R +/Next 155 0 R +>> endobj +147 0 obj << +/Title 148 0 R +/A 145 0 R +/Parent 63 0 R +/Prev 143 0 R +/Next 151 0 R +>> endobj +143 0 obj << +/Title 144 0 R +/A 141 0 R +/Parent 63 0 R +/Prev 139 0 R +/Next 147 0 R +>> endobj +139 0 obj << +/Title 140 0 R +/A 137 0 R +/Parent 63 0 R +/Prev 135 0 R +/Next 143 0 R +>> endobj +135 0 obj << +/Title 136 0 R +/A 133 0 R +/Parent 63 0 R +/Prev 131 0 R +/Next 139 0 R +>> endobj +131 0 obj << +/Title 132 0 R +/A 129 0 R +/Parent 63 0 R +/Prev 127 0 R +/Next 135 0 R +>> endobj +127 0 obj << +/Title 128 0 R +/A 125 0 R +/Parent 63 0 R +/Prev 123 0 R +/Next 131 0 R +>> endobj +123 0 obj << +/Title 124 0 R +/A 121 0 R +/Parent 63 0 R +/Prev 119 0 R +/Next 127 0 R +>> endobj +119 0 obj << +/Title 120 0 R +/A 117 0 R +/Parent 63 0 R +/Prev 115 0 R +/Next 123 0 R +>> endobj +115 0 obj << +/Title 116 0 R +/A 113 0 R +/Parent 63 0 R +/Prev 111 0 R +/Next 119 0 R +>> endobj +111 0 obj << +/Title 112 0 R +/A 109 0 R +/Parent 63 0 R +/Prev 107 0 R +/Next 115 0 R +>> endobj +107 0 obj << +/Title 108 0 R +/A 105 0 R +/Parent 63 0 R +/Prev 103 0 R +/Next 111 0 R +>> endobj +103 0 obj << +/Title 104 0 R +/A 101 0 R +/Parent 63 0 R +/Prev 99 0 R +/Next 107 0 R +>> endobj +99 0 obj << +/Title 100 0 R +/A 97 0 R +/Parent 63 0 R +/Prev 95 0 R +/Next 103 0 R +>> endobj +95 0 obj << +/Title 96 0 R +/A 93 0 R +/Parent 63 0 R +/Prev 91 0 R +/Next 99 0 R +>> endobj +91 0 obj << +/Title 92 0 R +/A 89 0 R +/Parent 63 0 R +/Prev 87 0 R +/Next 95 0 R +>> endobj +87 0 obj << +/Title 88 0 R +/A 85 0 R +/Parent 63 0 R +/Prev 83 0 R +/Next 91 0 R +>> endobj +83 0 obj << +/Title 84 0 R +/A 81 0 R +/Parent 63 0 R +/Prev 79 0 R +/Next 87 0 R +>> endobj +79 0 obj << +/Title 80 0 R +/A 77 0 R +/Parent 63 0 R +/Prev 75 0 R +/Next 83 0 R +>> endobj +75 0 obj << +/Title 76 0 R +/A 73 0 R +/Parent 63 0 R +/Prev 71 0 R +/Next 79 0 R +>> endobj +71 0 obj << +/Title 72 0 R +/A 69 0 R +/Parent 63 0 R +/Prev 67 0 R +/Next 75 0 R +>> endobj +67 0 obj << +/Title 68 0 R +/A 65 0 R +/Parent 63 0 R +/Next 71 0 R +>> endobj +63 0 obj << +/Title 64 0 R +/A 61 0 R +/Parent 55 0 R +/Prev 59 0 R +/First 67 0 R +/Last 179 0 R +/Count -29 +>> endobj +59 0 obj << +/Title 60 0 R +/A 57 0 R +/Parent 55 0 R +/Next 63 0 R +>> endobj +55 0 obj << +/Title 56 0 R +/A 53 0 R +/Parent 51 0 R +/Next 183 0 R +/First 59 0 R +/Last 63 0 R +/Count -2 +>> endobj +51 0 obj << +/Title 52 0 R +/A 49 0 R +/Parent 724 0 R +/Prev 43 0 R +/First 55 0 R +/Last 215 0 R +/Count -3 +>> endobj +47 0 obj << +/Title 48 0 R +/A 45 0 R +/Parent 43 0 R +>> endobj +43 0 obj << +/Title 44 0 R +/A 41 0 R +/Parent 724 0 R +/Prev 39 0 R +/Next 51 0 R +/First 47 0 R +/Last 47 0 R +/Count -1 +>> endobj +39 0 obj << +/Title 40 0 R +/A 37 0 R +/Parent 724 0 R +/Prev 27 0 R +/Next 43 0 R +>> endobj +35 0 obj << +/Title 36 0 R +/A 33 0 R +/Parent 27 0 R +/Prev 31 0 R +>> endobj +31 0 obj << +/Title 32 0 R +/A 29 0 R +/Parent 27 0 R +/Next 35 0 R +>> endobj +27 0 obj << +/Title 28 0 R +/A 25 0 R +/Parent 724 0 R +/Prev 7 0 R +/Next 39 0 R +/First 31 0 R +/Last 35 0 R +/Count -2 +>> endobj +23 0 obj << +/Title 24 0 R +/A 21 0 R +/Parent 7 0 R +/Prev 19 0 R +>> endobj +19 0 obj << +/Title 20 0 R +/A 17 0 R +/Parent 7 0 R +/Prev 15 0 R +/Next 23 0 R +>> endobj +15 0 obj << +/Title 16 0 R +/A 13 0 R +/Parent 7 0 R +/Prev 11 0 R +/Next 19 0 R +>> endobj +11 0 obj << +/Title 12 0 R +/A 9 0 R +/Parent 7 0 R +/Next 15 0 R +>> endobj +7 0 obj << +/Title 8 0 R +/A 5 0 R +/Parent 724 0 R +/Next 27 0 R +/First 11 0 R +/Last 23 0 R +/Count -4 +>> endobj +725 0 obj << +/Names [(Doc-Start) 226 0 R (chapter.1) 6 0 R (chapter.2) 26 0 R (chapter.3) 38 0 R (chapter.4) 42 0 R (chapter.5) 50 0 R] +/Limits [(Doc-Start) (chapter.5)] +>> endobj +726 0 obj << +/Names [(erasure__code_8h) 478 0 R (erasure__code_8h_a06a563b718c6269c8df0fe7647e5bb49) 379 0 R (erasure__code_8h_a12f59be6d348fea6ad2464a20af22fd3) 380 0 R (erasure__code_8h_a17799d49d9b83861322ebf314a55f77f) 386 0 R (erasure__code_8h_a17c6ccf6470796b756841e160dc8697c) 374 0 R (erasure__code_8h_a1fb1d6d463ac00ae196501c75d2036d2) 388 0 R] +/Limits [(erasure__code_8h) (erasure__code_8h_a1fb1d6d463ac00ae196501c75d2036d2)] +>> endobj +727 0 obj << +/Names [(erasure__code_8h_a1ff835062a19d6516f2d59d9c37ddb48) 372 0 R (erasure__code_8h_a21d5e25b4ac64062996149fea71aede8) 382 0 R (erasure__code_8h_a22b53cd4103da9ed88c351e7045ff313) 381 0 R (erasure__code_8h_a2688b38c18e93c95c525c0d5bf9e221a) 393 0 R (erasure__code_8h_a26c2200ad3bf04b1c858eb239b7ff940) 376 0 R (erasure__code_8h_a2fb7662ba4e1df4bb72659c57efeaad6) 394 0 R] +/Limits [(erasure__code_8h_a1ff835062a19d6516f2d59d9c37ddb48) (erasure__code_8h_a2fb7662ba4e1df4bb72659c57efeaad6)] +>> endobj +728 0 obj << +/Names [(erasure__code_8h_a484460566a8c888fda3d769324461345) 521 0 R (erasure__code_8h_a4f880c4b9fe6700e040b9f4ef4e45918) 373 0 R (erasure__code_8h_a590b5c35075aeea1243a9e4ef73a49d4) 320 0 R (erasure__code_8h_a6ce05684e168d73773847a3c2c13c175) 387 0 R (erasure__code_8h_a81be18ea979e8a32f384e1a7856badcf) 531 0 R (erasure__code_8h_aa486278c409735df8001096ac2b487dd) 384 0 R] +/Limits [(erasure__code_8h_a484460566a8c888fda3d769324461345) (erasure__code_8h_aa486278c409735df8001096ac2b487dd)] +>> endobj +729 0 obj << +/Names [(erasure__code_8h_aacd489f45babdbfe6a41f1bac2885ab6) 389 0 R (erasure__code_8h_abb7a991b4c0fb9ced373680ef36bae08) 375 0 R (erasure__code_8h_ac64153e1aef3cdc4b69d375ec762fa33) 392 0 R (erasure__code_8h_ac6468d7eb3c28116439abb4a7c5eca05) 396 0 R (erasure__code_8h_ac73ea8358bc3155c7f3a6c078a7d6d35) 520 0 R (erasure__code_8h_ad0eca329291d751df6ffb3aa3eb83610) 390 0 R] +/Limits [(erasure__code_8h_aacd489f45babdbfe6a41f1bac2885ab6) (erasure__code_8h_ad0eca329291d751df6ffb3aa3eb83610)] +>> endobj +730 0 obj << +/Names [(erasure__code_8h_ad808efb2e8af3803571c0a6c7c9faf39) 533 0 R (erasure__code_8h_ae1e4c9eb9a26a3a7852166d54d2a27f8) 377 0 R (erasure__code_8h_af88a7da05f46e1a0fe17d032a2cf78bf) 378 0 R (erasure__code_8h_af88c501e0c5138ec9c88f58c182945e8) 395 0 R (erasure__code_8h_afd549f435ee28276b5a9408a3a6256b1) 532 0 R (erasure__code_8h_afeefb3612c92a0bc87182f6e11030b11) 391 0 R] +/Limits [(erasure__code_8h_ad808efb2e8af3803571c0a6c7c9faf39) (erasure__code_8h_afeefb3612c92a0bc87182f6e11030b11)] +>> endobj +731 0 obj << +/Names [(gf__vect__mul_8h) 479 0 R (gf__vect__mul_8h_a15d42d058c64dec106d9e3e9fc2e1136) 369 0 R (gf__vect__mul_8h_a7a1f65b032f03494dbc68411f5614bb1) 371 0 R (gf__vect__mul_8h_a84eb9ca31c934f05a8e3fa7a02fa71dc) 370 0 R (gf__vect__mul_8h_a8f3e57729c3382514325612c54e20eaa) 385 0 R (gf__vect__mul_8h_aa7a737b69a0a77dc29aa28d0f17421a1) 383 0 R] +/Limits [(gf__vect__mul_8h) (gf__vect__mul_8h_aa7a737b69a0a77dc29aa28d0f17421a1)] +>> endobj +732 0 obj << +/Names [(index) 307 0 R (index_about_sec) 308 0 R (index_ec_sec) 311 0 R (index_intro_sec) 310 0 R (index_sys_reg_sec) 319 0 R (page.1) 305 0 R] +/Limits [(index) (page.1)] +>> endobj +733 0 obj << +/Names [(page.10) 528 0 R (page.11) 540 0 R (page.12) 547 0 R (page.13) 555 0 R (page.14) 561 0 R (page.15) 569 0 R] +/Limits [(page.10) (page.15)] +>> endobj +734 0 obj << +/Names [(page.16) 578 0 R (page.17) 584 0 R (page.18) 592 0 R (page.19) 600 0 R (page.2) 325 0 R (page.20) 606 0 R] +/Limits [(page.16) (page.20)] +>> endobj +735 0 obj << +/Names [(page.21) 613 0 R (page.22) 620 0 R (page.23) 628 0 R (page.24) 635 0 R (page.25) 643 0 R (page.26) 653 0 R] +/Limits [(page.21) (page.26)] +>> endobj +736 0 obj << +/Names [(page.27) 660 0 R (page.28) 668 0 R (page.3) 360 0 R (page.4) 368 0 R (page.5) 434 0 R (page.6) 462 0 R] +/Limits [(page.27) (page.6)] +>> endobj +737 0 obj << +/Names [(page.7) 477 0 R (page.8) 496 0 R (page.9) 518 0 R (requires) 327 0 R (requires__requires000001) 435 0 R (requires__requires000002) 465 0 R] +/Limits [(page.7) (requires__requires000002)] +>> endobj +738 0 obj << +/Names [(requires__requires000003) 463 0 R (requires__requires000004) 464 0 R (requires__requires000005) 438 0 R (requires__requires000006) 436 0 R (requires__requires000007) 437 0 R (requires__requires000008) 441 0 R] +/Limits [(requires__requires000003) (requires__requires000008)] +>> endobj +739 0 obj << +/Names [(requires__requires000009) 439 0 R (requires__requires000010) 440 0 R (requires__requires000011) 444 0 R (requires__requires000012) 442 0 R (requires__requires000013) 443 0 R (requires__requires000014) 447 0 R] +/Limits [(requires__requires000009) (requires__requires000014)] +>> endobj +740 0 obj << +/Names [(requires__requires000015) 445 0 R (requires__requires000016) 446 0 R (requires__requires000017) 450 0 R (requires__requires000018) 448 0 R (requires__requires000019) 449 0 R (requires__requires000020) 467 0 R] +/Limits [(requires__requires000015) (requires__requires000020)] +>> endobj +741 0 obj << +/Names [(requires__requires000021) 466 0 R (section*.1) 497 0 R (section*.2) 654 0 R (section.1.1) 10 0 R (section.1.2) 14 0 R (section.1.3) 18 0 R] +/Limits [(requires__requires000021) (section.1.3)] +>> endobj +742 0 obj << +/Names [(section.1.4) 22 0 R (section.2.1) 30 0 R (section.2.2) 34 0 R (section.4.1) 46 0 R (section.5.1) 54 0 R (section.5.2) 182 0 R] +/Limits [(section.1.4) (section.5.2)] +>> endobj +743 0 obj << +/Names [(section.5.3) 214 0 R (subsection.5.1.1) 58 0 R (subsection.5.1.2) 62 0 R (subsection.5.2.1) 186 0 R (subsection.5.2.2) 190 0 R (subsection.5.3.1) 218 0 R] +/Limits [(section.5.3) (subsection.5.3.1)] +>> endobj +744 0 obj << +/Names [(subsubsection.5.1.2.1) 66 0 R (subsubsection.5.1.2.10) 102 0 R (subsubsection.5.1.2.11) 106 0 R (subsubsection.5.1.2.12) 110 0 R (subsubsection.5.1.2.13) 114 0 R (subsubsection.5.1.2.14) 118 0 R] +/Limits [(subsubsection.5.1.2.1) (subsubsection.5.1.2.14)] +>> endobj +745 0 obj << +/Names [(subsubsection.5.1.2.15) 122 0 R (subsubsection.5.1.2.16) 126 0 R (subsubsection.5.1.2.17) 130 0 R (subsubsection.5.1.2.18) 134 0 R (subsubsection.5.1.2.19) 138 0 R (subsubsection.5.1.2.2) 70 0 R] +/Limits [(subsubsection.5.1.2.15) (subsubsection.5.1.2.2)] +>> endobj +746 0 obj << +/Names [(subsubsection.5.1.2.20) 142 0 R (subsubsection.5.1.2.21) 146 0 R (subsubsection.5.1.2.22) 150 0 R (subsubsection.5.1.2.23) 154 0 R (subsubsection.5.1.2.24) 158 0 R (subsubsection.5.1.2.25) 162 0 R] +/Limits [(subsubsection.5.1.2.20) (subsubsection.5.1.2.25)] +>> endobj +747 0 obj << +/Names [(subsubsection.5.1.2.26) 166 0 R (subsubsection.5.1.2.27) 170 0 R (subsubsection.5.1.2.28) 174 0 R (subsubsection.5.1.2.29) 178 0 R (subsubsection.5.1.2.3) 74 0 R (subsubsection.5.1.2.4) 78 0 R] +/Limits [(subsubsection.5.1.2.26) (subsubsection.5.1.2.4)] +>> endobj +748 0 obj << +/Names [(subsubsection.5.1.2.5) 82 0 R (subsubsection.5.1.2.6) 86 0 R (subsubsection.5.1.2.7) 90 0 R (subsubsection.5.1.2.8) 94 0 R (subsubsection.5.1.2.9) 98 0 R (subsubsection.5.2.2.1) 194 0 R] +/Limits [(subsubsection.5.1.2.5) (subsubsection.5.2.2.1)] +>> endobj +749 0 obj << +/Names [(subsubsection.5.2.2.2) 198 0 R (subsubsection.5.2.2.3) 202 0 R (subsubsection.5.2.2.4) 206 0 R (subsubsection.5.2.2.5) 210 0 R (table.5.1) 530 0 R (table.5.10) 571 0 R] +/Limits [(subsubsection.5.2.2.2) (table.5.10)] +>> endobj +750 0 obj << +/Names [(table.5.11) 579 0 R (table.5.12) 585 0 R (table.5.13) 586 0 R (table.5.14) 593 0 R (table.5.15) 594 0 R (table.5.16) 601 0 R] +/Limits [(table.5.11) (table.5.16)] +>> endobj +751 0 obj << +/Names [(table.5.17) 607 0 R (table.5.18) 608 0 R (table.5.19) 614 0 R (table.5.2) 541 0 R (table.5.20) 615 0 R (table.5.21) 621 0 R] +/Limits [(table.5.17) (table.5.21)] +>> endobj +752 0 obj << +/Names [(table.5.22) 622 0 R (table.5.23) 623 0 R (table.5.24) 629 0 R (table.5.25) 630 0 R (table.5.26) 636 0 R (table.5.27) 637 0 R] +/Limits [(table.5.22) (table.5.27)] +>> endobj +753 0 obj << +/Names [(table.5.28) 644 0 R (table.5.29) 645 0 R (table.5.3) 542 0 R (table.5.30) 655 0 R (table.5.31) 661 0 R (table.5.32) 662 0 R] +/Limits [(table.5.28) (table.5.32)] +>> endobj +754 0 obj << +/Names [(table.5.33) 669 0 R (table.5.34) 670 0 R (table.5.4) 548 0 R (table.5.5) 549 0 R (table.5.6) 556 0 R (table.5.7) 562 0 R] +/Limits [(table.5.33) (table.5.7)] +>> endobj +755 0 obj << +/Names [(table.5.8) 563 0 R (table.5.9) 570 0 R (types_8h) 480 0 R (version) 361 0 R (version_test) 362 0 R (version_test2) 363 0 R] +/Limits [(table.5.8) (version_test2)] +>> endobj +756 0 obj << +/Kids [725 0 R 726 0 R 727 0 R 728 0 R 729 0 R 730 0 R] +/Limits [(Doc-Start) (erasure__code_8h_afeefb3612c92a0bc87182f6e11030b11)] +>> endobj +757 0 obj << +/Kids [731 0 R 732 0 R 733 0 R 734 0 R 735 0 R 736 0 R] +/Limits [(gf__vect__mul_8h) (page.6)] +>> endobj +758 0 obj << +/Kids [737 0 R 738 0 R 739 0 R 740 0 R 741 0 R 742 0 R] +/Limits [(page.7) (section.5.2)] +>> endobj +759 0 obj << +/Kids [743 0 R 744 0 R 745 0 R 746 0 R 747 0 R 748 0 R] +/Limits [(section.5.3) (subsubsection.5.2.2.1)] +>> endobj +760 0 obj << +/Kids [749 0 R 750 0 R 751 0 R 752 0 R 753 0 R 754 0 R] +/Limits [(subsubsection.5.2.2.2) (table.5.7)] +>> endobj +761 0 obj << +/Kids [755 0 R] +/Limits [(table.5.8) (version_test2)] +>> endobj +762 0 obj << +/Kids [756 0 R 757 0 R 758 0 R 759 0 R 760 0 R 761 0 R] +/Limits [(Doc-Start) (version_test2)] +>> endobj +763 0 obj << +/Dests 762 0 R +>> endobj +764 0 obj << +/Type /Catalog +/Pages 723 0 R +/Outlines 724 0 R +/Names 763 0 R +/PageMode/UseOutlines/PageLabels << /Nums [0 << /S /D >> 1 << /S /D >> 2 << /S /r >> 4 << /S /D >> ] >> +/OpenAction 221 0 R +>> endobj +765 0 obj << +/Author()/Title()/Subject()/Creator(LaTeX with hyperref package)/Producer(pdfTeX-1.40.3)/Keywords() +/CreationDate (D:20140408225608-07'00') +/ModDate (D:20140408225608-07'00') +/Trapped /False +/PTEX.Fullbanner (This is pdfTeX using libpoppler, Version 3.141592-1.40.3-2.2 (Web2C 7.5.6) kpathsea version 3.5.6) +>> endobj +xref +0 766 +0000000001 65535 f +0000000002 00000 f +0000000003 00000 f +0000000004 00000 f +0000000397 00000 f +0000000015 00000 n +0000029129 00000 n +0000248311 00000 n +0000000060 00000 n +0000000164 00000 n +0000029306 00000 n +0000248239 00000 n +0000000211 00000 n +0000000339 00000 n +0000029424 00000 n +0000248153 00000 n +0000000387 00000 n +0000000454 00000 n +0000029541 00000 n +0000248067 00000 n +0000000502 00000 n +0000000645 00000 n +0000031891 00000 n +0000247994 00000 n +0000000693 00000 n +0000000818 00000 n +0000032878 00000 n +0000247870 00000 n +0000000864 00000 n +0000001017 00000 n +0000033056 00000 n +0000247796 00000 n +0000001065 00000 n +0000001218 00000 n +0000033174 00000 n +0000247722 00000 n +0000001266 00000 n +0000001457 00000 n +0000045007 00000 n +0000247634 00000 n +0000001503 00000 n +0000001676 00000 n +0000050083 00000 n +0000247509 00000 n +0000001722 00000 n +0000001802 00000 n +0000050139 00000 n +0000247448 00000 n +0000001850 00000 n +0000001925 00000 n +0000054175 00000 n +0000247335 00000 n +0000001971 00000 n +0000002091 00000 n +0000054292 00000 n +0000247223 00000 n +0000002139 00000 n +0000002320 00000 n +0000062532 00000 n +0000247149 00000 n +0000002373 00000 n +0000002503 00000 n +0000062588 00000 n +0000247036 00000 n +0000002556 00000 n +0000002696 00000 n +0000062701 00000 n +0000246962 00000 n +0000002754 00000 n +0000002857 00000 n +0000065938 00000 n +0000246875 00000 n +0000002915 00000 n +0000003046 00000 n +0000066108 00000 n +0000246788 00000 n +0000003104 00000 n +0000003230 00000 n +0000069083 00000 n +0000246701 00000 n +0000003288 00000 n +0000003391 00000 n +0000069252 00000 n +0000246614 00000 n +0000003449 00000 n +0000003593 00000 n +0000071916 00000 n +0000246527 00000 n +0000003651 00000 n +0000003800 00000 n +0000072086 00000 n +0000246440 00000 n +0000003858 00000 n +0000004002 00000 n +0000074788 00000 n +0000246353 00000 n +0000004060 00000 n +0000004204 00000 n +0000074958 00000 n +0000246264 00000 n +0000004262 00000 n +0000004412 00000 n +0000077736 00000 n +0000246173 00000 n +0000004472 00000 n +0000004617 00000 n +0000080387 00000 n +0000246081 00000 n +0000004677 00000 n +0000004822 00000 n +0000080558 00000 n +0000245989 00000 n +0000004882 00000 n +0000005032 00000 n +0000083234 00000 n +0000245897 00000 n +0000005092 00000 n +0000005237 00000 n +0000083405 00000 n +0000245805 00000 n +0000005297 00000 n +0000005442 00000 n +0000086187 00000 n +0000245713 00000 n +0000005502 00000 n +0000005652 00000 n +0000089050 00000 n +0000245621 00000 n +0000005712 00000 n +0000005857 00000 n +0000089221 00000 n +0000245529 00000 n +0000005917 00000 n +0000006062 00000 n +0000091925 00000 n +0000245437 00000 n +0000006122 00000 n +0000006272 00000 n +0000092096 00000 n +0000245345 00000 n +0000006332 00000 n +0000006477 00000 n +0000095033 00000 n +0000245253 00000 n +0000006537 00000 n +0000006679 00000 n +0000095203 00000 n +0000245161 00000 n +0000006739 00000 n +0000006856 00000 n +0000097392 00000 n +0000245069 00000 n +0000006916 00000 n +0000006977 00000 n +0000097563 00000 n +0000244977 00000 n +0000007037 00000 n +0000007151 00000 n +0000097734 00000 n +0000244885 00000 n +0000007211 00000 n +0000007272 00000 n +0000100342 00000 n +0000244793 00000 n +0000007332 00000 n +0000007449 00000 n +0000100513 00000 n +0000244701 00000 n +0000007509 00000 n +0000007649 00000 n +0000103118 00000 n +0000244609 00000 n +0000007709 00000 n +0000007854 00000 n +0000103289 00000 n +0000244517 00000 n +0000007914 00000 n +0000008059 00000 n +0000106077 00000 n +0000244439 00000 n +0000008119 00000 n +0000008259 00000 n +0000106248 00000 n +0000244309 00000 n +0000008308 00000 n +0000008488 00000 n +0000109728 00000 n +0000244230 00000 n +0000008542 00000 n +0000008673 00000 n +0000109784 00000 n +0000244112 00000 n +0000008727 00000 n +0000008868 00000 n +0000109898 00000 n +0000244033 00000 n +0000008927 00000 n +0000009016 00000 n +0000110069 00000 n +0000243940 00000 n +0000009075 00000 n +0000009187 00000 n +0000112732 00000 n +0000243847 00000 n +0000009246 00000 n +0000009363 00000 n +0000112903 00000 n +0000243754 00000 n +0000009422 00000 n +0000009539 00000 n +0000115203 00000 n +0000243675 00000 n +0000009598 00000 n +0000009710 00000 n +0000115374 00000 n +0000243558 00000 n +0000009759 00000 n +0000009903 00000 n +0000115431 00000 n +0000243493 00000 n +0000009957 00000 n +0000010088 00000 n +0000010605 00000 n +0000010717 00000 n +0000012711 00000 n +0000010140 00000 n +0000012654 00000 n +0000241253 00000 n +0000241599 00000 n +0000242647 00000 n +0000012333 00000 n +0000012585 00000 n +0000012632 00000 n +0000014877 00000 n +0000015067 00000 n +0000014745 00000 n +0000012824 00000 n +0000242123 00000 n +0000242297 00000 n +0000241082 00000 n +0000016450 00000 n +0000016600 00000 n +0000016753 00000 n +0000016906 00000 n +0000017059 00000 n +0000017212 00000 n +0000017362 00000 n +0000017515 00000 n +0000017667 00000 n +0000017818 00000 n +0000017969 00000 n +0000018121 00000 n +0000018272 00000 n +0000018424 00000 n +0000018583 00000 n +0000018741 00000 n +0000018905 00000 n +0000019069 00000 n +0000019233 00000 n +0000019397 00000 n +0000019560 00000 n +0000019724 00000 n +0000019887 00000 n +0000020051 00000 n +0000020214 00000 n +0000020379 00000 n +0000020544 00000 n +0000020708 00000 n +0000020873 00000 n +0000021037 00000 n +0000021202 00000 n +0000021366 00000 n +0000022687 00000 n +0000021531 00000 n +0000016070 00000 n +0000015165 00000 n +0000022852 00000 n +0000023016 00000 n +0000023181 00000 n +0000023345 00000 n +0000023510 00000 n +0000023674 00000 n +0000023838 00000 n +0000024003 00000 n +0000024167 00000 n +0000024332 00000 n +0000024496 00000 n +0000024661 00000 n +0000024814 00000 n +0000024973 00000 n +0000025132 00000 n +0000025296 00000 n +0000025460 00000 n +0000025624 00000 n +0000025788 00000 n +0000025952 00000 n +0000026105 00000 n +0000026264 00000 n +0000022387 00000 n +0000021616 00000 n +0000028880 00000 n +0000031270 00000 n +0000029659 00000 n +0000028748 00000 n +0000026349 00000 n +0000029072 00000 n +0000241953 00000 n +0000029184 00000 n +0000029245 00000 n +0000241424 00000 n +0000029362 00000 n +0000029480 00000 n +0000240940 00000 n +0000240085 00000 n +0000240514 00000 n +0000240372 00000 n +0000240229 00000 n +0000239942 00000 n +0000240655 00000 n +0000029597 00000 n +0000062644 00000 n +0000031420 00000 n +0000031947 00000 n +0000031122 00000 n +0000029845 00000 n +0000031834 00000 n +0000031628 00000 n +0000045063 00000 n +0000035239 00000 n +0000035430 00000 n +0000035621 00000 n +0000035812 00000 n +0000036003 00000 n +0000036194 00000 n +0000036384 00000 n +0000036575 00000 n +0000036765 00000 n +0000036956 00000 n +0000037146 00000 n +0000037337 00000 n +0000037528 00000 n +0000037719 00000 n +0000037910 00000 n +0000038101 00000 n +0000038292 00000 n +0000038483 00000 n +0000038674 00000 n +0000038865 00000 n +0000039056 00000 n +0000039247 00000 n +0000039438 00000 n +0000039628 00000 n +0000039819 00000 n +0000040009 00000 n +0000040200 00000 n +0000040390 00000 n +0000040581 00000 n +0000033229 00000 n +0000032709 00000 n +0000032058 00000 n +0000032821 00000 n +0000032934 00000 n +0000032995 00000 n +0000033112 00000 n +0000242764 00000 n +0000040829 00000 n +0000034883 00000 n +0000033340 00000 n +0000040772 00000 n +0000115146 00000 n +0000112846 00000 n +0000110012 00000 n +0000106020 00000 n +0000100456 00000 n +0000072029 00000 n +0000077679 00000 n +0000080501 00000 n +0000080330 00000 n +0000083177 00000 n +0000088993 00000 n +0000092039 00000 n +0000069026 00000 n +0000066051 00000 n +0000109841 00000 n +0000062814 00000 n +0000112675 00000 n +0000103232 00000 n +0000100285 00000 n +0000103061 00000 n +0000069196 00000 n +0000074731 00000 n +0000083348 00000 n +0000089164 00000 n +0000071859 00000 n +0000074901 00000 n +0000086130 00000 n +0000091868 00000 n +0000000399 00000 f +0000041881 00000 n +0000000401 00000 f +0000042073 00000 n +0000000403 00000 f +0000042265 00000 n +0000000405 00000 f +0000042456 00000 n +0000000407 00000 f +0000042648 00000 n +0000000409 00000 f +0000042840 00000 n +0000000411 00000 f +0000043032 00000 n +0000000413 00000 f +0000043224 00000 n +0000000415 00000 f +0000043415 00000 n +0000000417 00000 f +0000043607 00000 n +0000000419 00000 f +0000043799 00000 n +0000000421 00000 f +0000043991 00000 n +0000000423 00000 f +0000044182 00000 n +0000000425 00000 f +0000044374 00000 n +0000000427 00000 f +0000044566 00000 n +0000000429 00000 f +0000044758 00000 n +0000000451 00000 f +0000046866 00000 n +0000046034 00000 n +0000041629 00000 n +0000040927 00000 n +0000044950 00000 n +0000045124 00000 n +0000045181 00000 n +0000045238 00000 n +0000045295 00000 n +0000045352 00000 n +0000045409 00000 n +0000045465 00000 n +0000045522 00000 n +0000045579 00000 n +0000045636 00000 n +0000045693 00000 n +0000045750 00000 n +0000045807 00000 n +0000045864 00000 n +0000045921 00000 n +0000045977 00000 n +0000000453 00000 f +0000047057 00000 n +0000000455 00000 f +0000047249 00000 n +0000000457 00000 f +0000047441 00000 n +0000000000 00000 f +0000047633 00000 n +0000048165 00000 n +0000046702 00000 n +0000046132 00000 n +0000047825 00000 n +0000047882 00000 n +0000047939 00000 n +0000047995 00000 n +0000048051 00000 n +0000048108 00000 n +0000049099 00000 n +0000049257 00000 n +0000049411 00000 n +0000049569 00000 n +0000049723 00000 n +0000049873 00000 n +0000050195 00000 n +0000048927 00000 n +0000048263 00000 n +0000050026 00000 n +0000054231 00000 n +0000106191 00000 n +0000115317 00000 n +0000052001 00000 n +0000052194 00000 n +0000052387 00000 n +0000052580 00000 n +0000052772 00000 n +0000052963 00000 n +0000053156 00000 n +0000053348 00000 n +0000053541 00000 n +0000053733 00000 n +0000053926 00000 n +0000055873 00000 n +0000054404 00000 n +0000051789 00000 n +0000050306 00000 n +0000054118 00000 n +0000054348 00000 n +0000242470 00000 n +0000240798 00000 n +0000056064 00000 n +0000056257 00000 n +0000056450 00000 n +0000056642 00000 n +0000056835 00000 n +0000057028 00000 n +0000057219 00000 n +0000057411 00000 n +0000057604 00000 n +0000057796 00000 n +0000057989 00000 n +0000058181 00000 n +0000058374 00000 n +0000058567 00000 n +0000061704 00000 n +0000058817 00000 n +0000055629 00000 n +0000054554 00000 n +0000058760 00000 n +0000242881 00000 n +0000097677 00000 n +0000097335 00000 n +0000061896 00000 n +0000062089 00000 n +0000062282 00000 n +0000062871 00000 n +0000061548 00000 n +0000058941 00000 n +0000062475 00000 n +0000241774 00000 n +0000062757 00000 n +0000095147 00000 n +0000094976 00000 n +0000097506 00000 n +0000065329 00000 n +0000065522 00000 n +0000065688 00000 n +0000066221 00000 n +0000065181 00000 n +0000063034 00000 n +0000065881 00000 n +0000065994 00000 n +0000066164 00000 n +0000068803 00000 n +0000069365 00000 n +0000068671 00000 n +0000066371 00000 n +0000068969 00000 n +0000069139 00000 n +0000069308 00000 n +0000071472 00000 n +0000071638 00000 n +0000072142 00000 n +0000071332 00000 n +0000069528 00000 n +0000071802 00000 n +0000071972 00000 n +0000074451 00000 n +0000075014 00000 n +0000074319 00000 n +0000072305 00000 n +0000074617 00000 n +0000074674 00000 n +0000074844 00000 n +0000077234 00000 n +0000077400 00000 n +0000077850 00000 n +0000077094 00000 n +0000075177 00000 n +0000077566 00000 n +0000077623 00000 n +0000077793 00000 n +0000242998 00000 n +0000079943 00000 n +0000080109 00000 n +0000080615 00000 n +0000079803 00000 n +0000078013 00000 n +0000080273 00000 n +0000080444 00000 n +0000082897 00000 n +0000083462 00000 n +0000082765 00000 n +0000080778 00000 n +0000083063 00000 n +0000083120 00000 n +0000083291 00000 n +0000085685 00000 n +0000085851 00000 n +0000086301 00000 n +0000085545 00000 n +0000083625 00000 n +0000086017 00000 n +0000086074 00000 n +0000086244 00000 n +0000088606 00000 n +0000088772 00000 n +0000089278 00000 n +0000088466 00000 n +0000086464 00000 n +0000088936 00000 n +0000089107 00000 n +0000091588 00000 n +0000092153 00000 n +0000091456 00000 n +0000089441 00000 n +0000091754 00000 n +0000091811 00000 n +0000091982 00000 n +0000094697 00000 n +0000095260 00000 n +0000094565 00000 n +0000092316 00000 n +0000094863 00000 n +0000094920 00000 n +0000095090 00000 n +0000243115 00000 n +0000097791 00000 n +0000097109 00000 n +0000095423 00000 n +0000097221 00000 n +0000097278 00000 n +0000097449 00000 n +0000097620 00000 n +0000100006 00000 n +0000100570 00000 n +0000099874 00000 n +0000097954 00000 n +0000100171 00000 n +0000100228 00000 n +0000100399 00000 n +0000102781 00000 n +0000103346 00000 n +0000102649 00000 n +0000100733 00000 n +0000102947 00000 n +0000103004 00000 n +0000103175 00000 n +0000105740 00000 n +0000108653 00000 n +0000106301 00000 n +0000105608 00000 n +0000103509 00000 n +0000105906 00000 n +0000105963 00000 n +0000106134 00000 n +0000108845 00000 n +0000109038 00000 n +0000109231 00000 n +0000109422 00000 n +0000110126 00000 n +0000108489 00000 n +0000106464 00000 n +0000109615 00000 n +0000109672 00000 n +0000109955 00000 n +0000112396 00000 n +0000112960 00000 n +0000112264 00000 n +0000110289 00000 n +0000112561 00000 n +0000112618 00000 n +0000112789 00000 n +0000243232 00000 n +0000114866 00000 n +0000115488 00000 n +0000114734 00000 n +0000113110 00000 n +0000115032 00000 n +0000115089 00000 n +0000115260 00000 n +0000239481 00000 n +0000115638 00000 n +0000115961 00000 n +0000115986 00000 n +0000116461 00000 n +0000117073 00000 n +0000117099 00000 n +0000117412 00000 n +0000117523 00000 n +0000117618 00000 n +0000117979 00000 n +0000118004 00000 n +0000118351 00000 n +0000118535 00000 n +0000118906 00000 n +0000119568 00000 n +0000119892 00000 n +0000120195 00000 n +0000120735 00000 n +0000122499 00000 n +0000122732 00000 n +0000125260 00000 n +0000125496 00000 n +0000127821 00000 n +0000128050 00000 n +0000129970 00000 n +0000130203 00000 n +0000132711 00000 n +0000132958 00000 n +0000134482 00000 n +0000134734 00000 n +0000135998 00000 n +0000136227 00000 n +0000137496 00000 n +0000137726 00000 n +0000151595 00000 n +0000151990 00000 n +0000160014 00000 n +0000160352 00000 n +0000171728 00000 n +0000172110 00000 n +0000178885 00000 n +0000179160 00000 n +0000186548 00000 n +0000186829 00000 n +0000192223 00000 n +0000192519 00000 n +0000206190 00000 n +0000206568 00000 n +0000225983 00000 n +0000226563 00000 n +0000239124 00000 n +0000243317 00000 n +0000243419 00000 n +0000248420 00000 n +0000248600 00000 n +0000249046 00000 n +0000249560 00000 n +0000250074 00000 n +0000250588 00000 n +0000251102 00000 n +0000251548 00000 n +0000251743 00000 n +0000251913 00000 n +0000252082 00000 n +0000252252 00000 n +0000252417 00000 n +0000252635 00000 n +0000252941 00000 n +0000253247 00000 n +0000253553 00000 n +0000253776 00000 n +0000253973 00000 n +0000254203 00000 n +0000254490 00000 n +0000254777 00000 n +0000255067 00000 n +0000255352 00000 n +0000255629 00000 n +0000255877 00000 n +0000256071 00000 n +0000256264 00000 n +0000256458 00000 n +0000256651 00000 n +0000256840 00000 n +0000257034 00000 n +0000257188 00000 n +0000257305 00000 n +0000257417 00000 n +0000257544 00000 n +0000257669 00000 n +0000257746 00000 n +0000257863 00000 n +0000257901 00000 n +0000258111 00000 n +trailer +<< /Size 766 +/Root 764 0 R +/Info 765 0 R +/ID [<07BF1BFF8396560A3D29CED1E32BB73D> <07BF1BFF8396560A3D29CED1E32BB73D>] >> +startxref +258442 +%%EOF diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/docs/isa-l_open_src_2.13.pdf b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/docs/isa-l_open_src_2.13.pdf new file mode 100644 index 000000000..7ae862f99 Binary files /dev/null and b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/docs/isa-l_open_src_2.13.pdf differ diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_base.c b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_base.c new file mode 100644 index 000000000..2898f668f --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_base.c @@ -0,0 +1,348 @@ +/********************************************************************** + Copyright(c) 2011-2015 Intel Corporation All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**********************************************************************/ + +#include +#include // for memset +#include "ec_code.h" +#include "ec_base.h" // for GF tables +#include "ec_types.h" + +unsigned char gf_mul(unsigned char a, unsigned char b) +{ +#ifndef GF_LARGE_TABLES + int i; + + if ((a == 0) || (b == 0)) + return 0; + + return gff_base[(i = gflog_base[a] + gflog_base[b]) > 254 ? i - 255 : i]; +#else + return gf_mul_table_base[b * 256 + a]; +#endif +} + +unsigned char gf_inv(unsigned char a) +{ +#ifndef GF_LARGE_TABLES + if (a == 0) + return 0; + + return gff_base[255 - gflog_base[a]]; +#else + return gf_inv_table_base[a]; +#endif +} + +void gf_gen_rs_matrix(unsigned char *a, int m, int k) +{ + int i, j; + unsigned char p, gen = 1; + + memset(a, 0, k * m); + for (i = 0; i < k; i++) + a[k * i + i] = 1; + + for (i = k; i < m; i++) { + p = 1; + for (j = 0; j < k; j++) { + a[k * i + j] = p; + p = gf_mul(p, gen); + } + gen = gf_mul(gen, 2); + } +} + +void gf_gen_cauchy1_matrix(unsigned char *a, int m, int k) +{ + int i, j; + unsigned char *p; + + // Identity matrix in high position + memset(a, 0, k * m); + for (i = 0; i < k; i++) + a[k * i + i] = 1; + + // For the rest choose 1/(i + j) | i != j + p = &a[k * k]; + for (i = k; i < m; i++) + for (j = 0; j < k; j++) + *p++ = gf_inv(i ^ j); + +} + +int gf_invert_matrix(unsigned char *in_mat, unsigned char *out_mat, const int n) +{ + int i, j, k; + unsigned char temp; + + // Set out_mat[] to the identity matrix + for (i = 0; i < n * n; i++) // memset(out_mat, 0, n*n) + out_mat[i] = 0; + + for (i = 0; i < n; i++) + out_mat[i * n + i] = 1; + + // Inverse + for (i = 0; i < n; i++) { + // Check for 0 in pivot element + if (in_mat[i * n + i] == 0) { + // Find a row with non-zero in current column and swap + for (j = i + 1; j < n; j++) + if (in_mat[j * n + i]) + break; + + if (j == n) // Couldn't find means it's singular + return -1; + + for (k = 0; k < n; k++) { // Swap rows i,j + temp = in_mat[i * n + k]; + in_mat[i * n + k] = in_mat[j * n + k]; + in_mat[j * n + k] = temp; + + temp = out_mat[i * n + k]; + out_mat[i * n + k] = out_mat[j * n + k]; + out_mat[j * n + k] = temp; + } + } + + temp = gf_inv(in_mat[i * n + i]); // 1/pivot + for (j = 0; j < n; j++) { // Scale row i by 1/pivot + in_mat[i * n + j] = gf_mul(in_mat[i * n + j], temp); + out_mat[i * n + j] = gf_mul(out_mat[i * n + j], temp); + } + + for (j = 0; j < n; j++) { + if (j == i) + continue; + + temp = in_mat[j * n + i]; + for (k = 0; k < n; k++) { + out_mat[j * n + k] ^= gf_mul(temp, out_mat[i * n + k]); + in_mat[j * n + k] ^= gf_mul(temp, in_mat[i * n + k]); + } + } + } + return 0; +} + +// Calculates const table gftbl in GF(2^8) from single input A +// gftbl(A) = {A{00}, A{01}, A{02}, ... , A{0f} }, {A{00}, A{10}, A{20}, ... , A{f0} } + +void gf_vect_mul_init(unsigned char c, unsigned char *tbl) +{ + unsigned char c2 = (c << 1) ^ ((c & 0x80) ? 0x1d : 0); //Mult by GF{2} + unsigned char c4 = (c2 << 1) ^ ((c2 & 0x80) ? 0x1d : 0); //Mult by GF{2} + unsigned char c8 = (c4 << 1) ^ ((c4 & 0x80) ? 0x1d : 0); //Mult by GF{2} + +#if __WORDSIZE == 64 || _WIN64 || __x86_64__ + unsigned long long v1, v2, v4, v8, *t; + unsigned long long v10, v20, v40, v80; + unsigned char c17, c18, c20, c24; + + t = (unsigned long long *)tbl; + + v1 = c * 0x0100010001000100ull; + v2 = c2 * 0x0101000001010000ull; + v4 = c4 * 0x0101010100000000ull; + v8 = c8 * 0x0101010101010101ull; + + v4 = v1 ^ v2 ^ v4; + t[0] = v4; + t[1] = v8 ^ v4; + + c17 = (c8 << 1) ^ ((c8 & 0x80) ? 0x1d : 0); //Mult by GF{2} + c18 = (c17 << 1) ^ ((c17 & 0x80) ? 0x1d : 0); //Mult by GF{2} + c20 = (c18 << 1) ^ ((c18 & 0x80) ? 0x1d : 0); //Mult by GF{2} + c24 = (c20 << 1) ^ ((c20 & 0x80) ? 0x1d : 0); //Mult by GF{2} + + v10 = c17 * 0x0100010001000100ull; + v20 = c18 * 0x0101000001010000ull; + v40 = c20 * 0x0101010100000000ull; + v80 = c24 * 0x0101010101010101ull; + + v40 = v10 ^ v20 ^ v40; + t[2] = v40; + t[3] = v80 ^ v40; + +#else // 32-bit or other + unsigned char c3, c5, c6, c7, c9, c10, c11, c12, c13, c14, c15; + unsigned char c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, + c31; + + c3 = c2 ^ c; + c5 = c4 ^ c; + c6 = c4 ^ c2; + c7 = c4 ^ c3; + + c9 = c8 ^ c; + c10 = c8 ^ c2; + c11 = c8 ^ c3; + c12 = c8 ^ c4; + c13 = c8 ^ c5; + c14 = c8 ^ c6; + c15 = c8 ^ c7; + + tbl[0] = 0; + tbl[1] = c; + tbl[2] = c2; + tbl[3] = c3; + tbl[4] = c4; + tbl[5] = c5; + tbl[6] = c6; + tbl[7] = c7; + tbl[8] = c8; + tbl[9] = c9; + tbl[10] = c10; + tbl[11] = c11; + tbl[12] = c12; + tbl[13] = c13; + tbl[14] = c14; + tbl[15] = c15; + + c17 = (c8 << 1) ^ ((c8 & 0x80) ? 0x1d : 0); //Mult by GF{2} + c18 = (c17 << 1) ^ ((c17 & 0x80) ? 0x1d : 0); //Mult by GF{2} + c19 = c18 ^ c17; + c20 = (c18 << 1) ^ ((c18 & 0x80) ? 0x1d : 0); //Mult by GF{2} + c21 = c20 ^ c17; + c22 = c20 ^ c18; + c23 = c20 ^ c19; + c24 = (c20 << 1) ^ ((c20 & 0x80) ? 0x1d : 0); //Mult by GF{2} + c25 = c24 ^ c17; + c26 = c24 ^ c18; + c27 = c24 ^ c19; + c28 = c24 ^ c20; + c29 = c24 ^ c21; + c30 = c24 ^ c22; + c31 = c24 ^ c23; + + tbl[16] = 0; + tbl[17] = c17; + tbl[18] = c18; + tbl[19] = c19; + tbl[20] = c20; + tbl[21] = c21; + tbl[22] = c22; + tbl[23] = c23; + tbl[24] = c24; + tbl[25] = c25; + tbl[26] = c26; + tbl[27] = c27; + tbl[28] = c28; + tbl[29] = c29; + tbl[30] = c30; + tbl[31] = c31; + +#endif //__WORDSIZE == 64 || _WIN64 || __x86_64__ +} + +void gf_vect_dot_prod_base(int len, int vlen, unsigned char *v, + unsigned char **src, unsigned char *dest) +{ + int i, j; + unsigned char s; + for (i = 0; i < len; i++) { + s = 0; + for (j = 0; j < vlen; j++) + s ^= gf_mul(src[j][i], v[j * 32 + 1]); + + dest[i] = s; + } +} + +void gf_vect_mad_base(int len, int vec, int vec_i, + unsigned char *v, unsigned char *src, unsigned char *dest) +{ + int i; + unsigned char s; + for (i = 0; i < len; i++) { + s = dest[i]; + s ^= gf_mul(src[i], v[vec_i * 32 + 1]); + dest[i] = s; + } +} + +void ec_encode_data_base(int len, int srcs, int dests, unsigned char *v, + unsigned char **src, unsigned char **dest) +{ + int i, j, l; + unsigned char s; + + for (l = 0; l < dests; l++) { + for (i = 0; i < len; i++) { + s = 0; + for (j = 0; j < srcs; j++) + s ^= gf_mul(src[j][i], v[j * 32 + l * srcs * 32 + 1]); + + dest[l][i] = s; + } + } +} + +void ec_encode_data_update_base(int len, int k, int rows, int vec_i, unsigned char *v, + unsigned char *data, unsigned char **dest) +{ + int i, l; + unsigned char s; + + for (l = 0; l < rows; l++) { + for (i = 0; i < len; i++) { + s = dest[l][i]; + s ^= gf_mul(data[i], v[vec_i * 32 + l * k * 32 + 1]); + + dest[l][i] = s; + } + } +} + +void gf_vect_mul_base(int len, unsigned char *a, unsigned char *src, unsigned char *dest) +{ + //2nd element of table array is ref value used to fill it in + unsigned char c = a[1]; + while (len-- > 0) + *dest++ = gf_mul(c, *src++); +} + +struct slver { + UINT16 snum; + UINT8 ver; + UINT8 core; +}; + +// Version info +struct slver gf_vect_mul_init_slver_00020035; +struct slver gf_vect_mul_init_slver = { 0x0035, 0x02, 0x00 }; + +struct slver ec_encode_data_base_slver_00010135; +struct slver ec_encode_data_base_slver = { 0x0135, 0x01, 0x00 }; + +struct slver gf_vect_mul_base_slver_00010136; +struct slver gf_vect_mul_base_slver = { 0x0136, 0x01, 0x00 }; + +struct slver gf_vect_dot_prod_base_slver_00010137; +struct slver gf_vect_dot_prod_base_slver = { 0x0137, 0x01, 0x00 }; diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_base.h b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_base.h new file mode 100644 index 000000000..db4fd9d6c --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_base.h @@ -0,0 +1,6680 @@ +/********************************************************************** + Copyright(c) 2011-2015 Intel Corporation All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**********************************************************************/ + +#ifndef _EC_BASE_H_ +#define _EC_BASE_H_ + +// Global GF(256) tables +#ifndef GF_LARGE_TABLES +unsigned char gff_base[] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1d, 0x3a, + 0x74, 0xe8, 0xcd, 0x87, 0x13, 0x26, 0x4c, 0x98, 0x2d, 0x5a, + 0xb4, 0x75, 0xea, 0xc9, 0x8f, 0x03, 0x06, 0x0c, 0x18, 0x30, + 0x60, 0xc0, 0x9d, 0x27, 0x4e, 0x9c, 0x25, 0x4a, 0x94, 0x35, + 0x6a, 0xd4, 0xb5, 0x77, 0xee, 0xc1, 0x9f, 0x23, 0x46, 0x8c, + 0x05, 0x0a, 0x14, 0x28, 0x50, 0xa0, 0x5d, 0xba, 0x69, 0xd2, + 0xb9, 0x6f, 0xde, 0xa1, 0x5f, 0xbe, 0x61, 0xc2, 0x99, 0x2f, + 0x5e, 0xbc, 0x65, 0xca, 0x89, 0x0f, 0x1e, 0x3c, 0x78, 0xf0, + 0xfd, 0xe7, 0xd3, 0xbb, 0x6b, 0xd6, 0xb1, 0x7f, 0xfe, 0xe1, + 0xdf, 0xa3, 0x5b, 0xb6, 0x71, 0xe2, 0xd9, 0xaf, 0x43, 0x86, + 0x11, 0x22, 0x44, 0x88, 0x0d, 0x1a, 0x34, 0x68, 0xd0, 0xbd, + 0x67, 0xce, 0x81, 0x1f, 0x3e, 0x7c, 0xf8, 0xed, 0xc7, 0x93, + 0x3b, 0x76, 0xec, 0xc5, 0x97, 0x33, 0x66, 0xcc, 0x85, 0x17, + 0x2e, 0x5c, 0xb8, 0x6d, 0xda, 0xa9, 0x4f, 0x9e, 0x21, 0x42, + 0x84, 0x15, 0x2a, 0x54, 0xa8, 0x4d, 0x9a, 0x29, 0x52, 0xa4, + 0x55, 0xaa, 0x49, 0x92, 0x39, 0x72, 0xe4, 0xd5, 0xb7, 0x73, + 0xe6, 0xd1, 0xbf, 0x63, 0xc6, 0x91, 0x3f, 0x7e, 0xfc, 0xe5, + 0xd7, 0xb3, 0x7b, 0xf6, 0xf1, 0xff, 0xe3, 0xdb, 0xab, 0x4b, + 0x96, 0x31, 0x62, 0xc4, 0x95, 0x37, 0x6e, 0xdc, 0xa5, 0x57, + 0xae, 0x41, 0x82, 0x19, 0x32, 0x64, 0xc8, 0x8d, 0x07, 0x0e, + 0x1c, 0x38, 0x70, 0xe0, 0xdd, 0xa7, 0x53, 0xa6, 0x51, 0xa2, + 0x59, 0xb2, 0x79, 0xf2, 0xf9, 0xef, 0xc3, 0x9b, 0x2b, 0x56, + 0xac, 0x45, 0x8a, 0x09, 0x12, 0x24, 0x48, 0x90, 0x3d, 0x7a, + 0xf4, 0xf5, 0xf7, 0xf3, 0xfb, 0xeb, 0xcb, 0x8b, 0x0b, 0x16, + 0x2c, 0x58, 0xb0, 0x7d, 0xfa, 0xe9, 0xcf, 0x83, 0x1b, 0x36, + 0x6c, 0xd8, 0xad, 0x47, 0x8e, 0x01 +}; + +unsigned char gflog_base[] = { + 0x00, 0xff, 0x01, 0x19, 0x02, 0x32, 0x1a, 0xc6, 0x03, 0xdf, + 0x33, 0xee, 0x1b, 0x68, 0xc7, 0x4b, 0x04, 0x64, 0xe0, 0x0e, + 0x34, 0x8d, 0xef, 0x81, 0x1c, 0xc1, 0x69, 0xf8, 0xc8, 0x08, + 0x4c, 0x71, 0x05, 0x8a, 0x65, 0x2f, 0xe1, 0x24, 0x0f, 0x21, + 0x35, 0x93, 0x8e, 0xda, 0xf0, 0x12, 0x82, 0x45, 0x1d, 0xb5, + 0xc2, 0x7d, 0x6a, 0x27, 0xf9, 0xb9, 0xc9, 0x9a, 0x09, 0x78, + 0x4d, 0xe4, 0x72, 0xa6, 0x06, 0xbf, 0x8b, 0x62, 0x66, 0xdd, + 0x30, 0xfd, 0xe2, 0x98, 0x25, 0xb3, 0x10, 0x91, 0x22, 0x88, + 0x36, 0xd0, 0x94, 0xce, 0x8f, 0x96, 0xdb, 0xbd, 0xf1, 0xd2, + 0x13, 0x5c, 0x83, 0x38, 0x46, 0x40, 0x1e, 0x42, 0xb6, 0xa3, + 0xc3, 0x48, 0x7e, 0x6e, 0x6b, 0x3a, 0x28, 0x54, 0xfa, 0x85, + 0xba, 0x3d, 0xca, 0x5e, 0x9b, 0x9f, 0x0a, 0x15, 0x79, 0x2b, + 0x4e, 0xd4, 0xe5, 0xac, 0x73, 0xf3, 0xa7, 0x57, 0x07, 0x70, + 0xc0, 0xf7, 0x8c, 0x80, 0x63, 0x0d, 0x67, 0x4a, 0xde, 0xed, + 0x31, 0xc5, 0xfe, 0x18, 0xe3, 0xa5, 0x99, 0x77, 0x26, 0xb8, + 0xb4, 0x7c, 0x11, 0x44, 0x92, 0xd9, 0x23, 0x20, 0x89, 0x2e, + 0x37, 0x3f, 0xd1, 0x5b, 0x95, 0xbc, 0xcf, 0xcd, 0x90, 0x87, + 0x97, 0xb2, 0xdc, 0xfc, 0xbe, 0x61, 0xf2, 0x56, 0xd3, 0xab, + 0x14, 0x2a, 0x5d, 0x9e, 0x84, 0x3c, 0x39, 0x53, 0x47, 0x6d, + 0x41, 0xa2, 0x1f, 0x2d, 0x43, 0xd8, 0xb7, 0x7b, 0xa4, 0x76, + 0xc4, 0x17, 0x49, 0xec, 0x7f, 0x0c, 0x6f, 0xf6, 0x6c, 0xa1, + 0x3b, 0x52, 0x29, 0x9d, 0x55, 0xaa, 0xfb, 0x60, 0x86, 0xb1, + 0xbb, 0xcc, 0x3e, 0x5a, 0xcb, 0x59, 0x5f, 0xb0, 0x9c, 0xa9, + 0xa0, 0x51, 0x0b, 0xf5, 0x16, 0xeb, 0x7a, 0x75, 0x2c, 0xd7, + 0x4f, 0xae, 0xd5, 0xe9, 0xe6, 0xe7, 0xad, 0xe8, 0x74, 0xd6, + 0xf4, 0xea, 0xa8, 0x50, 0x58, 0xaf +}; +#else +unsigned char gf_mul_table_base[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, + 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, + 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, + 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, + 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, + 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, + 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, + 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, + 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, + 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, + 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, + 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, + 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, + 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, + 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, + 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, + 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, + 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, + 0xfe, 0xff, 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, + 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, 0x20, 0x22, + 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, + 0x38, 0x3a, 0x3c, 0x3e, 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, + 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, + 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, + 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, 0x80, 0x82, 0x84, 0x86, + 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, + 0x9c, 0x9e, 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, + 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, 0xc0, 0xc2, + 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, + 0xd8, 0xda, 0xdc, 0xde, 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, + 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe, + 0x1d, 0x1f, 0x19, 0x1b, 0x15, 0x17, 0x11, 0x13, 0x0d, 0x0f, + 0x09, 0x0b, 0x05, 0x07, 0x01, 0x03, 0x3d, 0x3f, 0x39, 0x3b, + 0x35, 0x37, 0x31, 0x33, 0x2d, 0x2f, 0x29, 0x2b, 0x25, 0x27, + 0x21, 0x23, 0x5d, 0x5f, 0x59, 0x5b, 0x55, 0x57, 0x51, 0x53, + 0x4d, 0x4f, 0x49, 0x4b, 0x45, 0x47, 0x41, 0x43, 0x7d, 0x7f, + 0x79, 0x7b, 0x75, 0x77, 0x71, 0x73, 0x6d, 0x6f, 0x69, 0x6b, + 0x65, 0x67, 0x61, 0x63, 0x9d, 0x9f, 0x99, 0x9b, 0x95, 0x97, + 0x91, 0x93, 0x8d, 0x8f, 0x89, 0x8b, 0x85, 0x87, 0x81, 0x83, + 0xbd, 0xbf, 0xb9, 0xbb, 0xb5, 0xb7, 0xb1, 0xb3, 0xad, 0xaf, + 0xa9, 0xab, 0xa5, 0xa7, 0xa1, 0xa3, 0xdd, 0xdf, 0xd9, 0xdb, + 0xd5, 0xd7, 0xd1, 0xd3, 0xcd, 0xcf, 0xc9, 0xcb, 0xc5, 0xc7, + 0xc1, 0xc3, 0xfd, 0xff, 0xf9, 0xfb, 0xf5, 0xf7, 0xf1, 0xf3, + 0xed, 0xef, 0xe9, 0xeb, 0xe5, 0xe7, 0xe1, 0xe3, 0x00, 0x03, + 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, + 0x14, 0x17, 0x12, 0x11, 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, + 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21, + 0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, + 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71, 0x50, 0x53, 0x56, 0x55, + 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, + 0x42, 0x41, 0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, + 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1, 0xf0, 0xf3, + 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, + 0xe4, 0xe7, 0xe2, 0xe1, 0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, + 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1, + 0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, + 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81, 0x9d, 0x9e, 0x9b, 0x98, + 0x91, 0x92, 0x97, 0x94, 0x85, 0x86, 0x83, 0x80, 0x89, 0x8a, + 0x8f, 0x8c, 0xad, 0xae, 0xab, 0xa8, 0xa1, 0xa2, 0xa7, 0xa4, + 0xb5, 0xb6, 0xb3, 0xb0, 0xb9, 0xba, 0xbf, 0xbc, 0xfd, 0xfe, + 0xfb, 0xf8, 0xf1, 0xf2, 0xf7, 0xf4, 0xe5, 0xe6, 0xe3, 0xe0, + 0xe9, 0xea, 0xef, 0xec, 0xcd, 0xce, 0xcb, 0xc8, 0xc1, 0xc2, + 0xc7, 0xc4, 0xd5, 0xd6, 0xd3, 0xd0, 0xd9, 0xda, 0xdf, 0xdc, + 0x5d, 0x5e, 0x5b, 0x58, 0x51, 0x52, 0x57, 0x54, 0x45, 0x46, + 0x43, 0x40, 0x49, 0x4a, 0x4f, 0x4c, 0x6d, 0x6e, 0x6b, 0x68, + 0x61, 0x62, 0x67, 0x64, 0x75, 0x76, 0x73, 0x70, 0x79, 0x7a, + 0x7f, 0x7c, 0x3d, 0x3e, 0x3b, 0x38, 0x31, 0x32, 0x37, 0x34, + 0x25, 0x26, 0x23, 0x20, 0x29, 0x2a, 0x2f, 0x2c, 0x0d, 0x0e, + 0x0b, 0x08, 0x01, 0x02, 0x07, 0x04, 0x15, 0x16, 0x13, 0x10, + 0x19, 0x1a, 0x1f, 0x1c, 0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, + 0x18, 0x1c, 0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38, 0x3c, + 0x40, 0x44, 0x48, 0x4c, 0x50, 0x54, 0x58, 0x5c, 0x60, 0x64, + 0x68, 0x6c, 0x70, 0x74, 0x78, 0x7c, 0x80, 0x84, 0x88, 0x8c, + 0x90, 0x94, 0x98, 0x9c, 0xa0, 0xa4, 0xa8, 0xac, 0xb0, 0xb4, + 0xb8, 0xbc, 0xc0, 0xc4, 0xc8, 0xcc, 0xd0, 0xd4, 0xd8, 0xdc, + 0xe0, 0xe4, 0xe8, 0xec, 0xf0, 0xf4, 0xf8, 0xfc, 0x1d, 0x19, + 0x15, 0x11, 0x0d, 0x09, 0x05, 0x01, 0x3d, 0x39, 0x35, 0x31, + 0x2d, 0x29, 0x25, 0x21, 0x5d, 0x59, 0x55, 0x51, 0x4d, 0x49, + 0x45, 0x41, 0x7d, 0x79, 0x75, 0x71, 0x6d, 0x69, 0x65, 0x61, + 0x9d, 0x99, 0x95, 0x91, 0x8d, 0x89, 0x85, 0x81, 0xbd, 0xb9, + 0xb5, 0xb1, 0xad, 0xa9, 0xa5, 0xa1, 0xdd, 0xd9, 0xd5, 0xd1, + 0xcd, 0xc9, 0xc5, 0xc1, 0xfd, 0xf9, 0xf5, 0xf1, 0xed, 0xe9, + 0xe5, 0xe1, 0x3a, 0x3e, 0x32, 0x36, 0x2a, 0x2e, 0x22, 0x26, + 0x1a, 0x1e, 0x12, 0x16, 0x0a, 0x0e, 0x02, 0x06, 0x7a, 0x7e, + 0x72, 0x76, 0x6a, 0x6e, 0x62, 0x66, 0x5a, 0x5e, 0x52, 0x56, + 0x4a, 0x4e, 0x42, 0x46, 0xba, 0xbe, 0xb2, 0xb6, 0xaa, 0xae, + 0xa2, 0xa6, 0x9a, 0x9e, 0x92, 0x96, 0x8a, 0x8e, 0x82, 0x86, + 0xfa, 0xfe, 0xf2, 0xf6, 0xea, 0xee, 0xe2, 0xe6, 0xda, 0xde, + 0xd2, 0xd6, 0xca, 0xce, 0xc2, 0xc6, 0x27, 0x23, 0x2f, 0x2b, + 0x37, 0x33, 0x3f, 0x3b, 0x07, 0x03, 0x0f, 0x0b, 0x17, 0x13, + 0x1f, 0x1b, 0x67, 0x63, 0x6f, 0x6b, 0x77, 0x73, 0x7f, 0x7b, + 0x47, 0x43, 0x4f, 0x4b, 0x57, 0x53, 0x5f, 0x5b, 0xa7, 0xa3, + 0xaf, 0xab, 0xb7, 0xb3, 0xbf, 0xbb, 0x87, 0x83, 0x8f, 0x8b, + 0x97, 0x93, 0x9f, 0x9b, 0xe7, 0xe3, 0xef, 0xeb, 0xf7, 0xf3, + 0xff, 0xfb, 0xc7, 0xc3, 0xcf, 0xcb, 0xd7, 0xd3, 0xdf, 0xdb, + 0x00, 0x05, 0x0a, 0x0f, 0x14, 0x11, 0x1e, 0x1b, 0x28, 0x2d, + 0x22, 0x27, 0x3c, 0x39, 0x36, 0x33, 0x50, 0x55, 0x5a, 0x5f, + 0x44, 0x41, 0x4e, 0x4b, 0x78, 0x7d, 0x72, 0x77, 0x6c, 0x69, + 0x66, 0x63, 0xa0, 0xa5, 0xaa, 0xaf, 0xb4, 0xb1, 0xbe, 0xbb, + 0x88, 0x8d, 0x82, 0x87, 0x9c, 0x99, 0x96, 0x93, 0xf0, 0xf5, + 0xfa, 0xff, 0xe4, 0xe1, 0xee, 0xeb, 0xd8, 0xdd, 0xd2, 0xd7, + 0xcc, 0xc9, 0xc6, 0xc3, 0x5d, 0x58, 0x57, 0x52, 0x49, 0x4c, + 0x43, 0x46, 0x75, 0x70, 0x7f, 0x7a, 0x61, 0x64, 0x6b, 0x6e, + 0x0d, 0x08, 0x07, 0x02, 0x19, 0x1c, 0x13, 0x16, 0x25, 0x20, + 0x2f, 0x2a, 0x31, 0x34, 0x3b, 0x3e, 0xfd, 0xf8, 0xf7, 0xf2, + 0xe9, 0xec, 0xe3, 0xe6, 0xd5, 0xd0, 0xdf, 0xda, 0xc1, 0xc4, + 0xcb, 0xce, 0xad, 0xa8, 0xa7, 0xa2, 0xb9, 0xbc, 0xb3, 0xb6, + 0x85, 0x80, 0x8f, 0x8a, 0x91, 0x94, 0x9b, 0x9e, 0xba, 0xbf, + 0xb0, 0xb5, 0xae, 0xab, 0xa4, 0xa1, 0x92, 0x97, 0x98, 0x9d, + 0x86, 0x83, 0x8c, 0x89, 0xea, 0xef, 0xe0, 0xe5, 0xfe, 0xfb, + 0xf4, 0xf1, 0xc2, 0xc7, 0xc8, 0xcd, 0xd6, 0xd3, 0xdc, 0xd9, + 0x1a, 0x1f, 0x10, 0x15, 0x0e, 0x0b, 0x04, 0x01, 0x32, 0x37, + 0x38, 0x3d, 0x26, 0x23, 0x2c, 0x29, 0x4a, 0x4f, 0x40, 0x45, + 0x5e, 0x5b, 0x54, 0x51, 0x62, 0x67, 0x68, 0x6d, 0x76, 0x73, + 0x7c, 0x79, 0xe7, 0xe2, 0xed, 0xe8, 0xf3, 0xf6, 0xf9, 0xfc, + 0xcf, 0xca, 0xc5, 0xc0, 0xdb, 0xde, 0xd1, 0xd4, 0xb7, 0xb2, + 0xbd, 0xb8, 0xa3, 0xa6, 0xa9, 0xac, 0x9f, 0x9a, 0x95, 0x90, + 0x8b, 0x8e, 0x81, 0x84, 0x47, 0x42, 0x4d, 0x48, 0x53, 0x56, + 0x59, 0x5c, 0x6f, 0x6a, 0x65, 0x60, 0x7b, 0x7e, 0x71, 0x74, + 0x17, 0x12, 0x1d, 0x18, 0x03, 0x06, 0x09, 0x0c, 0x3f, 0x3a, + 0x35, 0x30, 0x2b, 0x2e, 0x21, 0x24, 0x00, 0x06, 0x0c, 0x0a, + 0x18, 0x1e, 0x14, 0x12, 0x30, 0x36, 0x3c, 0x3a, 0x28, 0x2e, + 0x24, 0x22, 0x60, 0x66, 0x6c, 0x6a, 0x78, 0x7e, 0x74, 0x72, + 0x50, 0x56, 0x5c, 0x5a, 0x48, 0x4e, 0x44, 0x42, 0xc0, 0xc6, + 0xcc, 0xca, 0xd8, 0xde, 0xd4, 0xd2, 0xf0, 0xf6, 0xfc, 0xfa, + 0xe8, 0xee, 0xe4, 0xe2, 0xa0, 0xa6, 0xac, 0xaa, 0xb8, 0xbe, + 0xb4, 0xb2, 0x90, 0x96, 0x9c, 0x9a, 0x88, 0x8e, 0x84, 0x82, + 0x9d, 0x9b, 0x91, 0x97, 0x85, 0x83, 0x89, 0x8f, 0xad, 0xab, + 0xa1, 0xa7, 0xb5, 0xb3, 0xb9, 0xbf, 0xfd, 0xfb, 0xf1, 0xf7, + 0xe5, 0xe3, 0xe9, 0xef, 0xcd, 0xcb, 0xc1, 0xc7, 0xd5, 0xd3, + 0xd9, 0xdf, 0x5d, 0x5b, 0x51, 0x57, 0x45, 0x43, 0x49, 0x4f, + 0x6d, 0x6b, 0x61, 0x67, 0x75, 0x73, 0x79, 0x7f, 0x3d, 0x3b, + 0x31, 0x37, 0x25, 0x23, 0x29, 0x2f, 0x0d, 0x0b, 0x01, 0x07, + 0x15, 0x13, 0x19, 0x1f, 0x27, 0x21, 0x2b, 0x2d, 0x3f, 0x39, + 0x33, 0x35, 0x17, 0x11, 0x1b, 0x1d, 0x0f, 0x09, 0x03, 0x05, + 0x47, 0x41, 0x4b, 0x4d, 0x5f, 0x59, 0x53, 0x55, 0x77, 0x71, + 0x7b, 0x7d, 0x6f, 0x69, 0x63, 0x65, 0xe7, 0xe1, 0xeb, 0xed, + 0xff, 0xf9, 0xf3, 0xf5, 0xd7, 0xd1, 0xdb, 0xdd, 0xcf, 0xc9, + 0xc3, 0xc5, 0x87, 0x81, 0x8b, 0x8d, 0x9f, 0x99, 0x93, 0x95, + 0xb7, 0xb1, 0xbb, 0xbd, 0xaf, 0xa9, 0xa3, 0xa5, 0xba, 0xbc, + 0xb6, 0xb0, 0xa2, 0xa4, 0xae, 0xa8, 0x8a, 0x8c, 0x86, 0x80, + 0x92, 0x94, 0x9e, 0x98, 0xda, 0xdc, 0xd6, 0xd0, 0xc2, 0xc4, + 0xce, 0xc8, 0xea, 0xec, 0xe6, 0xe0, 0xf2, 0xf4, 0xfe, 0xf8, + 0x7a, 0x7c, 0x76, 0x70, 0x62, 0x64, 0x6e, 0x68, 0x4a, 0x4c, + 0x46, 0x40, 0x52, 0x54, 0x5e, 0x58, 0x1a, 0x1c, 0x16, 0x10, + 0x02, 0x04, 0x0e, 0x08, 0x2a, 0x2c, 0x26, 0x20, 0x32, 0x34, + 0x3e, 0x38, 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, + 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d, 0x70, 0x77, + 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, 0x48, 0x4f, 0x46, 0x41, + 0x54, 0x53, 0x5a, 0x5d, 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, + 0xf2, 0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd, + 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 0xa8, 0xaf, + 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd, 0xdd, 0xda, 0xd3, 0xd4, + 0xc1, 0xc6, 0xcf, 0xc8, 0xe5, 0xe2, 0xeb, 0xec, 0xf9, 0xfe, + 0xf7, 0xf0, 0xad, 0xaa, 0xa3, 0xa4, 0xb1, 0xb6, 0xbf, 0xb8, + 0x95, 0x92, 0x9b, 0x9c, 0x89, 0x8e, 0x87, 0x80, 0x3d, 0x3a, + 0x33, 0x34, 0x21, 0x26, 0x2f, 0x28, 0x05, 0x02, 0x0b, 0x0c, + 0x19, 0x1e, 0x17, 0x10, 0x4d, 0x4a, 0x43, 0x44, 0x51, 0x56, + 0x5f, 0x58, 0x75, 0x72, 0x7b, 0x7c, 0x69, 0x6e, 0x67, 0x60, + 0xa7, 0xa0, 0xa9, 0xae, 0xbb, 0xbc, 0xb5, 0xb2, 0x9f, 0x98, + 0x91, 0x96, 0x83, 0x84, 0x8d, 0x8a, 0xd7, 0xd0, 0xd9, 0xde, + 0xcb, 0xcc, 0xc5, 0xc2, 0xef, 0xe8, 0xe1, 0xe6, 0xf3, 0xf4, + 0xfd, 0xfa, 0x47, 0x40, 0x49, 0x4e, 0x5b, 0x5c, 0x55, 0x52, + 0x7f, 0x78, 0x71, 0x76, 0x63, 0x64, 0x6d, 0x6a, 0x37, 0x30, + 0x39, 0x3e, 0x2b, 0x2c, 0x25, 0x22, 0x0f, 0x08, 0x01, 0x06, + 0x13, 0x14, 0x1d, 0x1a, 0x7a, 0x7d, 0x74, 0x73, 0x66, 0x61, + 0x68, 0x6f, 0x42, 0x45, 0x4c, 0x4b, 0x5e, 0x59, 0x50, 0x57, + 0x0a, 0x0d, 0x04, 0x03, 0x16, 0x11, 0x18, 0x1f, 0x32, 0x35, + 0x3c, 0x3b, 0x2e, 0x29, 0x20, 0x27, 0x9a, 0x9d, 0x94, 0x93, + 0x86, 0x81, 0x88, 0x8f, 0xa2, 0xa5, 0xac, 0xab, 0xbe, 0xb9, + 0xb0, 0xb7, 0xea, 0xed, 0xe4, 0xe3, 0xf6, 0xf1, 0xf8, 0xff, + 0xd2, 0xd5, 0xdc, 0xdb, 0xce, 0xc9, 0xc0, 0xc7, 0x00, 0x08, + 0x10, 0x18, 0x20, 0x28, 0x30, 0x38, 0x40, 0x48, 0x50, 0x58, + 0x60, 0x68, 0x70, 0x78, 0x80, 0x88, 0x90, 0x98, 0xa0, 0xa8, + 0xb0, 0xb8, 0xc0, 0xc8, 0xd0, 0xd8, 0xe0, 0xe8, 0xf0, 0xf8, + 0x1d, 0x15, 0x0d, 0x05, 0x3d, 0x35, 0x2d, 0x25, 0x5d, 0x55, + 0x4d, 0x45, 0x7d, 0x75, 0x6d, 0x65, 0x9d, 0x95, 0x8d, 0x85, + 0xbd, 0xb5, 0xad, 0xa5, 0xdd, 0xd5, 0xcd, 0xc5, 0xfd, 0xf5, + 0xed, 0xe5, 0x3a, 0x32, 0x2a, 0x22, 0x1a, 0x12, 0x0a, 0x02, + 0x7a, 0x72, 0x6a, 0x62, 0x5a, 0x52, 0x4a, 0x42, 0xba, 0xb2, + 0xaa, 0xa2, 0x9a, 0x92, 0x8a, 0x82, 0xfa, 0xf2, 0xea, 0xe2, + 0xda, 0xd2, 0xca, 0xc2, 0x27, 0x2f, 0x37, 0x3f, 0x07, 0x0f, + 0x17, 0x1f, 0x67, 0x6f, 0x77, 0x7f, 0x47, 0x4f, 0x57, 0x5f, + 0xa7, 0xaf, 0xb7, 0xbf, 0x87, 0x8f, 0x97, 0x9f, 0xe7, 0xef, + 0xf7, 0xff, 0xc7, 0xcf, 0xd7, 0xdf, 0x74, 0x7c, 0x64, 0x6c, + 0x54, 0x5c, 0x44, 0x4c, 0x34, 0x3c, 0x24, 0x2c, 0x14, 0x1c, + 0x04, 0x0c, 0xf4, 0xfc, 0xe4, 0xec, 0xd4, 0xdc, 0xc4, 0xcc, + 0xb4, 0xbc, 0xa4, 0xac, 0x94, 0x9c, 0x84, 0x8c, 0x69, 0x61, + 0x79, 0x71, 0x49, 0x41, 0x59, 0x51, 0x29, 0x21, 0x39, 0x31, + 0x09, 0x01, 0x19, 0x11, 0xe9, 0xe1, 0xf9, 0xf1, 0xc9, 0xc1, + 0xd9, 0xd1, 0xa9, 0xa1, 0xb9, 0xb1, 0x89, 0x81, 0x99, 0x91, + 0x4e, 0x46, 0x5e, 0x56, 0x6e, 0x66, 0x7e, 0x76, 0x0e, 0x06, + 0x1e, 0x16, 0x2e, 0x26, 0x3e, 0x36, 0xce, 0xc6, 0xde, 0xd6, + 0xee, 0xe6, 0xfe, 0xf6, 0x8e, 0x86, 0x9e, 0x96, 0xae, 0xa6, + 0xbe, 0xb6, 0x53, 0x5b, 0x43, 0x4b, 0x73, 0x7b, 0x63, 0x6b, + 0x13, 0x1b, 0x03, 0x0b, 0x33, 0x3b, 0x23, 0x2b, 0xd3, 0xdb, + 0xc3, 0xcb, 0xf3, 0xfb, 0xe3, 0xeb, 0x93, 0x9b, 0x83, 0x8b, + 0xb3, 0xbb, 0xa3, 0xab, 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, + 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, + 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, + 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7, 0x3d, 0x34, 0x2f, 0x26, + 0x19, 0x10, 0x0b, 0x02, 0x75, 0x7c, 0x67, 0x6e, 0x51, 0x58, + 0x43, 0x4a, 0xad, 0xa4, 0xbf, 0xb6, 0x89, 0x80, 0x9b, 0x92, + 0xe5, 0xec, 0xf7, 0xfe, 0xc1, 0xc8, 0xd3, 0xda, 0x7a, 0x73, + 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45, 0x32, 0x3b, 0x20, 0x29, + 0x16, 0x1f, 0x04, 0x0d, 0xea, 0xe3, 0xf8, 0xf1, 0xce, 0xc7, + 0xdc, 0xd5, 0xa2, 0xab, 0xb0, 0xb9, 0x86, 0x8f, 0x94, 0x9d, + 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, + 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30, 0xd7, 0xde, 0xc5, 0xcc, + 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, + 0xa9, 0xa0, 0xf4, 0xfd, 0xe6, 0xef, 0xd0, 0xd9, 0xc2, 0xcb, + 0xbc, 0xb5, 0xae, 0xa7, 0x98, 0x91, 0x8a, 0x83, 0x64, 0x6d, + 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b, 0x2c, 0x25, 0x3e, 0x37, + 0x08, 0x01, 0x1a, 0x13, 0xc9, 0xc0, 0xdb, 0xd2, 0xed, 0xe4, + 0xff, 0xf6, 0x81, 0x88, 0x93, 0x9a, 0xa5, 0xac, 0xb7, 0xbe, + 0x59, 0x50, 0x4b, 0x42, 0x7d, 0x74, 0x6f, 0x66, 0x11, 0x18, + 0x03, 0x0a, 0x35, 0x3c, 0x27, 0x2e, 0x8e, 0x87, 0x9c, 0x95, + 0xaa, 0xa3, 0xb8, 0xb1, 0xc6, 0xcf, 0xd4, 0xdd, 0xe2, 0xeb, + 0xf0, 0xf9, 0x1e, 0x17, 0x0c, 0x05, 0x3a, 0x33, 0x28, 0x21, + 0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69, 0xb3, 0xba, + 0xa1, 0xa8, 0x97, 0x9e, 0x85, 0x8c, 0xfb, 0xf2, 0xe9, 0xe0, + 0xdf, 0xd6, 0xcd, 0xc4, 0x23, 0x2a, 0x31, 0x38, 0x07, 0x0e, + 0x15, 0x1c, 0x6b, 0x62, 0x79, 0x70, 0x4f, 0x46, 0x5d, 0x54, + 0x00, 0x0a, 0x14, 0x1e, 0x28, 0x22, 0x3c, 0x36, 0x50, 0x5a, + 0x44, 0x4e, 0x78, 0x72, 0x6c, 0x66, 0xa0, 0xaa, 0xb4, 0xbe, + 0x88, 0x82, 0x9c, 0x96, 0xf0, 0xfa, 0xe4, 0xee, 0xd8, 0xd2, + 0xcc, 0xc6, 0x5d, 0x57, 0x49, 0x43, 0x75, 0x7f, 0x61, 0x6b, + 0x0d, 0x07, 0x19, 0x13, 0x25, 0x2f, 0x31, 0x3b, 0xfd, 0xf7, + 0xe9, 0xe3, 0xd5, 0xdf, 0xc1, 0xcb, 0xad, 0xa7, 0xb9, 0xb3, + 0x85, 0x8f, 0x91, 0x9b, 0xba, 0xb0, 0xae, 0xa4, 0x92, 0x98, + 0x86, 0x8c, 0xea, 0xe0, 0xfe, 0xf4, 0xc2, 0xc8, 0xd6, 0xdc, + 0x1a, 0x10, 0x0e, 0x04, 0x32, 0x38, 0x26, 0x2c, 0x4a, 0x40, + 0x5e, 0x54, 0x62, 0x68, 0x76, 0x7c, 0xe7, 0xed, 0xf3, 0xf9, + 0xcf, 0xc5, 0xdb, 0xd1, 0xb7, 0xbd, 0xa3, 0xa9, 0x9f, 0x95, + 0x8b, 0x81, 0x47, 0x4d, 0x53, 0x59, 0x6f, 0x65, 0x7b, 0x71, + 0x17, 0x1d, 0x03, 0x09, 0x3f, 0x35, 0x2b, 0x21, 0x69, 0x63, + 0x7d, 0x77, 0x41, 0x4b, 0x55, 0x5f, 0x39, 0x33, 0x2d, 0x27, + 0x11, 0x1b, 0x05, 0x0f, 0xc9, 0xc3, 0xdd, 0xd7, 0xe1, 0xeb, + 0xf5, 0xff, 0x99, 0x93, 0x8d, 0x87, 0xb1, 0xbb, 0xa5, 0xaf, + 0x34, 0x3e, 0x20, 0x2a, 0x1c, 0x16, 0x08, 0x02, 0x64, 0x6e, + 0x70, 0x7a, 0x4c, 0x46, 0x58, 0x52, 0x94, 0x9e, 0x80, 0x8a, + 0xbc, 0xb6, 0xa8, 0xa2, 0xc4, 0xce, 0xd0, 0xda, 0xec, 0xe6, + 0xf8, 0xf2, 0xd3, 0xd9, 0xc7, 0xcd, 0xfb, 0xf1, 0xef, 0xe5, + 0x83, 0x89, 0x97, 0x9d, 0xab, 0xa1, 0xbf, 0xb5, 0x73, 0x79, + 0x67, 0x6d, 0x5b, 0x51, 0x4f, 0x45, 0x23, 0x29, 0x37, 0x3d, + 0x0b, 0x01, 0x1f, 0x15, 0x8e, 0x84, 0x9a, 0x90, 0xa6, 0xac, + 0xb2, 0xb8, 0xde, 0xd4, 0xca, 0xc0, 0xf6, 0xfc, 0xe2, 0xe8, + 0x2e, 0x24, 0x3a, 0x30, 0x06, 0x0c, 0x12, 0x18, 0x7e, 0x74, + 0x6a, 0x60, 0x56, 0x5c, 0x42, 0x48, 0x00, 0x0b, 0x16, 0x1d, + 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, + 0x62, 0x69, 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, + 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9, 0x7d, 0x76, + 0x6b, 0x60, 0x51, 0x5a, 0x47, 0x4c, 0x25, 0x2e, 0x33, 0x38, + 0x09, 0x02, 0x1f, 0x14, 0xcd, 0xc6, 0xdb, 0xd0, 0xe1, 0xea, + 0xf7, 0xfc, 0x95, 0x9e, 0x83, 0x88, 0xb9, 0xb2, 0xaf, 0xa4, + 0xfa, 0xf1, 0xec, 0xe7, 0xd6, 0xdd, 0xc0, 0xcb, 0xa2, 0xa9, + 0xb4, 0xbf, 0x8e, 0x85, 0x98, 0x93, 0x4a, 0x41, 0x5c, 0x57, + 0x66, 0x6d, 0x70, 0x7b, 0x12, 0x19, 0x04, 0x0f, 0x3e, 0x35, + 0x28, 0x23, 0x87, 0x8c, 0x91, 0x9a, 0xab, 0xa0, 0xbd, 0xb6, + 0xdf, 0xd4, 0xc9, 0xc2, 0xf3, 0xf8, 0xe5, 0xee, 0x37, 0x3c, + 0x21, 0x2a, 0x1b, 0x10, 0x0d, 0x06, 0x6f, 0x64, 0x79, 0x72, + 0x43, 0x48, 0x55, 0x5e, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, + 0xd3, 0xd8, 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, + 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68, 0x01, 0x0a, + 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x94, 0x9f, 0x82, 0x89, + 0xb8, 0xb3, 0xae, 0xa5, 0xcc, 0xc7, 0xda, 0xd1, 0xe0, 0xeb, + 0xf6, 0xfd, 0x24, 0x2f, 0x32, 0x39, 0x08, 0x03, 0x1e, 0x15, + 0x7c, 0x77, 0x6a, 0x61, 0x50, 0x5b, 0x46, 0x4d, 0x13, 0x18, + 0x05, 0x0e, 0x3f, 0x34, 0x29, 0x22, 0x4b, 0x40, 0x5d, 0x56, + 0x67, 0x6c, 0x71, 0x7a, 0xa3, 0xa8, 0xb5, 0xbe, 0x8f, 0x84, + 0x99, 0x92, 0xfb, 0xf0, 0xed, 0xe6, 0xd7, 0xdc, 0xc1, 0xca, + 0x6e, 0x65, 0x78, 0x73, 0x42, 0x49, 0x54, 0x5f, 0x36, 0x3d, + 0x20, 0x2b, 0x1a, 0x11, 0x0c, 0x07, 0xde, 0xd5, 0xc8, 0xc3, + 0xf2, 0xf9, 0xe4, 0xef, 0x86, 0x8d, 0x90, 0x9b, 0xaa, 0xa1, + 0xbc, 0xb7, 0x00, 0x0c, 0x18, 0x14, 0x30, 0x3c, 0x28, 0x24, + 0x60, 0x6c, 0x78, 0x74, 0x50, 0x5c, 0x48, 0x44, 0xc0, 0xcc, + 0xd8, 0xd4, 0xf0, 0xfc, 0xe8, 0xe4, 0xa0, 0xac, 0xb8, 0xb4, + 0x90, 0x9c, 0x88, 0x84, 0x9d, 0x91, 0x85, 0x89, 0xad, 0xa1, + 0xb5, 0xb9, 0xfd, 0xf1, 0xe5, 0xe9, 0xcd, 0xc1, 0xd5, 0xd9, + 0x5d, 0x51, 0x45, 0x49, 0x6d, 0x61, 0x75, 0x79, 0x3d, 0x31, + 0x25, 0x29, 0x0d, 0x01, 0x15, 0x19, 0x27, 0x2b, 0x3f, 0x33, + 0x17, 0x1b, 0x0f, 0x03, 0x47, 0x4b, 0x5f, 0x53, 0x77, 0x7b, + 0x6f, 0x63, 0xe7, 0xeb, 0xff, 0xf3, 0xd7, 0xdb, 0xcf, 0xc3, + 0x87, 0x8b, 0x9f, 0x93, 0xb7, 0xbb, 0xaf, 0xa3, 0xba, 0xb6, + 0xa2, 0xae, 0x8a, 0x86, 0x92, 0x9e, 0xda, 0xd6, 0xc2, 0xce, + 0xea, 0xe6, 0xf2, 0xfe, 0x7a, 0x76, 0x62, 0x6e, 0x4a, 0x46, + 0x52, 0x5e, 0x1a, 0x16, 0x02, 0x0e, 0x2a, 0x26, 0x32, 0x3e, + 0x4e, 0x42, 0x56, 0x5a, 0x7e, 0x72, 0x66, 0x6a, 0x2e, 0x22, + 0x36, 0x3a, 0x1e, 0x12, 0x06, 0x0a, 0x8e, 0x82, 0x96, 0x9a, + 0xbe, 0xb2, 0xa6, 0xaa, 0xee, 0xe2, 0xf6, 0xfa, 0xde, 0xd2, + 0xc6, 0xca, 0xd3, 0xdf, 0xcb, 0xc7, 0xe3, 0xef, 0xfb, 0xf7, + 0xb3, 0xbf, 0xab, 0xa7, 0x83, 0x8f, 0x9b, 0x97, 0x13, 0x1f, + 0x0b, 0x07, 0x23, 0x2f, 0x3b, 0x37, 0x73, 0x7f, 0x6b, 0x67, + 0x43, 0x4f, 0x5b, 0x57, 0x69, 0x65, 0x71, 0x7d, 0x59, 0x55, + 0x41, 0x4d, 0x09, 0x05, 0x11, 0x1d, 0x39, 0x35, 0x21, 0x2d, + 0xa9, 0xa5, 0xb1, 0xbd, 0x99, 0x95, 0x81, 0x8d, 0xc9, 0xc5, + 0xd1, 0xdd, 0xf9, 0xf5, 0xe1, 0xed, 0xf4, 0xf8, 0xec, 0xe0, + 0xc4, 0xc8, 0xdc, 0xd0, 0x94, 0x98, 0x8c, 0x80, 0xa4, 0xa8, + 0xbc, 0xb0, 0x34, 0x38, 0x2c, 0x20, 0x04, 0x08, 0x1c, 0x10, + 0x54, 0x58, 0x4c, 0x40, 0x64, 0x68, 0x7c, 0x70, 0x00, 0x0d, + 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, + 0x5c, 0x51, 0x46, 0x4b, 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, + 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b, + 0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, + 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6, 0x6d, 0x60, 0x77, 0x7a, + 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, + 0x2b, 0x26, 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, + 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c, 0xb7, 0xba, + 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, + 0xeb, 0xe6, 0xf1, 0xfc, 0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, + 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91, + 0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, + 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41, 0xce, 0xc3, 0xd4, 0xd9, + 0xfa, 0xf7, 0xe0, 0xed, 0xa6, 0xab, 0xbc, 0xb1, 0x92, 0x9f, + 0x88, 0x85, 0x1e, 0x13, 0x04, 0x09, 0x2a, 0x27, 0x30, 0x3d, + 0x76, 0x7b, 0x6c, 0x61, 0x42, 0x4f, 0x58, 0x55, 0x73, 0x7e, + 0x69, 0x64, 0x47, 0x4a, 0x5d, 0x50, 0x1b, 0x16, 0x01, 0x0c, + 0x2f, 0x22, 0x35, 0x38, 0xa3, 0xae, 0xb9, 0xb4, 0x97, 0x9a, + 0x8d, 0x80, 0xcb, 0xc6, 0xd1, 0xdc, 0xff, 0xf2, 0xe5, 0xe8, + 0xa9, 0xa4, 0xb3, 0xbe, 0x9d, 0x90, 0x87, 0x8a, 0xc1, 0xcc, + 0xdb, 0xd6, 0xf5, 0xf8, 0xef, 0xe2, 0x79, 0x74, 0x63, 0x6e, + 0x4d, 0x40, 0x57, 0x5a, 0x11, 0x1c, 0x0b, 0x06, 0x25, 0x28, + 0x3f, 0x32, 0x14, 0x19, 0x0e, 0x03, 0x20, 0x2d, 0x3a, 0x37, + 0x7c, 0x71, 0x66, 0x6b, 0x48, 0x45, 0x52, 0x5f, 0xc4, 0xc9, + 0xde, 0xd3, 0xf0, 0xfd, 0xea, 0xe7, 0xac, 0xa1, 0xb6, 0xbb, + 0x98, 0x95, 0x82, 0x8f, 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, + 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a, + 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, + 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba, 0xdd, 0xd3, 0xc1, 0xcf, + 0xe5, 0xeb, 0xf9, 0xf7, 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, + 0x89, 0x87, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17, + 0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0xa7, 0xa9, + 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d, 0xd7, 0xd9, 0xcb, 0xc5, + 0xef, 0xe1, 0xf3, 0xfd, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, + 0x63, 0x6d, 0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, + 0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, + 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20, 0x9a, 0x94, 0x86, 0x88, + 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, + 0xce, 0xc0, 0x53, 0x5d, 0x4f, 0x41, 0x6b, 0x65, 0x77, 0x79, + 0x23, 0x2d, 0x3f, 0x31, 0x1b, 0x15, 0x07, 0x09, 0xb3, 0xbd, + 0xaf, 0xa1, 0x8b, 0x85, 0x97, 0x99, 0xc3, 0xcd, 0xdf, 0xd1, + 0xfb, 0xf5, 0xe7, 0xe9, 0x8e, 0x80, 0x92, 0x9c, 0xb6, 0xb8, + 0xaa, 0xa4, 0xfe, 0xf0, 0xe2, 0xec, 0xc6, 0xc8, 0xda, 0xd4, + 0x6e, 0x60, 0x72, 0x7c, 0x56, 0x58, 0x4a, 0x44, 0x1e, 0x10, + 0x02, 0x0c, 0x26, 0x28, 0x3a, 0x34, 0xf4, 0xfa, 0xe8, 0xe6, + 0xcc, 0xc2, 0xd0, 0xde, 0x84, 0x8a, 0x98, 0x96, 0xbc, 0xb2, + 0xa0, 0xae, 0x14, 0x1a, 0x08, 0x06, 0x2c, 0x22, 0x30, 0x3e, + 0x64, 0x6a, 0x78, 0x76, 0x5c, 0x52, 0x40, 0x4e, 0x29, 0x27, + 0x35, 0x3b, 0x11, 0x1f, 0x0d, 0x03, 0x59, 0x57, 0x45, 0x4b, + 0x61, 0x6f, 0x7d, 0x73, 0xc9, 0xc7, 0xd5, 0xdb, 0xf1, 0xff, + 0xed, 0xe3, 0xb9, 0xb7, 0xa5, 0xab, 0x81, 0x8f, 0x9d, 0x93, + 0x00, 0x0f, 0x1e, 0x11, 0x3c, 0x33, 0x22, 0x2d, 0x78, 0x77, + 0x66, 0x69, 0x44, 0x4b, 0x5a, 0x55, 0xf0, 0xff, 0xee, 0xe1, + 0xcc, 0xc3, 0xd2, 0xdd, 0x88, 0x87, 0x96, 0x99, 0xb4, 0xbb, + 0xaa, 0xa5, 0xfd, 0xf2, 0xe3, 0xec, 0xc1, 0xce, 0xdf, 0xd0, + 0x85, 0x8a, 0x9b, 0x94, 0xb9, 0xb6, 0xa7, 0xa8, 0x0d, 0x02, + 0x13, 0x1c, 0x31, 0x3e, 0x2f, 0x20, 0x75, 0x7a, 0x6b, 0x64, + 0x49, 0x46, 0x57, 0x58, 0xe7, 0xe8, 0xf9, 0xf6, 0xdb, 0xd4, + 0xc5, 0xca, 0x9f, 0x90, 0x81, 0x8e, 0xa3, 0xac, 0xbd, 0xb2, + 0x17, 0x18, 0x09, 0x06, 0x2b, 0x24, 0x35, 0x3a, 0x6f, 0x60, + 0x71, 0x7e, 0x53, 0x5c, 0x4d, 0x42, 0x1a, 0x15, 0x04, 0x0b, + 0x26, 0x29, 0x38, 0x37, 0x62, 0x6d, 0x7c, 0x73, 0x5e, 0x51, + 0x40, 0x4f, 0xea, 0xe5, 0xf4, 0xfb, 0xd6, 0xd9, 0xc8, 0xc7, + 0x92, 0x9d, 0x8c, 0x83, 0xae, 0xa1, 0xb0, 0xbf, 0xd3, 0xdc, + 0xcd, 0xc2, 0xef, 0xe0, 0xf1, 0xfe, 0xab, 0xa4, 0xb5, 0xba, + 0x97, 0x98, 0x89, 0x86, 0x23, 0x2c, 0x3d, 0x32, 0x1f, 0x10, + 0x01, 0x0e, 0x5b, 0x54, 0x45, 0x4a, 0x67, 0x68, 0x79, 0x76, + 0x2e, 0x21, 0x30, 0x3f, 0x12, 0x1d, 0x0c, 0x03, 0x56, 0x59, + 0x48, 0x47, 0x6a, 0x65, 0x74, 0x7b, 0xde, 0xd1, 0xc0, 0xcf, + 0xe2, 0xed, 0xfc, 0xf3, 0xa6, 0xa9, 0xb8, 0xb7, 0x9a, 0x95, + 0x84, 0x8b, 0x34, 0x3b, 0x2a, 0x25, 0x08, 0x07, 0x16, 0x19, + 0x4c, 0x43, 0x52, 0x5d, 0x70, 0x7f, 0x6e, 0x61, 0xc4, 0xcb, + 0xda, 0xd5, 0xf8, 0xf7, 0xe6, 0xe9, 0xbc, 0xb3, 0xa2, 0xad, + 0x80, 0x8f, 0x9e, 0x91, 0xc9, 0xc6, 0xd7, 0xd8, 0xf5, 0xfa, + 0xeb, 0xe4, 0xb1, 0xbe, 0xaf, 0xa0, 0x8d, 0x82, 0x93, 0x9c, + 0x39, 0x36, 0x27, 0x28, 0x05, 0x0a, 0x1b, 0x14, 0x41, 0x4e, + 0x5f, 0x50, 0x7d, 0x72, 0x63, 0x6c, 0x00, 0x10, 0x20, 0x30, + 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, + 0xe0, 0xf0, 0x1d, 0x0d, 0x3d, 0x2d, 0x5d, 0x4d, 0x7d, 0x6d, + 0x9d, 0x8d, 0xbd, 0xad, 0xdd, 0xcd, 0xfd, 0xed, 0x3a, 0x2a, + 0x1a, 0x0a, 0x7a, 0x6a, 0x5a, 0x4a, 0xba, 0xaa, 0x9a, 0x8a, + 0xfa, 0xea, 0xda, 0xca, 0x27, 0x37, 0x07, 0x17, 0x67, 0x77, + 0x47, 0x57, 0xa7, 0xb7, 0x87, 0x97, 0xe7, 0xf7, 0xc7, 0xd7, + 0x74, 0x64, 0x54, 0x44, 0x34, 0x24, 0x14, 0x04, 0xf4, 0xe4, + 0xd4, 0xc4, 0xb4, 0xa4, 0x94, 0x84, 0x69, 0x79, 0x49, 0x59, + 0x29, 0x39, 0x09, 0x19, 0xe9, 0xf9, 0xc9, 0xd9, 0xa9, 0xb9, + 0x89, 0x99, 0x4e, 0x5e, 0x6e, 0x7e, 0x0e, 0x1e, 0x2e, 0x3e, + 0xce, 0xde, 0xee, 0xfe, 0x8e, 0x9e, 0xae, 0xbe, 0x53, 0x43, + 0x73, 0x63, 0x13, 0x03, 0x33, 0x23, 0xd3, 0xc3, 0xf3, 0xe3, + 0x93, 0x83, 0xb3, 0xa3, 0xe8, 0xf8, 0xc8, 0xd8, 0xa8, 0xb8, + 0x88, 0x98, 0x68, 0x78, 0x48, 0x58, 0x28, 0x38, 0x08, 0x18, + 0xf5, 0xe5, 0xd5, 0xc5, 0xb5, 0xa5, 0x95, 0x85, 0x75, 0x65, + 0x55, 0x45, 0x35, 0x25, 0x15, 0x05, 0xd2, 0xc2, 0xf2, 0xe2, + 0x92, 0x82, 0xb2, 0xa2, 0x52, 0x42, 0x72, 0x62, 0x12, 0x02, + 0x32, 0x22, 0xcf, 0xdf, 0xef, 0xff, 0x8f, 0x9f, 0xaf, 0xbf, + 0x4f, 0x5f, 0x6f, 0x7f, 0x0f, 0x1f, 0x2f, 0x3f, 0x9c, 0x8c, + 0xbc, 0xac, 0xdc, 0xcc, 0xfc, 0xec, 0x1c, 0x0c, 0x3c, 0x2c, + 0x5c, 0x4c, 0x7c, 0x6c, 0x81, 0x91, 0xa1, 0xb1, 0xc1, 0xd1, + 0xe1, 0xf1, 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, + 0xa6, 0xb6, 0x86, 0x96, 0xe6, 0xf6, 0xc6, 0xd6, 0x26, 0x36, + 0x06, 0x16, 0x66, 0x76, 0x46, 0x56, 0xbb, 0xab, 0x9b, 0x8b, + 0xfb, 0xeb, 0xdb, 0xcb, 0x3b, 0x2b, 0x1b, 0x0b, 0x7b, 0x6b, + 0x5b, 0x4b, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x0d, 0x1c, + 0x2f, 0x3e, 0x49, 0x58, 0x6b, 0x7a, 0x85, 0x94, 0xa7, 0xb6, + 0xc1, 0xd0, 0xe3, 0xf2, 0x1a, 0x0b, 0x38, 0x29, 0x5e, 0x4f, + 0x7c, 0x6d, 0x92, 0x83, 0xb0, 0xa1, 0xd6, 0xc7, 0xf4, 0xe5, + 0x17, 0x06, 0x35, 0x24, 0x53, 0x42, 0x71, 0x60, 0x9f, 0x8e, + 0xbd, 0xac, 0xdb, 0xca, 0xf9, 0xe8, 0x34, 0x25, 0x16, 0x07, + 0x70, 0x61, 0x52, 0x43, 0xbc, 0xad, 0x9e, 0x8f, 0xf8, 0xe9, + 0xda, 0xcb, 0x39, 0x28, 0x1b, 0x0a, 0x7d, 0x6c, 0x5f, 0x4e, + 0xb1, 0xa0, 0x93, 0x82, 0xf5, 0xe4, 0xd7, 0xc6, 0x2e, 0x3f, + 0x0c, 0x1d, 0x6a, 0x7b, 0x48, 0x59, 0xa6, 0xb7, 0x84, 0x95, + 0xe2, 0xf3, 0xc0, 0xd1, 0x23, 0x32, 0x01, 0x10, 0x67, 0x76, + 0x45, 0x54, 0xab, 0xba, 0x89, 0x98, 0xef, 0xfe, 0xcd, 0xdc, + 0x68, 0x79, 0x4a, 0x5b, 0x2c, 0x3d, 0x0e, 0x1f, 0xe0, 0xf1, + 0xc2, 0xd3, 0xa4, 0xb5, 0x86, 0x97, 0x65, 0x74, 0x47, 0x56, + 0x21, 0x30, 0x03, 0x12, 0xed, 0xfc, 0xcf, 0xde, 0xa9, 0xb8, + 0x8b, 0x9a, 0x72, 0x63, 0x50, 0x41, 0x36, 0x27, 0x14, 0x05, + 0xfa, 0xeb, 0xd8, 0xc9, 0xbe, 0xaf, 0x9c, 0x8d, 0x7f, 0x6e, + 0x5d, 0x4c, 0x3b, 0x2a, 0x19, 0x08, 0xf7, 0xe6, 0xd5, 0xc4, + 0xb3, 0xa2, 0x91, 0x80, 0x5c, 0x4d, 0x7e, 0x6f, 0x18, 0x09, + 0x3a, 0x2b, 0xd4, 0xc5, 0xf6, 0xe7, 0x90, 0x81, 0xb2, 0xa3, + 0x51, 0x40, 0x73, 0x62, 0x15, 0x04, 0x37, 0x26, 0xd9, 0xc8, + 0xfb, 0xea, 0x9d, 0x8c, 0xbf, 0xae, 0x46, 0x57, 0x64, 0x75, + 0x02, 0x13, 0x20, 0x31, 0xce, 0xdf, 0xec, 0xfd, 0x8a, 0x9b, + 0xa8, 0xb9, 0x4b, 0x5a, 0x69, 0x78, 0x0f, 0x1e, 0x2d, 0x3c, + 0xc3, 0xd2, 0xe1, 0xf0, 0x87, 0x96, 0xa5, 0xb4, 0x00, 0x12, + 0x24, 0x36, 0x48, 0x5a, 0x6c, 0x7e, 0x90, 0x82, 0xb4, 0xa6, + 0xd8, 0xca, 0xfc, 0xee, 0x3d, 0x2f, 0x19, 0x0b, 0x75, 0x67, + 0x51, 0x43, 0xad, 0xbf, 0x89, 0x9b, 0xe5, 0xf7, 0xc1, 0xd3, + 0x7a, 0x68, 0x5e, 0x4c, 0x32, 0x20, 0x16, 0x04, 0xea, 0xf8, + 0xce, 0xdc, 0xa2, 0xb0, 0x86, 0x94, 0x47, 0x55, 0x63, 0x71, + 0x0f, 0x1d, 0x2b, 0x39, 0xd7, 0xc5, 0xf3, 0xe1, 0x9f, 0x8d, + 0xbb, 0xa9, 0xf4, 0xe6, 0xd0, 0xc2, 0xbc, 0xae, 0x98, 0x8a, + 0x64, 0x76, 0x40, 0x52, 0x2c, 0x3e, 0x08, 0x1a, 0xc9, 0xdb, + 0xed, 0xff, 0x81, 0x93, 0xa5, 0xb7, 0x59, 0x4b, 0x7d, 0x6f, + 0x11, 0x03, 0x35, 0x27, 0x8e, 0x9c, 0xaa, 0xb8, 0xc6, 0xd4, + 0xe2, 0xf0, 0x1e, 0x0c, 0x3a, 0x28, 0x56, 0x44, 0x72, 0x60, + 0xb3, 0xa1, 0x97, 0x85, 0xfb, 0xe9, 0xdf, 0xcd, 0x23, 0x31, + 0x07, 0x15, 0x6b, 0x79, 0x4f, 0x5d, 0xf5, 0xe7, 0xd1, 0xc3, + 0xbd, 0xaf, 0x99, 0x8b, 0x65, 0x77, 0x41, 0x53, 0x2d, 0x3f, + 0x09, 0x1b, 0xc8, 0xda, 0xec, 0xfe, 0x80, 0x92, 0xa4, 0xb6, + 0x58, 0x4a, 0x7c, 0x6e, 0x10, 0x02, 0x34, 0x26, 0x8f, 0x9d, + 0xab, 0xb9, 0xc7, 0xd5, 0xe3, 0xf1, 0x1f, 0x0d, 0x3b, 0x29, + 0x57, 0x45, 0x73, 0x61, 0xb2, 0xa0, 0x96, 0x84, 0xfa, 0xe8, + 0xde, 0xcc, 0x22, 0x30, 0x06, 0x14, 0x6a, 0x78, 0x4e, 0x5c, + 0x01, 0x13, 0x25, 0x37, 0x49, 0x5b, 0x6d, 0x7f, 0x91, 0x83, + 0xb5, 0xa7, 0xd9, 0xcb, 0xfd, 0xef, 0x3c, 0x2e, 0x18, 0x0a, + 0x74, 0x66, 0x50, 0x42, 0xac, 0xbe, 0x88, 0x9a, 0xe4, 0xf6, + 0xc0, 0xd2, 0x7b, 0x69, 0x5f, 0x4d, 0x33, 0x21, 0x17, 0x05, + 0xeb, 0xf9, 0xcf, 0xdd, 0xa3, 0xb1, 0x87, 0x95, 0x46, 0x54, + 0x62, 0x70, 0x0e, 0x1c, 0x2a, 0x38, 0xd6, 0xc4, 0xf2, 0xe0, + 0x9e, 0x8c, 0xba, 0xa8, 0x00, 0x13, 0x26, 0x35, 0x4c, 0x5f, + 0x6a, 0x79, 0x98, 0x8b, 0xbe, 0xad, 0xd4, 0xc7, 0xf2, 0xe1, + 0x2d, 0x3e, 0x0b, 0x18, 0x61, 0x72, 0x47, 0x54, 0xb5, 0xa6, + 0x93, 0x80, 0xf9, 0xea, 0xdf, 0xcc, 0x5a, 0x49, 0x7c, 0x6f, + 0x16, 0x05, 0x30, 0x23, 0xc2, 0xd1, 0xe4, 0xf7, 0x8e, 0x9d, + 0xa8, 0xbb, 0x77, 0x64, 0x51, 0x42, 0x3b, 0x28, 0x1d, 0x0e, + 0xef, 0xfc, 0xc9, 0xda, 0xa3, 0xb0, 0x85, 0x96, 0xb4, 0xa7, + 0x92, 0x81, 0xf8, 0xeb, 0xde, 0xcd, 0x2c, 0x3f, 0x0a, 0x19, + 0x60, 0x73, 0x46, 0x55, 0x99, 0x8a, 0xbf, 0xac, 0xd5, 0xc6, + 0xf3, 0xe0, 0x01, 0x12, 0x27, 0x34, 0x4d, 0x5e, 0x6b, 0x78, + 0xee, 0xfd, 0xc8, 0xdb, 0xa2, 0xb1, 0x84, 0x97, 0x76, 0x65, + 0x50, 0x43, 0x3a, 0x29, 0x1c, 0x0f, 0xc3, 0xd0, 0xe5, 0xf6, + 0x8f, 0x9c, 0xa9, 0xba, 0x5b, 0x48, 0x7d, 0x6e, 0x17, 0x04, + 0x31, 0x22, 0x75, 0x66, 0x53, 0x40, 0x39, 0x2a, 0x1f, 0x0c, + 0xed, 0xfe, 0xcb, 0xd8, 0xa1, 0xb2, 0x87, 0x94, 0x58, 0x4b, + 0x7e, 0x6d, 0x14, 0x07, 0x32, 0x21, 0xc0, 0xd3, 0xe6, 0xf5, + 0x8c, 0x9f, 0xaa, 0xb9, 0x2f, 0x3c, 0x09, 0x1a, 0x63, 0x70, + 0x45, 0x56, 0xb7, 0xa4, 0x91, 0x82, 0xfb, 0xe8, 0xdd, 0xce, + 0x02, 0x11, 0x24, 0x37, 0x4e, 0x5d, 0x68, 0x7b, 0x9a, 0x89, + 0xbc, 0xaf, 0xd6, 0xc5, 0xf0, 0xe3, 0xc1, 0xd2, 0xe7, 0xf4, + 0x8d, 0x9e, 0xab, 0xb8, 0x59, 0x4a, 0x7f, 0x6c, 0x15, 0x06, + 0x33, 0x20, 0xec, 0xff, 0xca, 0xd9, 0xa0, 0xb3, 0x86, 0x95, + 0x74, 0x67, 0x52, 0x41, 0x38, 0x2b, 0x1e, 0x0d, 0x9b, 0x88, + 0xbd, 0xae, 0xd7, 0xc4, 0xf1, 0xe2, 0x03, 0x10, 0x25, 0x36, + 0x4f, 0x5c, 0x69, 0x7a, 0xb6, 0xa5, 0x90, 0x83, 0xfa, 0xe9, + 0xdc, 0xcf, 0x2e, 0x3d, 0x08, 0x1b, 0x62, 0x71, 0x44, 0x57, + 0x00, 0x14, 0x28, 0x3c, 0x50, 0x44, 0x78, 0x6c, 0xa0, 0xb4, + 0x88, 0x9c, 0xf0, 0xe4, 0xd8, 0xcc, 0x5d, 0x49, 0x75, 0x61, + 0x0d, 0x19, 0x25, 0x31, 0xfd, 0xe9, 0xd5, 0xc1, 0xad, 0xb9, + 0x85, 0x91, 0xba, 0xae, 0x92, 0x86, 0xea, 0xfe, 0xc2, 0xd6, + 0x1a, 0x0e, 0x32, 0x26, 0x4a, 0x5e, 0x62, 0x76, 0xe7, 0xf3, + 0xcf, 0xdb, 0xb7, 0xa3, 0x9f, 0x8b, 0x47, 0x53, 0x6f, 0x7b, + 0x17, 0x03, 0x3f, 0x2b, 0x69, 0x7d, 0x41, 0x55, 0x39, 0x2d, + 0x11, 0x05, 0xc9, 0xdd, 0xe1, 0xf5, 0x99, 0x8d, 0xb1, 0xa5, + 0x34, 0x20, 0x1c, 0x08, 0x64, 0x70, 0x4c, 0x58, 0x94, 0x80, + 0xbc, 0xa8, 0xc4, 0xd0, 0xec, 0xf8, 0xd3, 0xc7, 0xfb, 0xef, + 0x83, 0x97, 0xab, 0xbf, 0x73, 0x67, 0x5b, 0x4f, 0x23, 0x37, + 0x0b, 0x1f, 0x8e, 0x9a, 0xa6, 0xb2, 0xde, 0xca, 0xf6, 0xe2, + 0x2e, 0x3a, 0x06, 0x12, 0x7e, 0x6a, 0x56, 0x42, 0xd2, 0xc6, + 0xfa, 0xee, 0x82, 0x96, 0xaa, 0xbe, 0x72, 0x66, 0x5a, 0x4e, + 0x22, 0x36, 0x0a, 0x1e, 0x8f, 0x9b, 0xa7, 0xb3, 0xdf, 0xcb, + 0xf7, 0xe3, 0x2f, 0x3b, 0x07, 0x13, 0x7f, 0x6b, 0x57, 0x43, + 0x68, 0x7c, 0x40, 0x54, 0x38, 0x2c, 0x10, 0x04, 0xc8, 0xdc, + 0xe0, 0xf4, 0x98, 0x8c, 0xb0, 0xa4, 0x35, 0x21, 0x1d, 0x09, + 0x65, 0x71, 0x4d, 0x59, 0x95, 0x81, 0xbd, 0xa9, 0xc5, 0xd1, + 0xed, 0xf9, 0xbb, 0xaf, 0x93, 0x87, 0xeb, 0xff, 0xc3, 0xd7, + 0x1b, 0x0f, 0x33, 0x27, 0x4b, 0x5f, 0x63, 0x77, 0xe6, 0xf2, + 0xce, 0xda, 0xb6, 0xa2, 0x9e, 0x8a, 0x46, 0x52, 0x6e, 0x7a, + 0x16, 0x02, 0x3e, 0x2a, 0x01, 0x15, 0x29, 0x3d, 0x51, 0x45, + 0x79, 0x6d, 0xa1, 0xb5, 0x89, 0x9d, 0xf1, 0xe5, 0xd9, 0xcd, + 0x5c, 0x48, 0x74, 0x60, 0x0c, 0x18, 0x24, 0x30, 0xfc, 0xe8, + 0xd4, 0xc0, 0xac, 0xb8, 0x84, 0x90, 0x00, 0x15, 0x2a, 0x3f, + 0x54, 0x41, 0x7e, 0x6b, 0xa8, 0xbd, 0x82, 0x97, 0xfc, 0xe9, + 0xd6, 0xc3, 0x4d, 0x58, 0x67, 0x72, 0x19, 0x0c, 0x33, 0x26, + 0xe5, 0xf0, 0xcf, 0xda, 0xb1, 0xa4, 0x9b, 0x8e, 0x9a, 0x8f, + 0xb0, 0xa5, 0xce, 0xdb, 0xe4, 0xf1, 0x32, 0x27, 0x18, 0x0d, + 0x66, 0x73, 0x4c, 0x59, 0xd7, 0xc2, 0xfd, 0xe8, 0x83, 0x96, + 0xa9, 0xbc, 0x7f, 0x6a, 0x55, 0x40, 0x2b, 0x3e, 0x01, 0x14, + 0x29, 0x3c, 0x03, 0x16, 0x7d, 0x68, 0x57, 0x42, 0x81, 0x94, + 0xab, 0xbe, 0xd5, 0xc0, 0xff, 0xea, 0x64, 0x71, 0x4e, 0x5b, + 0x30, 0x25, 0x1a, 0x0f, 0xcc, 0xd9, 0xe6, 0xf3, 0x98, 0x8d, + 0xb2, 0xa7, 0xb3, 0xa6, 0x99, 0x8c, 0xe7, 0xf2, 0xcd, 0xd8, + 0x1b, 0x0e, 0x31, 0x24, 0x4f, 0x5a, 0x65, 0x70, 0xfe, 0xeb, + 0xd4, 0xc1, 0xaa, 0xbf, 0x80, 0x95, 0x56, 0x43, 0x7c, 0x69, + 0x02, 0x17, 0x28, 0x3d, 0x52, 0x47, 0x78, 0x6d, 0x06, 0x13, + 0x2c, 0x39, 0xfa, 0xef, 0xd0, 0xc5, 0xae, 0xbb, 0x84, 0x91, + 0x1f, 0x0a, 0x35, 0x20, 0x4b, 0x5e, 0x61, 0x74, 0xb7, 0xa2, + 0x9d, 0x88, 0xe3, 0xf6, 0xc9, 0xdc, 0xc8, 0xdd, 0xe2, 0xf7, + 0x9c, 0x89, 0xb6, 0xa3, 0x60, 0x75, 0x4a, 0x5f, 0x34, 0x21, + 0x1e, 0x0b, 0x85, 0x90, 0xaf, 0xba, 0xd1, 0xc4, 0xfb, 0xee, + 0x2d, 0x38, 0x07, 0x12, 0x79, 0x6c, 0x53, 0x46, 0x7b, 0x6e, + 0x51, 0x44, 0x2f, 0x3a, 0x05, 0x10, 0xd3, 0xc6, 0xf9, 0xec, + 0x87, 0x92, 0xad, 0xb8, 0x36, 0x23, 0x1c, 0x09, 0x62, 0x77, + 0x48, 0x5d, 0x9e, 0x8b, 0xb4, 0xa1, 0xca, 0xdf, 0xe0, 0xf5, + 0xe1, 0xf4, 0xcb, 0xde, 0xb5, 0xa0, 0x9f, 0x8a, 0x49, 0x5c, + 0x63, 0x76, 0x1d, 0x08, 0x37, 0x22, 0xac, 0xb9, 0x86, 0x93, + 0xf8, 0xed, 0xd2, 0xc7, 0x04, 0x11, 0x2e, 0x3b, 0x50, 0x45, + 0x7a, 0x6f, 0x00, 0x16, 0x2c, 0x3a, 0x58, 0x4e, 0x74, 0x62, + 0xb0, 0xa6, 0x9c, 0x8a, 0xe8, 0xfe, 0xc4, 0xd2, 0x7d, 0x6b, + 0x51, 0x47, 0x25, 0x33, 0x09, 0x1f, 0xcd, 0xdb, 0xe1, 0xf7, + 0x95, 0x83, 0xb9, 0xaf, 0xfa, 0xec, 0xd6, 0xc0, 0xa2, 0xb4, + 0x8e, 0x98, 0x4a, 0x5c, 0x66, 0x70, 0x12, 0x04, 0x3e, 0x28, + 0x87, 0x91, 0xab, 0xbd, 0xdf, 0xc9, 0xf3, 0xe5, 0x37, 0x21, + 0x1b, 0x0d, 0x6f, 0x79, 0x43, 0x55, 0xe9, 0xff, 0xc5, 0xd3, + 0xb1, 0xa7, 0x9d, 0x8b, 0x59, 0x4f, 0x75, 0x63, 0x01, 0x17, + 0x2d, 0x3b, 0x94, 0x82, 0xb8, 0xae, 0xcc, 0xda, 0xe0, 0xf6, + 0x24, 0x32, 0x08, 0x1e, 0x7c, 0x6a, 0x50, 0x46, 0x13, 0x05, + 0x3f, 0x29, 0x4b, 0x5d, 0x67, 0x71, 0xa3, 0xb5, 0x8f, 0x99, + 0xfb, 0xed, 0xd7, 0xc1, 0x6e, 0x78, 0x42, 0x54, 0x36, 0x20, + 0x1a, 0x0c, 0xde, 0xc8, 0xf2, 0xe4, 0x86, 0x90, 0xaa, 0xbc, + 0xcf, 0xd9, 0xe3, 0xf5, 0x97, 0x81, 0xbb, 0xad, 0x7f, 0x69, + 0x53, 0x45, 0x27, 0x31, 0x0b, 0x1d, 0xb2, 0xa4, 0x9e, 0x88, + 0xea, 0xfc, 0xc6, 0xd0, 0x02, 0x14, 0x2e, 0x38, 0x5a, 0x4c, + 0x76, 0x60, 0x35, 0x23, 0x19, 0x0f, 0x6d, 0x7b, 0x41, 0x57, + 0x85, 0x93, 0xa9, 0xbf, 0xdd, 0xcb, 0xf1, 0xe7, 0x48, 0x5e, + 0x64, 0x72, 0x10, 0x06, 0x3c, 0x2a, 0xf8, 0xee, 0xd4, 0xc2, + 0xa0, 0xb6, 0x8c, 0x9a, 0x26, 0x30, 0x0a, 0x1c, 0x7e, 0x68, + 0x52, 0x44, 0x96, 0x80, 0xba, 0xac, 0xce, 0xd8, 0xe2, 0xf4, + 0x5b, 0x4d, 0x77, 0x61, 0x03, 0x15, 0x2f, 0x39, 0xeb, 0xfd, + 0xc7, 0xd1, 0xb3, 0xa5, 0x9f, 0x89, 0xdc, 0xca, 0xf0, 0xe6, + 0x84, 0x92, 0xa8, 0xbe, 0x6c, 0x7a, 0x40, 0x56, 0x34, 0x22, + 0x18, 0x0e, 0xa1, 0xb7, 0x8d, 0x9b, 0xf9, 0xef, 0xd5, 0xc3, + 0x11, 0x07, 0x3d, 0x2b, 0x49, 0x5f, 0x65, 0x73, 0x00, 0x17, + 0x2e, 0x39, 0x5c, 0x4b, 0x72, 0x65, 0xb8, 0xaf, 0x96, 0x81, + 0xe4, 0xf3, 0xca, 0xdd, 0x6d, 0x7a, 0x43, 0x54, 0x31, 0x26, + 0x1f, 0x08, 0xd5, 0xc2, 0xfb, 0xec, 0x89, 0x9e, 0xa7, 0xb0, + 0xda, 0xcd, 0xf4, 0xe3, 0x86, 0x91, 0xa8, 0xbf, 0x62, 0x75, + 0x4c, 0x5b, 0x3e, 0x29, 0x10, 0x07, 0xb7, 0xa0, 0x99, 0x8e, + 0xeb, 0xfc, 0xc5, 0xd2, 0x0f, 0x18, 0x21, 0x36, 0x53, 0x44, + 0x7d, 0x6a, 0xa9, 0xbe, 0x87, 0x90, 0xf5, 0xe2, 0xdb, 0xcc, + 0x11, 0x06, 0x3f, 0x28, 0x4d, 0x5a, 0x63, 0x74, 0xc4, 0xd3, + 0xea, 0xfd, 0x98, 0x8f, 0xb6, 0xa1, 0x7c, 0x6b, 0x52, 0x45, + 0x20, 0x37, 0x0e, 0x19, 0x73, 0x64, 0x5d, 0x4a, 0x2f, 0x38, + 0x01, 0x16, 0xcb, 0xdc, 0xe5, 0xf2, 0x97, 0x80, 0xb9, 0xae, + 0x1e, 0x09, 0x30, 0x27, 0x42, 0x55, 0x6c, 0x7b, 0xa6, 0xb1, + 0x88, 0x9f, 0xfa, 0xed, 0xd4, 0xc3, 0x4f, 0x58, 0x61, 0x76, + 0x13, 0x04, 0x3d, 0x2a, 0xf7, 0xe0, 0xd9, 0xce, 0xab, 0xbc, + 0x85, 0x92, 0x22, 0x35, 0x0c, 0x1b, 0x7e, 0x69, 0x50, 0x47, + 0x9a, 0x8d, 0xb4, 0xa3, 0xc6, 0xd1, 0xe8, 0xff, 0x95, 0x82, + 0xbb, 0xac, 0xc9, 0xde, 0xe7, 0xf0, 0x2d, 0x3a, 0x03, 0x14, + 0x71, 0x66, 0x5f, 0x48, 0xf8, 0xef, 0xd6, 0xc1, 0xa4, 0xb3, + 0x8a, 0x9d, 0x40, 0x57, 0x6e, 0x79, 0x1c, 0x0b, 0x32, 0x25, + 0xe6, 0xf1, 0xc8, 0xdf, 0xba, 0xad, 0x94, 0x83, 0x5e, 0x49, + 0x70, 0x67, 0x02, 0x15, 0x2c, 0x3b, 0x8b, 0x9c, 0xa5, 0xb2, + 0xd7, 0xc0, 0xf9, 0xee, 0x33, 0x24, 0x1d, 0x0a, 0x6f, 0x78, + 0x41, 0x56, 0x3c, 0x2b, 0x12, 0x05, 0x60, 0x77, 0x4e, 0x59, + 0x84, 0x93, 0xaa, 0xbd, 0xd8, 0xcf, 0xf6, 0xe1, 0x51, 0x46, + 0x7f, 0x68, 0x0d, 0x1a, 0x23, 0x34, 0xe9, 0xfe, 0xc7, 0xd0, + 0xb5, 0xa2, 0x9b, 0x8c, 0x00, 0x18, 0x30, 0x28, 0x60, 0x78, + 0x50, 0x48, 0xc0, 0xd8, 0xf0, 0xe8, 0xa0, 0xb8, 0x90, 0x88, + 0x9d, 0x85, 0xad, 0xb5, 0xfd, 0xe5, 0xcd, 0xd5, 0x5d, 0x45, + 0x6d, 0x75, 0x3d, 0x25, 0x0d, 0x15, 0x27, 0x3f, 0x17, 0x0f, + 0x47, 0x5f, 0x77, 0x6f, 0xe7, 0xff, 0xd7, 0xcf, 0x87, 0x9f, + 0xb7, 0xaf, 0xba, 0xa2, 0x8a, 0x92, 0xda, 0xc2, 0xea, 0xf2, + 0x7a, 0x62, 0x4a, 0x52, 0x1a, 0x02, 0x2a, 0x32, 0x4e, 0x56, + 0x7e, 0x66, 0x2e, 0x36, 0x1e, 0x06, 0x8e, 0x96, 0xbe, 0xa6, + 0xee, 0xf6, 0xde, 0xc6, 0xd3, 0xcb, 0xe3, 0xfb, 0xb3, 0xab, + 0x83, 0x9b, 0x13, 0x0b, 0x23, 0x3b, 0x73, 0x6b, 0x43, 0x5b, + 0x69, 0x71, 0x59, 0x41, 0x09, 0x11, 0x39, 0x21, 0xa9, 0xb1, + 0x99, 0x81, 0xc9, 0xd1, 0xf9, 0xe1, 0xf4, 0xec, 0xc4, 0xdc, + 0x94, 0x8c, 0xa4, 0xbc, 0x34, 0x2c, 0x04, 0x1c, 0x54, 0x4c, + 0x64, 0x7c, 0x9c, 0x84, 0xac, 0xb4, 0xfc, 0xe4, 0xcc, 0xd4, + 0x5c, 0x44, 0x6c, 0x74, 0x3c, 0x24, 0x0c, 0x14, 0x01, 0x19, + 0x31, 0x29, 0x61, 0x79, 0x51, 0x49, 0xc1, 0xd9, 0xf1, 0xe9, + 0xa1, 0xb9, 0x91, 0x89, 0xbb, 0xa3, 0x8b, 0x93, 0xdb, 0xc3, + 0xeb, 0xf3, 0x7b, 0x63, 0x4b, 0x53, 0x1b, 0x03, 0x2b, 0x33, + 0x26, 0x3e, 0x16, 0x0e, 0x46, 0x5e, 0x76, 0x6e, 0xe6, 0xfe, + 0xd6, 0xce, 0x86, 0x9e, 0xb6, 0xae, 0xd2, 0xca, 0xe2, 0xfa, + 0xb2, 0xaa, 0x82, 0x9a, 0x12, 0x0a, 0x22, 0x3a, 0x72, 0x6a, + 0x42, 0x5a, 0x4f, 0x57, 0x7f, 0x67, 0x2f, 0x37, 0x1f, 0x07, + 0x8f, 0x97, 0xbf, 0xa7, 0xef, 0xf7, 0xdf, 0xc7, 0xf5, 0xed, + 0xc5, 0xdd, 0x95, 0x8d, 0xa5, 0xbd, 0x35, 0x2d, 0x05, 0x1d, + 0x55, 0x4d, 0x65, 0x7d, 0x68, 0x70, 0x58, 0x40, 0x08, 0x10, + 0x38, 0x20, 0xa8, 0xb0, 0x98, 0x80, 0xc8, 0xd0, 0xf8, 0xe0, + 0x00, 0x19, 0x32, 0x2b, 0x64, 0x7d, 0x56, 0x4f, 0xc8, 0xd1, + 0xfa, 0xe3, 0xac, 0xb5, 0x9e, 0x87, 0x8d, 0x94, 0xbf, 0xa6, + 0xe9, 0xf0, 0xdb, 0xc2, 0x45, 0x5c, 0x77, 0x6e, 0x21, 0x38, + 0x13, 0x0a, 0x07, 0x1e, 0x35, 0x2c, 0x63, 0x7a, 0x51, 0x48, + 0xcf, 0xd6, 0xfd, 0xe4, 0xab, 0xb2, 0x99, 0x80, 0x8a, 0x93, + 0xb8, 0xa1, 0xee, 0xf7, 0xdc, 0xc5, 0x42, 0x5b, 0x70, 0x69, + 0x26, 0x3f, 0x14, 0x0d, 0x0e, 0x17, 0x3c, 0x25, 0x6a, 0x73, + 0x58, 0x41, 0xc6, 0xdf, 0xf4, 0xed, 0xa2, 0xbb, 0x90, 0x89, + 0x83, 0x9a, 0xb1, 0xa8, 0xe7, 0xfe, 0xd5, 0xcc, 0x4b, 0x52, + 0x79, 0x60, 0x2f, 0x36, 0x1d, 0x04, 0x09, 0x10, 0x3b, 0x22, + 0x6d, 0x74, 0x5f, 0x46, 0xc1, 0xd8, 0xf3, 0xea, 0xa5, 0xbc, + 0x97, 0x8e, 0x84, 0x9d, 0xb6, 0xaf, 0xe0, 0xf9, 0xd2, 0xcb, + 0x4c, 0x55, 0x7e, 0x67, 0x28, 0x31, 0x1a, 0x03, 0x1c, 0x05, + 0x2e, 0x37, 0x78, 0x61, 0x4a, 0x53, 0xd4, 0xcd, 0xe6, 0xff, + 0xb0, 0xa9, 0x82, 0x9b, 0x91, 0x88, 0xa3, 0xba, 0xf5, 0xec, + 0xc7, 0xde, 0x59, 0x40, 0x6b, 0x72, 0x3d, 0x24, 0x0f, 0x16, + 0x1b, 0x02, 0x29, 0x30, 0x7f, 0x66, 0x4d, 0x54, 0xd3, 0xca, + 0xe1, 0xf8, 0xb7, 0xae, 0x85, 0x9c, 0x96, 0x8f, 0xa4, 0xbd, + 0xf2, 0xeb, 0xc0, 0xd9, 0x5e, 0x47, 0x6c, 0x75, 0x3a, 0x23, + 0x08, 0x11, 0x12, 0x0b, 0x20, 0x39, 0x76, 0x6f, 0x44, 0x5d, + 0xda, 0xc3, 0xe8, 0xf1, 0xbe, 0xa7, 0x8c, 0x95, 0x9f, 0x86, + 0xad, 0xb4, 0xfb, 0xe2, 0xc9, 0xd0, 0x57, 0x4e, 0x65, 0x7c, + 0x33, 0x2a, 0x01, 0x18, 0x15, 0x0c, 0x27, 0x3e, 0x71, 0x68, + 0x43, 0x5a, 0xdd, 0xc4, 0xef, 0xf6, 0xb9, 0xa0, 0x8b, 0x92, + 0x98, 0x81, 0xaa, 0xb3, 0xfc, 0xe5, 0xce, 0xd7, 0x50, 0x49, + 0x62, 0x7b, 0x34, 0x2d, 0x06, 0x1f, 0x00, 0x1a, 0x34, 0x2e, + 0x68, 0x72, 0x5c, 0x46, 0xd0, 0xca, 0xe4, 0xfe, 0xb8, 0xa2, + 0x8c, 0x96, 0xbd, 0xa7, 0x89, 0x93, 0xd5, 0xcf, 0xe1, 0xfb, + 0x6d, 0x77, 0x59, 0x43, 0x05, 0x1f, 0x31, 0x2b, 0x67, 0x7d, + 0x53, 0x49, 0x0f, 0x15, 0x3b, 0x21, 0xb7, 0xad, 0x83, 0x99, + 0xdf, 0xc5, 0xeb, 0xf1, 0xda, 0xc0, 0xee, 0xf4, 0xb2, 0xa8, + 0x86, 0x9c, 0x0a, 0x10, 0x3e, 0x24, 0x62, 0x78, 0x56, 0x4c, + 0xce, 0xd4, 0xfa, 0xe0, 0xa6, 0xbc, 0x92, 0x88, 0x1e, 0x04, + 0x2a, 0x30, 0x76, 0x6c, 0x42, 0x58, 0x73, 0x69, 0x47, 0x5d, + 0x1b, 0x01, 0x2f, 0x35, 0xa3, 0xb9, 0x97, 0x8d, 0xcb, 0xd1, + 0xff, 0xe5, 0xa9, 0xb3, 0x9d, 0x87, 0xc1, 0xdb, 0xf5, 0xef, + 0x79, 0x63, 0x4d, 0x57, 0x11, 0x0b, 0x25, 0x3f, 0x14, 0x0e, + 0x20, 0x3a, 0x7c, 0x66, 0x48, 0x52, 0xc4, 0xde, 0xf0, 0xea, + 0xac, 0xb6, 0x98, 0x82, 0x81, 0x9b, 0xb5, 0xaf, 0xe9, 0xf3, + 0xdd, 0xc7, 0x51, 0x4b, 0x65, 0x7f, 0x39, 0x23, 0x0d, 0x17, + 0x3c, 0x26, 0x08, 0x12, 0x54, 0x4e, 0x60, 0x7a, 0xec, 0xf6, + 0xd8, 0xc2, 0x84, 0x9e, 0xb0, 0xaa, 0xe6, 0xfc, 0xd2, 0xc8, + 0x8e, 0x94, 0xba, 0xa0, 0x36, 0x2c, 0x02, 0x18, 0x5e, 0x44, + 0x6a, 0x70, 0x5b, 0x41, 0x6f, 0x75, 0x33, 0x29, 0x07, 0x1d, + 0x8b, 0x91, 0xbf, 0xa5, 0xe3, 0xf9, 0xd7, 0xcd, 0x4f, 0x55, + 0x7b, 0x61, 0x27, 0x3d, 0x13, 0x09, 0x9f, 0x85, 0xab, 0xb1, + 0xf7, 0xed, 0xc3, 0xd9, 0xf2, 0xe8, 0xc6, 0xdc, 0x9a, 0x80, + 0xae, 0xb4, 0x22, 0x38, 0x16, 0x0c, 0x4a, 0x50, 0x7e, 0x64, + 0x28, 0x32, 0x1c, 0x06, 0x40, 0x5a, 0x74, 0x6e, 0xf8, 0xe2, + 0xcc, 0xd6, 0x90, 0x8a, 0xa4, 0xbe, 0x95, 0x8f, 0xa1, 0xbb, + 0xfd, 0xe7, 0xc9, 0xd3, 0x45, 0x5f, 0x71, 0x6b, 0x2d, 0x37, + 0x19, 0x03, 0x00, 0x1b, 0x36, 0x2d, 0x6c, 0x77, 0x5a, 0x41, + 0xd8, 0xc3, 0xee, 0xf5, 0xb4, 0xaf, 0x82, 0x99, 0xad, 0xb6, + 0x9b, 0x80, 0xc1, 0xda, 0xf7, 0xec, 0x75, 0x6e, 0x43, 0x58, + 0x19, 0x02, 0x2f, 0x34, 0x47, 0x5c, 0x71, 0x6a, 0x2b, 0x30, + 0x1d, 0x06, 0x9f, 0x84, 0xa9, 0xb2, 0xf3, 0xe8, 0xc5, 0xde, + 0xea, 0xf1, 0xdc, 0xc7, 0x86, 0x9d, 0xb0, 0xab, 0x32, 0x29, + 0x04, 0x1f, 0x5e, 0x45, 0x68, 0x73, 0x8e, 0x95, 0xb8, 0xa3, + 0xe2, 0xf9, 0xd4, 0xcf, 0x56, 0x4d, 0x60, 0x7b, 0x3a, 0x21, + 0x0c, 0x17, 0x23, 0x38, 0x15, 0x0e, 0x4f, 0x54, 0x79, 0x62, + 0xfb, 0xe0, 0xcd, 0xd6, 0x97, 0x8c, 0xa1, 0xba, 0xc9, 0xd2, + 0xff, 0xe4, 0xa5, 0xbe, 0x93, 0x88, 0x11, 0x0a, 0x27, 0x3c, + 0x7d, 0x66, 0x4b, 0x50, 0x64, 0x7f, 0x52, 0x49, 0x08, 0x13, + 0x3e, 0x25, 0xbc, 0xa7, 0x8a, 0x91, 0xd0, 0xcb, 0xe6, 0xfd, + 0x01, 0x1a, 0x37, 0x2c, 0x6d, 0x76, 0x5b, 0x40, 0xd9, 0xc2, + 0xef, 0xf4, 0xb5, 0xae, 0x83, 0x98, 0xac, 0xb7, 0x9a, 0x81, + 0xc0, 0xdb, 0xf6, 0xed, 0x74, 0x6f, 0x42, 0x59, 0x18, 0x03, + 0x2e, 0x35, 0x46, 0x5d, 0x70, 0x6b, 0x2a, 0x31, 0x1c, 0x07, + 0x9e, 0x85, 0xa8, 0xb3, 0xf2, 0xe9, 0xc4, 0xdf, 0xeb, 0xf0, + 0xdd, 0xc6, 0x87, 0x9c, 0xb1, 0xaa, 0x33, 0x28, 0x05, 0x1e, + 0x5f, 0x44, 0x69, 0x72, 0x8f, 0x94, 0xb9, 0xa2, 0xe3, 0xf8, + 0xd5, 0xce, 0x57, 0x4c, 0x61, 0x7a, 0x3b, 0x20, 0x0d, 0x16, + 0x22, 0x39, 0x14, 0x0f, 0x4e, 0x55, 0x78, 0x63, 0xfa, 0xe1, + 0xcc, 0xd7, 0x96, 0x8d, 0xa0, 0xbb, 0xc8, 0xd3, 0xfe, 0xe5, + 0xa4, 0xbf, 0x92, 0x89, 0x10, 0x0b, 0x26, 0x3d, 0x7c, 0x67, + 0x4a, 0x51, 0x65, 0x7e, 0x53, 0x48, 0x09, 0x12, 0x3f, 0x24, + 0xbd, 0xa6, 0x8b, 0x90, 0xd1, 0xca, 0xe7, 0xfc, 0x00, 0x1c, + 0x38, 0x24, 0x70, 0x6c, 0x48, 0x54, 0xe0, 0xfc, 0xd8, 0xc4, + 0x90, 0x8c, 0xa8, 0xb4, 0xdd, 0xc1, 0xe5, 0xf9, 0xad, 0xb1, + 0x95, 0x89, 0x3d, 0x21, 0x05, 0x19, 0x4d, 0x51, 0x75, 0x69, + 0xa7, 0xbb, 0x9f, 0x83, 0xd7, 0xcb, 0xef, 0xf3, 0x47, 0x5b, + 0x7f, 0x63, 0x37, 0x2b, 0x0f, 0x13, 0x7a, 0x66, 0x42, 0x5e, + 0x0a, 0x16, 0x32, 0x2e, 0x9a, 0x86, 0xa2, 0xbe, 0xea, 0xf6, + 0xd2, 0xce, 0x53, 0x4f, 0x6b, 0x77, 0x23, 0x3f, 0x1b, 0x07, + 0xb3, 0xaf, 0x8b, 0x97, 0xc3, 0xdf, 0xfb, 0xe7, 0x8e, 0x92, + 0xb6, 0xaa, 0xfe, 0xe2, 0xc6, 0xda, 0x6e, 0x72, 0x56, 0x4a, + 0x1e, 0x02, 0x26, 0x3a, 0xf4, 0xe8, 0xcc, 0xd0, 0x84, 0x98, + 0xbc, 0xa0, 0x14, 0x08, 0x2c, 0x30, 0x64, 0x78, 0x5c, 0x40, + 0x29, 0x35, 0x11, 0x0d, 0x59, 0x45, 0x61, 0x7d, 0xc9, 0xd5, + 0xf1, 0xed, 0xb9, 0xa5, 0x81, 0x9d, 0xa6, 0xba, 0x9e, 0x82, + 0xd6, 0xca, 0xee, 0xf2, 0x46, 0x5a, 0x7e, 0x62, 0x36, 0x2a, + 0x0e, 0x12, 0x7b, 0x67, 0x43, 0x5f, 0x0b, 0x17, 0x33, 0x2f, + 0x9b, 0x87, 0xa3, 0xbf, 0xeb, 0xf7, 0xd3, 0xcf, 0x01, 0x1d, + 0x39, 0x25, 0x71, 0x6d, 0x49, 0x55, 0xe1, 0xfd, 0xd9, 0xc5, + 0x91, 0x8d, 0xa9, 0xb5, 0xdc, 0xc0, 0xe4, 0xf8, 0xac, 0xb0, + 0x94, 0x88, 0x3c, 0x20, 0x04, 0x18, 0x4c, 0x50, 0x74, 0x68, + 0xf5, 0xe9, 0xcd, 0xd1, 0x85, 0x99, 0xbd, 0xa1, 0x15, 0x09, + 0x2d, 0x31, 0x65, 0x79, 0x5d, 0x41, 0x28, 0x34, 0x10, 0x0c, + 0x58, 0x44, 0x60, 0x7c, 0xc8, 0xd4, 0xf0, 0xec, 0xb8, 0xa4, + 0x80, 0x9c, 0x52, 0x4e, 0x6a, 0x76, 0x22, 0x3e, 0x1a, 0x06, + 0xb2, 0xae, 0x8a, 0x96, 0xc2, 0xde, 0xfa, 0xe6, 0x8f, 0x93, + 0xb7, 0xab, 0xff, 0xe3, 0xc7, 0xdb, 0x6f, 0x73, 0x57, 0x4b, + 0x1f, 0x03, 0x27, 0x3b, 0x00, 0x1d, 0x3a, 0x27, 0x74, 0x69, + 0x4e, 0x53, 0xe8, 0xf5, 0xd2, 0xcf, 0x9c, 0x81, 0xa6, 0xbb, + 0xcd, 0xd0, 0xf7, 0xea, 0xb9, 0xa4, 0x83, 0x9e, 0x25, 0x38, + 0x1f, 0x02, 0x51, 0x4c, 0x6b, 0x76, 0x87, 0x9a, 0xbd, 0xa0, + 0xf3, 0xee, 0xc9, 0xd4, 0x6f, 0x72, 0x55, 0x48, 0x1b, 0x06, + 0x21, 0x3c, 0x4a, 0x57, 0x70, 0x6d, 0x3e, 0x23, 0x04, 0x19, + 0xa2, 0xbf, 0x98, 0x85, 0xd6, 0xcb, 0xec, 0xf1, 0x13, 0x0e, + 0x29, 0x34, 0x67, 0x7a, 0x5d, 0x40, 0xfb, 0xe6, 0xc1, 0xdc, + 0x8f, 0x92, 0xb5, 0xa8, 0xde, 0xc3, 0xe4, 0xf9, 0xaa, 0xb7, + 0x90, 0x8d, 0x36, 0x2b, 0x0c, 0x11, 0x42, 0x5f, 0x78, 0x65, + 0x94, 0x89, 0xae, 0xb3, 0xe0, 0xfd, 0xda, 0xc7, 0x7c, 0x61, + 0x46, 0x5b, 0x08, 0x15, 0x32, 0x2f, 0x59, 0x44, 0x63, 0x7e, + 0x2d, 0x30, 0x17, 0x0a, 0xb1, 0xac, 0x8b, 0x96, 0xc5, 0xd8, + 0xff, 0xe2, 0x26, 0x3b, 0x1c, 0x01, 0x52, 0x4f, 0x68, 0x75, + 0xce, 0xd3, 0xf4, 0xe9, 0xba, 0xa7, 0x80, 0x9d, 0xeb, 0xf6, + 0xd1, 0xcc, 0x9f, 0x82, 0xa5, 0xb8, 0x03, 0x1e, 0x39, 0x24, + 0x77, 0x6a, 0x4d, 0x50, 0xa1, 0xbc, 0x9b, 0x86, 0xd5, 0xc8, + 0xef, 0xf2, 0x49, 0x54, 0x73, 0x6e, 0x3d, 0x20, 0x07, 0x1a, + 0x6c, 0x71, 0x56, 0x4b, 0x18, 0x05, 0x22, 0x3f, 0x84, 0x99, + 0xbe, 0xa3, 0xf0, 0xed, 0xca, 0xd7, 0x35, 0x28, 0x0f, 0x12, + 0x41, 0x5c, 0x7b, 0x66, 0xdd, 0xc0, 0xe7, 0xfa, 0xa9, 0xb4, + 0x93, 0x8e, 0xf8, 0xe5, 0xc2, 0xdf, 0x8c, 0x91, 0xb6, 0xab, + 0x10, 0x0d, 0x2a, 0x37, 0x64, 0x79, 0x5e, 0x43, 0xb2, 0xaf, + 0x88, 0x95, 0xc6, 0xdb, 0xfc, 0xe1, 0x5a, 0x47, 0x60, 0x7d, + 0x2e, 0x33, 0x14, 0x09, 0x7f, 0x62, 0x45, 0x58, 0x0b, 0x16, + 0x31, 0x2c, 0x97, 0x8a, 0xad, 0xb0, 0xe3, 0xfe, 0xd9, 0xc4, + 0x00, 0x1e, 0x3c, 0x22, 0x78, 0x66, 0x44, 0x5a, 0xf0, 0xee, + 0xcc, 0xd2, 0x88, 0x96, 0xb4, 0xaa, 0xfd, 0xe3, 0xc1, 0xdf, + 0x85, 0x9b, 0xb9, 0xa7, 0x0d, 0x13, 0x31, 0x2f, 0x75, 0x6b, + 0x49, 0x57, 0xe7, 0xf9, 0xdb, 0xc5, 0x9f, 0x81, 0xa3, 0xbd, + 0x17, 0x09, 0x2b, 0x35, 0x6f, 0x71, 0x53, 0x4d, 0x1a, 0x04, + 0x26, 0x38, 0x62, 0x7c, 0x5e, 0x40, 0xea, 0xf4, 0xd6, 0xc8, + 0x92, 0x8c, 0xae, 0xb0, 0xd3, 0xcd, 0xef, 0xf1, 0xab, 0xb5, + 0x97, 0x89, 0x23, 0x3d, 0x1f, 0x01, 0x5b, 0x45, 0x67, 0x79, + 0x2e, 0x30, 0x12, 0x0c, 0x56, 0x48, 0x6a, 0x74, 0xde, 0xc0, + 0xe2, 0xfc, 0xa6, 0xb8, 0x9a, 0x84, 0x34, 0x2a, 0x08, 0x16, + 0x4c, 0x52, 0x70, 0x6e, 0xc4, 0xda, 0xf8, 0xe6, 0xbc, 0xa2, + 0x80, 0x9e, 0xc9, 0xd7, 0xf5, 0xeb, 0xb1, 0xaf, 0x8d, 0x93, + 0x39, 0x27, 0x05, 0x1b, 0x41, 0x5f, 0x7d, 0x63, 0xbb, 0xa5, + 0x87, 0x99, 0xc3, 0xdd, 0xff, 0xe1, 0x4b, 0x55, 0x77, 0x69, + 0x33, 0x2d, 0x0f, 0x11, 0x46, 0x58, 0x7a, 0x64, 0x3e, 0x20, + 0x02, 0x1c, 0xb6, 0xa8, 0x8a, 0x94, 0xce, 0xd0, 0xf2, 0xec, + 0x5c, 0x42, 0x60, 0x7e, 0x24, 0x3a, 0x18, 0x06, 0xac, 0xb2, + 0x90, 0x8e, 0xd4, 0xca, 0xe8, 0xf6, 0xa1, 0xbf, 0x9d, 0x83, + 0xd9, 0xc7, 0xe5, 0xfb, 0x51, 0x4f, 0x6d, 0x73, 0x29, 0x37, + 0x15, 0x0b, 0x68, 0x76, 0x54, 0x4a, 0x10, 0x0e, 0x2c, 0x32, + 0x98, 0x86, 0xa4, 0xba, 0xe0, 0xfe, 0xdc, 0xc2, 0x95, 0x8b, + 0xa9, 0xb7, 0xed, 0xf3, 0xd1, 0xcf, 0x65, 0x7b, 0x59, 0x47, + 0x1d, 0x03, 0x21, 0x3f, 0x8f, 0x91, 0xb3, 0xad, 0xf7, 0xe9, + 0xcb, 0xd5, 0x7f, 0x61, 0x43, 0x5d, 0x07, 0x19, 0x3b, 0x25, + 0x72, 0x6c, 0x4e, 0x50, 0x0a, 0x14, 0x36, 0x28, 0x82, 0x9c, + 0xbe, 0xa0, 0xfa, 0xe4, 0xc6, 0xd8, 0x00, 0x1f, 0x3e, 0x21, + 0x7c, 0x63, 0x42, 0x5d, 0xf8, 0xe7, 0xc6, 0xd9, 0x84, 0x9b, + 0xba, 0xa5, 0xed, 0xf2, 0xd3, 0xcc, 0x91, 0x8e, 0xaf, 0xb0, + 0x15, 0x0a, 0x2b, 0x34, 0x69, 0x76, 0x57, 0x48, 0xc7, 0xd8, + 0xf9, 0xe6, 0xbb, 0xa4, 0x85, 0x9a, 0x3f, 0x20, 0x01, 0x1e, + 0x43, 0x5c, 0x7d, 0x62, 0x2a, 0x35, 0x14, 0x0b, 0x56, 0x49, + 0x68, 0x77, 0xd2, 0xcd, 0xec, 0xf3, 0xae, 0xb1, 0x90, 0x8f, + 0x93, 0x8c, 0xad, 0xb2, 0xef, 0xf0, 0xd1, 0xce, 0x6b, 0x74, + 0x55, 0x4a, 0x17, 0x08, 0x29, 0x36, 0x7e, 0x61, 0x40, 0x5f, + 0x02, 0x1d, 0x3c, 0x23, 0x86, 0x99, 0xb8, 0xa7, 0xfa, 0xe5, + 0xc4, 0xdb, 0x54, 0x4b, 0x6a, 0x75, 0x28, 0x37, 0x16, 0x09, + 0xac, 0xb3, 0x92, 0x8d, 0xd0, 0xcf, 0xee, 0xf1, 0xb9, 0xa6, + 0x87, 0x98, 0xc5, 0xda, 0xfb, 0xe4, 0x41, 0x5e, 0x7f, 0x60, + 0x3d, 0x22, 0x03, 0x1c, 0x3b, 0x24, 0x05, 0x1a, 0x47, 0x58, + 0x79, 0x66, 0xc3, 0xdc, 0xfd, 0xe2, 0xbf, 0xa0, 0x81, 0x9e, + 0xd6, 0xc9, 0xe8, 0xf7, 0xaa, 0xb5, 0x94, 0x8b, 0x2e, 0x31, + 0x10, 0x0f, 0x52, 0x4d, 0x6c, 0x73, 0xfc, 0xe3, 0xc2, 0xdd, + 0x80, 0x9f, 0xbe, 0xa1, 0x04, 0x1b, 0x3a, 0x25, 0x78, 0x67, + 0x46, 0x59, 0x11, 0x0e, 0x2f, 0x30, 0x6d, 0x72, 0x53, 0x4c, + 0xe9, 0xf6, 0xd7, 0xc8, 0x95, 0x8a, 0xab, 0xb4, 0xa8, 0xb7, + 0x96, 0x89, 0xd4, 0xcb, 0xea, 0xf5, 0x50, 0x4f, 0x6e, 0x71, + 0x2c, 0x33, 0x12, 0x0d, 0x45, 0x5a, 0x7b, 0x64, 0x39, 0x26, + 0x07, 0x18, 0xbd, 0xa2, 0x83, 0x9c, 0xc1, 0xde, 0xff, 0xe0, + 0x6f, 0x70, 0x51, 0x4e, 0x13, 0x0c, 0x2d, 0x32, 0x97, 0x88, + 0xa9, 0xb6, 0xeb, 0xf4, 0xd5, 0xca, 0x82, 0x9d, 0xbc, 0xa3, + 0xfe, 0xe1, 0xc0, 0xdf, 0x7a, 0x65, 0x44, 0x5b, 0x06, 0x19, + 0x38, 0x27, 0x00, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0, + 0x1d, 0x3d, 0x5d, 0x7d, 0x9d, 0xbd, 0xdd, 0xfd, 0x3a, 0x1a, + 0x7a, 0x5a, 0xba, 0x9a, 0xfa, 0xda, 0x27, 0x07, 0x67, 0x47, + 0xa7, 0x87, 0xe7, 0xc7, 0x74, 0x54, 0x34, 0x14, 0xf4, 0xd4, + 0xb4, 0x94, 0x69, 0x49, 0x29, 0x09, 0xe9, 0xc9, 0xa9, 0x89, + 0x4e, 0x6e, 0x0e, 0x2e, 0xce, 0xee, 0x8e, 0xae, 0x53, 0x73, + 0x13, 0x33, 0xd3, 0xf3, 0x93, 0xb3, 0xe8, 0xc8, 0xa8, 0x88, + 0x68, 0x48, 0x28, 0x08, 0xf5, 0xd5, 0xb5, 0x95, 0x75, 0x55, + 0x35, 0x15, 0xd2, 0xf2, 0x92, 0xb2, 0x52, 0x72, 0x12, 0x32, + 0xcf, 0xef, 0x8f, 0xaf, 0x4f, 0x6f, 0x0f, 0x2f, 0x9c, 0xbc, + 0xdc, 0xfc, 0x1c, 0x3c, 0x5c, 0x7c, 0x81, 0xa1, 0xc1, 0xe1, + 0x01, 0x21, 0x41, 0x61, 0xa6, 0x86, 0xe6, 0xc6, 0x26, 0x06, + 0x66, 0x46, 0xbb, 0x9b, 0xfb, 0xdb, 0x3b, 0x1b, 0x7b, 0x5b, + 0xcd, 0xed, 0x8d, 0xad, 0x4d, 0x6d, 0x0d, 0x2d, 0xd0, 0xf0, + 0x90, 0xb0, 0x50, 0x70, 0x10, 0x30, 0xf7, 0xd7, 0xb7, 0x97, + 0x77, 0x57, 0x37, 0x17, 0xea, 0xca, 0xaa, 0x8a, 0x6a, 0x4a, + 0x2a, 0x0a, 0xb9, 0x99, 0xf9, 0xd9, 0x39, 0x19, 0x79, 0x59, + 0xa4, 0x84, 0xe4, 0xc4, 0x24, 0x04, 0x64, 0x44, 0x83, 0xa3, + 0xc3, 0xe3, 0x03, 0x23, 0x43, 0x63, 0x9e, 0xbe, 0xde, 0xfe, + 0x1e, 0x3e, 0x5e, 0x7e, 0x25, 0x05, 0x65, 0x45, 0xa5, 0x85, + 0xe5, 0xc5, 0x38, 0x18, 0x78, 0x58, 0xb8, 0x98, 0xf8, 0xd8, + 0x1f, 0x3f, 0x5f, 0x7f, 0x9f, 0xbf, 0xdf, 0xff, 0x02, 0x22, + 0x42, 0x62, 0x82, 0xa2, 0xc2, 0xe2, 0x51, 0x71, 0x11, 0x31, + 0xd1, 0xf1, 0x91, 0xb1, 0x4c, 0x6c, 0x0c, 0x2c, 0xcc, 0xec, + 0x8c, 0xac, 0x6b, 0x4b, 0x2b, 0x0b, 0xeb, 0xcb, 0xab, 0x8b, + 0x76, 0x56, 0x36, 0x16, 0xf6, 0xd6, 0xb6, 0x96, 0x00, 0x21, + 0x42, 0x63, 0x84, 0xa5, 0xc6, 0xe7, 0x15, 0x34, 0x57, 0x76, + 0x91, 0xb0, 0xd3, 0xf2, 0x2a, 0x0b, 0x68, 0x49, 0xae, 0x8f, + 0xec, 0xcd, 0x3f, 0x1e, 0x7d, 0x5c, 0xbb, 0x9a, 0xf9, 0xd8, + 0x54, 0x75, 0x16, 0x37, 0xd0, 0xf1, 0x92, 0xb3, 0x41, 0x60, + 0x03, 0x22, 0xc5, 0xe4, 0x87, 0xa6, 0x7e, 0x5f, 0x3c, 0x1d, + 0xfa, 0xdb, 0xb8, 0x99, 0x6b, 0x4a, 0x29, 0x08, 0xef, 0xce, + 0xad, 0x8c, 0xa8, 0x89, 0xea, 0xcb, 0x2c, 0x0d, 0x6e, 0x4f, + 0xbd, 0x9c, 0xff, 0xde, 0x39, 0x18, 0x7b, 0x5a, 0x82, 0xa3, + 0xc0, 0xe1, 0x06, 0x27, 0x44, 0x65, 0x97, 0xb6, 0xd5, 0xf4, + 0x13, 0x32, 0x51, 0x70, 0xfc, 0xdd, 0xbe, 0x9f, 0x78, 0x59, + 0x3a, 0x1b, 0xe9, 0xc8, 0xab, 0x8a, 0x6d, 0x4c, 0x2f, 0x0e, + 0xd6, 0xf7, 0x94, 0xb5, 0x52, 0x73, 0x10, 0x31, 0xc3, 0xe2, + 0x81, 0xa0, 0x47, 0x66, 0x05, 0x24, 0x4d, 0x6c, 0x0f, 0x2e, + 0xc9, 0xe8, 0x8b, 0xaa, 0x58, 0x79, 0x1a, 0x3b, 0xdc, 0xfd, + 0x9e, 0xbf, 0x67, 0x46, 0x25, 0x04, 0xe3, 0xc2, 0xa1, 0x80, + 0x72, 0x53, 0x30, 0x11, 0xf6, 0xd7, 0xb4, 0x95, 0x19, 0x38, + 0x5b, 0x7a, 0x9d, 0xbc, 0xdf, 0xfe, 0x0c, 0x2d, 0x4e, 0x6f, + 0x88, 0xa9, 0xca, 0xeb, 0x33, 0x12, 0x71, 0x50, 0xb7, 0x96, + 0xf5, 0xd4, 0x26, 0x07, 0x64, 0x45, 0xa2, 0x83, 0xe0, 0xc1, + 0xe5, 0xc4, 0xa7, 0x86, 0x61, 0x40, 0x23, 0x02, 0xf0, 0xd1, + 0xb2, 0x93, 0x74, 0x55, 0x36, 0x17, 0xcf, 0xee, 0x8d, 0xac, + 0x4b, 0x6a, 0x09, 0x28, 0xda, 0xfb, 0x98, 0xb9, 0x5e, 0x7f, + 0x1c, 0x3d, 0xb1, 0x90, 0xf3, 0xd2, 0x35, 0x14, 0x77, 0x56, + 0xa4, 0x85, 0xe6, 0xc7, 0x20, 0x01, 0x62, 0x43, 0x9b, 0xba, + 0xd9, 0xf8, 0x1f, 0x3e, 0x5d, 0x7c, 0x8e, 0xaf, 0xcc, 0xed, + 0x0a, 0x2b, 0x48, 0x69, 0x00, 0x22, 0x44, 0x66, 0x88, 0xaa, + 0xcc, 0xee, 0x0d, 0x2f, 0x49, 0x6b, 0x85, 0xa7, 0xc1, 0xe3, + 0x1a, 0x38, 0x5e, 0x7c, 0x92, 0xb0, 0xd6, 0xf4, 0x17, 0x35, + 0x53, 0x71, 0x9f, 0xbd, 0xdb, 0xf9, 0x34, 0x16, 0x70, 0x52, + 0xbc, 0x9e, 0xf8, 0xda, 0x39, 0x1b, 0x7d, 0x5f, 0xb1, 0x93, + 0xf5, 0xd7, 0x2e, 0x0c, 0x6a, 0x48, 0xa6, 0x84, 0xe2, 0xc0, + 0x23, 0x01, 0x67, 0x45, 0xab, 0x89, 0xef, 0xcd, 0x68, 0x4a, + 0x2c, 0x0e, 0xe0, 0xc2, 0xa4, 0x86, 0x65, 0x47, 0x21, 0x03, + 0xed, 0xcf, 0xa9, 0x8b, 0x72, 0x50, 0x36, 0x14, 0xfa, 0xd8, + 0xbe, 0x9c, 0x7f, 0x5d, 0x3b, 0x19, 0xf7, 0xd5, 0xb3, 0x91, + 0x5c, 0x7e, 0x18, 0x3a, 0xd4, 0xf6, 0x90, 0xb2, 0x51, 0x73, + 0x15, 0x37, 0xd9, 0xfb, 0x9d, 0xbf, 0x46, 0x64, 0x02, 0x20, + 0xce, 0xec, 0x8a, 0xa8, 0x4b, 0x69, 0x0f, 0x2d, 0xc3, 0xe1, + 0x87, 0xa5, 0xd0, 0xf2, 0x94, 0xb6, 0x58, 0x7a, 0x1c, 0x3e, + 0xdd, 0xff, 0x99, 0xbb, 0x55, 0x77, 0x11, 0x33, 0xca, 0xe8, + 0x8e, 0xac, 0x42, 0x60, 0x06, 0x24, 0xc7, 0xe5, 0x83, 0xa1, + 0x4f, 0x6d, 0x0b, 0x29, 0xe4, 0xc6, 0xa0, 0x82, 0x6c, 0x4e, + 0x28, 0x0a, 0xe9, 0xcb, 0xad, 0x8f, 0x61, 0x43, 0x25, 0x07, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0xf3, 0xd1, + 0xb7, 0x95, 0x7b, 0x59, 0x3f, 0x1d, 0xb8, 0x9a, 0xfc, 0xde, + 0x30, 0x12, 0x74, 0x56, 0xb5, 0x97, 0xf1, 0xd3, 0x3d, 0x1f, + 0x79, 0x5b, 0xa2, 0x80, 0xe6, 0xc4, 0x2a, 0x08, 0x6e, 0x4c, + 0xaf, 0x8d, 0xeb, 0xc9, 0x27, 0x05, 0x63, 0x41, 0x8c, 0xae, + 0xc8, 0xea, 0x04, 0x26, 0x40, 0x62, 0x81, 0xa3, 0xc5, 0xe7, + 0x09, 0x2b, 0x4d, 0x6f, 0x96, 0xb4, 0xd2, 0xf0, 0x1e, 0x3c, + 0x5a, 0x78, 0x9b, 0xb9, 0xdf, 0xfd, 0x13, 0x31, 0x57, 0x75, + 0x00, 0x23, 0x46, 0x65, 0x8c, 0xaf, 0xca, 0xe9, 0x05, 0x26, + 0x43, 0x60, 0x89, 0xaa, 0xcf, 0xec, 0x0a, 0x29, 0x4c, 0x6f, + 0x86, 0xa5, 0xc0, 0xe3, 0x0f, 0x2c, 0x49, 0x6a, 0x83, 0xa0, + 0xc5, 0xe6, 0x14, 0x37, 0x52, 0x71, 0x98, 0xbb, 0xde, 0xfd, + 0x11, 0x32, 0x57, 0x74, 0x9d, 0xbe, 0xdb, 0xf8, 0x1e, 0x3d, + 0x58, 0x7b, 0x92, 0xb1, 0xd4, 0xf7, 0x1b, 0x38, 0x5d, 0x7e, + 0x97, 0xb4, 0xd1, 0xf2, 0x28, 0x0b, 0x6e, 0x4d, 0xa4, 0x87, + 0xe2, 0xc1, 0x2d, 0x0e, 0x6b, 0x48, 0xa1, 0x82, 0xe7, 0xc4, + 0x22, 0x01, 0x64, 0x47, 0xae, 0x8d, 0xe8, 0xcb, 0x27, 0x04, + 0x61, 0x42, 0xab, 0x88, 0xed, 0xce, 0x3c, 0x1f, 0x7a, 0x59, + 0xb0, 0x93, 0xf6, 0xd5, 0x39, 0x1a, 0x7f, 0x5c, 0xb5, 0x96, + 0xf3, 0xd0, 0x36, 0x15, 0x70, 0x53, 0xba, 0x99, 0xfc, 0xdf, + 0x33, 0x10, 0x75, 0x56, 0xbf, 0x9c, 0xf9, 0xda, 0x50, 0x73, + 0x16, 0x35, 0xdc, 0xff, 0x9a, 0xb9, 0x55, 0x76, 0x13, 0x30, + 0xd9, 0xfa, 0x9f, 0xbc, 0x5a, 0x79, 0x1c, 0x3f, 0xd6, 0xf5, + 0x90, 0xb3, 0x5f, 0x7c, 0x19, 0x3a, 0xd3, 0xf0, 0x95, 0xb6, + 0x44, 0x67, 0x02, 0x21, 0xc8, 0xeb, 0x8e, 0xad, 0x41, 0x62, + 0x07, 0x24, 0xcd, 0xee, 0x8b, 0xa8, 0x4e, 0x6d, 0x08, 0x2b, + 0xc2, 0xe1, 0x84, 0xa7, 0x4b, 0x68, 0x0d, 0x2e, 0xc7, 0xe4, + 0x81, 0xa2, 0x78, 0x5b, 0x3e, 0x1d, 0xf4, 0xd7, 0xb2, 0x91, + 0x7d, 0x5e, 0x3b, 0x18, 0xf1, 0xd2, 0xb7, 0x94, 0x72, 0x51, + 0x34, 0x17, 0xfe, 0xdd, 0xb8, 0x9b, 0x77, 0x54, 0x31, 0x12, + 0xfb, 0xd8, 0xbd, 0x9e, 0x6c, 0x4f, 0x2a, 0x09, 0xe0, 0xc3, + 0xa6, 0x85, 0x69, 0x4a, 0x2f, 0x0c, 0xe5, 0xc6, 0xa3, 0x80, + 0x66, 0x45, 0x20, 0x03, 0xea, 0xc9, 0xac, 0x8f, 0x63, 0x40, + 0x25, 0x06, 0xef, 0xcc, 0xa9, 0x8a, 0x00, 0x24, 0x48, 0x6c, + 0x90, 0xb4, 0xd8, 0xfc, 0x3d, 0x19, 0x75, 0x51, 0xad, 0x89, + 0xe5, 0xc1, 0x7a, 0x5e, 0x32, 0x16, 0xea, 0xce, 0xa2, 0x86, + 0x47, 0x63, 0x0f, 0x2b, 0xd7, 0xf3, 0x9f, 0xbb, 0xf4, 0xd0, + 0xbc, 0x98, 0x64, 0x40, 0x2c, 0x08, 0xc9, 0xed, 0x81, 0xa5, + 0x59, 0x7d, 0x11, 0x35, 0x8e, 0xaa, 0xc6, 0xe2, 0x1e, 0x3a, + 0x56, 0x72, 0xb3, 0x97, 0xfb, 0xdf, 0x23, 0x07, 0x6b, 0x4f, + 0xf5, 0xd1, 0xbd, 0x99, 0x65, 0x41, 0x2d, 0x09, 0xc8, 0xec, + 0x80, 0xa4, 0x58, 0x7c, 0x10, 0x34, 0x8f, 0xab, 0xc7, 0xe3, + 0x1f, 0x3b, 0x57, 0x73, 0xb2, 0x96, 0xfa, 0xde, 0x22, 0x06, + 0x6a, 0x4e, 0x01, 0x25, 0x49, 0x6d, 0x91, 0xb5, 0xd9, 0xfd, + 0x3c, 0x18, 0x74, 0x50, 0xac, 0x88, 0xe4, 0xc0, 0x7b, 0x5f, + 0x33, 0x17, 0xeb, 0xcf, 0xa3, 0x87, 0x46, 0x62, 0x0e, 0x2a, + 0xd6, 0xf2, 0x9e, 0xba, 0xf7, 0xd3, 0xbf, 0x9b, 0x67, 0x43, + 0x2f, 0x0b, 0xca, 0xee, 0x82, 0xa6, 0x5a, 0x7e, 0x12, 0x36, + 0x8d, 0xa9, 0xc5, 0xe1, 0x1d, 0x39, 0x55, 0x71, 0xb0, 0x94, + 0xf8, 0xdc, 0x20, 0x04, 0x68, 0x4c, 0x03, 0x27, 0x4b, 0x6f, + 0x93, 0xb7, 0xdb, 0xff, 0x3e, 0x1a, 0x76, 0x52, 0xae, 0x8a, + 0xe6, 0xc2, 0x79, 0x5d, 0x31, 0x15, 0xe9, 0xcd, 0xa1, 0x85, + 0x44, 0x60, 0x0c, 0x28, 0xd4, 0xf0, 0x9c, 0xb8, 0x02, 0x26, + 0x4a, 0x6e, 0x92, 0xb6, 0xda, 0xfe, 0x3f, 0x1b, 0x77, 0x53, + 0xaf, 0x8b, 0xe7, 0xc3, 0x78, 0x5c, 0x30, 0x14, 0xe8, 0xcc, + 0xa0, 0x84, 0x45, 0x61, 0x0d, 0x29, 0xd5, 0xf1, 0x9d, 0xb9, + 0xf6, 0xd2, 0xbe, 0x9a, 0x66, 0x42, 0x2e, 0x0a, 0xcb, 0xef, + 0x83, 0xa7, 0x5b, 0x7f, 0x13, 0x37, 0x8c, 0xa8, 0xc4, 0xe0, + 0x1c, 0x38, 0x54, 0x70, 0xb1, 0x95, 0xf9, 0xdd, 0x21, 0x05, + 0x69, 0x4d, 0x00, 0x25, 0x4a, 0x6f, 0x94, 0xb1, 0xde, 0xfb, + 0x35, 0x10, 0x7f, 0x5a, 0xa1, 0x84, 0xeb, 0xce, 0x6a, 0x4f, + 0x20, 0x05, 0xfe, 0xdb, 0xb4, 0x91, 0x5f, 0x7a, 0x15, 0x30, + 0xcb, 0xee, 0x81, 0xa4, 0xd4, 0xf1, 0x9e, 0xbb, 0x40, 0x65, + 0x0a, 0x2f, 0xe1, 0xc4, 0xab, 0x8e, 0x75, 0x50, 0x3f, 0x1a, + 0xbe, 0x9b, 0xf4, 0xd1, 0x2a, 0x0f, 0x60, 0x45, 0x8b, 0xae, + 0xc1, 0xe4, 0x1f, 0x3a, 0x55, 0x70, 0xb5, 0x90, 0xff, 0xda, + 0x21, 0x04, 0x6b, 0x4e, 0x80, 0xa5, 0xca, 0xef, 0x14, 0x31, + 0x5e, 0x7b, 0xdf, 0xfa, 0x95, 0xb0, 0x4b, 0x6e, 0x01, 0x24, + 0xea, 0xcf, 0xa0, 0x85, 0x7e, 0x5b, 0x34, 0x11, 0x61, 0x44, + 0x2b, 0x0e, 0xf5, 0xd0, 0xbf, 0x9a, 0x54, 0x71, 0x1e, 0x3b, + 0xc0, 0xe5, 0x8a, 0xaf, 0x0b, 0x2e, 0x41, 0x64, 0x9f, 0xba, + 0xd5, 0xf0, 0x3e, 0x1b, 0x74, 0x51, 0xaa, 0x8f, 0xe0, 0xc5, + 0x77, 0x52, 0x3d, 0x18, 0xe3, 0xc6, 0xa9, 0x8c, 0x42, 0x67, + 0x08, 0x2d, 0xd6, 0xf3, 0x9c, 0xb9, 0x1d, 0x38, 0x57, 0x72, + 0x89, 0xac, 0xc3, 0xe6, 0x28, 0x0d, 0x62, 0x47, 0xbc, 0x99, + 0xf6, 0xd3, 0xa3, 0x86, 0xe9, 0xcc, 0x37, 0x12, 0x7d, 0x58, + 0x96, 0xb3, 0xdc, 0xf9, 0x02, 0x27, 0x48, 0x6d, 0xc9, 0xec, + 0x83, 0xa6, 0x5d, 0x78, 0x17, 0x32, 0xfc, 0xd9, 0xb6, 0x93, + 0x68, 0x4d, 0x22, 0x07, 0xc2, 0xe7, 0x88, 0xad, 0x56, 0x73, + 0x1c, 0x39, 0xf7, 0xd2, 0xbd, 0x98, 0x63, 0x46, 0x29, 0x0c, + 0xa8, 0x8d, 0xe2, 0xc7, 0x3c, 0x19, 0x76, 0x53, 0x9d, 0xb8, + 0xd7, 0xf2, 0x09, 0x2c, 0x43, 0x66, 0x16, 0x33, 0x5c, 0x79, + 0x82, 0xa7, 0xc8, 0xed, 0x23, 0x06, 0x69, 0x4c, 0xb7, 0x92, + 0xfd, 0xd8, 0x7c, 0x59, 0x36, 0x13, 0xe8, 0xcd, 0xa2, 0x87, + 0x49, 0x6c, 0x03, 0x26, 0xdd, 0xf8, 0x97, 0xb2, 0x00, 0x26, + 0x4c, 0x6a, 0x98, 0xbe, 0xd4, 0xf2, 0x2d, 0x0b, 0x61, 0x47, + 0xb5, 0x93, 0xf9, 0xdf, 0x5a, 0x7c, 0x16, 0x30, 0xc2, 0xe4, + 0x8e, 0xa8, 0x77, 0x51, 0x3b, 0x1d, 0xef, 0xc9, 0xa3, 0x85, + 0xb4, 0x92, 0xf8, 0xde, 0x2c, 0x0a, 0x60, 0x46, 0x99, 0xbf, + 0xd5, 0xf3, 0x01, 0x27, 0x4d, 0x6b, 0xee, 0xc8, 0xa2, 0x84, + 0x76, 0x50, 0x3a, 0x1c, 0xc3, 0xe5, 0x8f, 0xa9, 0x5b, 0x7d, + 0x17, 0x31, 0x75, 0x53, 0x39, 0x1f, 0xed, 0xcb, 0xa1, 0x87, + 0x58, 0x7e, 0x14, 0x32, 0xc0, 0xe6, 0x8c, 0xaa, 0x2f, 0x09, + 0x63, 0x45, 0xb7, 0x91, 0xfb, 0xdd, 0x02, 0x24, 0x4e, 0x68, + 0x9a, 0xbc, 0xd6, 0xf0, 0xc1, 0xe7, 0x8d, 0xab, 0x59, 0x7f, + 0x15, 0x33, 0xec, 0xca, 0xa0, 0x86, 0x74, 0x52, 0x38, 0x1e, + 0x9b, 0xbd, 0xd7, 0xf1, 0x03, 0x25, 0x4f, 0x69, 0xb6, 0x90, + 0xfa, 0xdc, 0x2e, 0x08, 0x62, 0x44, 0xea, 0xcc, 0xa6, 0x80, + 0x72, 0x54, 0x3e, 0x18, 0xc7, 0xe1, 0x8b, 0xad, 0x5f, 0x79, + 0x13, 0x35, 0xb0, 0x96, 0xfc, 0xda, 0x28, 0x0e, 0x64, 0x42, + 0x9d, 0xbb, 0xd1, 0xf7, 0x05, 0x23, 0x49, 0x6f, 0x5e, 0x78, + 0x12, 0x34, 0xc6, 0xe0, 0x8a, 0xac, 0x73, 0x55, 0x3f, 0x19, + 0xeb, 0xcd, 0xa7, 0x81, 0x04, 0x22, 0x48, 0x6e, 0x9c, 0xba, + 0xd0, 0xf6, 0x29, 0x0f, 0x65, 0x43, 0xb1, 0x97, 0xfd, 0xdb, + 0x9f, 0xb9, 0xd3, 0xf5, 0x07, 0x21, 0x4b, 0x6d, 0xb2, 0x94, + 0xfe, 0xd8, 0x2a, 0x0c, 0x66, 0x40, 0xc5, 0xe3, 0x89, 0xaf, + 0x5d, 0x7b, 0x11, 0x37, 0xe8, 0xce, 0xa4, 0x82, 0x70, 0x56, + 0x3c, 0x1a, 0x2b, 0x0d, 0x67, 0x41, 0xb3, 0x95, 0xff, 0xd9, + 0x06, 0x20, 0x4a, 0x6c, 0x9e, 0xb8, 0xd2, 0xf4, 0x71, 0x57, + 0x3d, 0x1b, 0xe9, 0xcf, 0xa5, 0x83, 0x5c, 0x7a, 0x10, 0x36, + 0xc4, 0xe2, 0x88, 0xae, 0x00, 0x27, 0x4e, 0x69, 0x9c, 0xbb, + 0xd2, 0xf5, 0x25, 0x02, 0x6b, 0x4c, 0xb9, 0x9e, 0xf7, 0xd0, + 0x4a, 0x6d, 0x04, 0x23, 0xd6, 0xf1, 0x98, 0xbf, 0x6f, 0x48, + 0x21, 0x06, 0xf3, 0xd4, 0xbd, 0x9a, 0x94, 0xb3, 0xda, 0xfd, + 0x08, 0x2f, 0x46, 0x61, 0xb1, 0x96, 0xff, 0xd8, 0x2d, 0x0a, + 0x63, 0x44, 0xde, 0xf9, 0x90, 0xb7, 0x42, 0x65, 0x0c, 0x2b, + 0xfb, 0xdc, 0xb5, 0x92, 0x67, 0x40, 0x29, 0x0e, 0x35, 0x12, + 0x7b, 0x5c, 0xa9, 0x8e, 0xe7, 0xc0, 0x10, 0x37, 0x5e, 0x79, + 0x8c, 0xab, 0xc2, 0xe5, 0x7f, 0x58, 0x31, 0x16, 0xe3, 0xc4, + 0xad, 0x8a, 0x5a, 0x7d, 0x14, 0x33, 0xc6, 0xe1, 0x88, 0xaf, + 0xa1, 0x86, 0xef, 0xc8, 0x3d, 0x1a, 0x73, 0x54, 0x84, 0xa3, + 0xca, 0xed, 0x18, 0x3f, 0x56, 0x71, 0xeb, 0xcc, 0xa5, 0x82, + 0x77, 0x50, 0x39, 0x1e, 0xce, 0xe9, 0x80, 0xa7, 0x52, 0x75, + 0x1c, 0x3b, 0x6a, 0x4d, 0x24, 0x03, 0xf6, 0xd1, 0xb8, 0x9f, + 0x4f, 0x68, 0x01, 0x26, 0xd3, 0xf4, 0x9d, 0xba, 0x20, 0x07, + 0x6e, 0x49, 0xbc, 0x9b, 0xf2, 0xd5, 0x05, 0x22, 0x4b, 0x6c, + 0x99, 0xbe, 0xd7, 0xf0, 0xfe, 0xd9, 0xb0, 0x97, 0x62, 0x45, + 0x2c, 0x0b, 0xdb, 0xfc, 0x95, 0xb2, 0x47, 0x60, 0x09, 0x2e, + 0xb4, 0x93, 0xfa, 0xdd, 0x28, 0x0f, 0x66, 0x41, 0x91, 0xb6, + 0xdf, 0xf8, 0x0d, 0x2a, 0x43, 0x64, 0x5f, 0x78, 0x11, 0x36, + 0xc3, 0xe4, 0x8d, 0xaa, 0x7a, 0x5d, 0x34, 0x13, 0xe6, 0xc1, + 0xa8, 0x8f, 0x15, 0x32, 0x5b, 0x7c, 0x89, 0xae, 0xc7, 0xe0, + 0x30, 0x17, 0x7e, 0x59, 0xac, 0x8b, 0xe2, 0xc5, 0xcb, 0xec, + 0x85, 0xa2, 0x57, 0x70, 0x19, 0x3e, 0xee, 0xc9, 0xa0, 0x87, + 0x72, 0x55, 0x3c, 0x1b, 0x81, 0xa6, 0xcf, 0xe8, 0x1d, 0x3a, + 0x53, 0x74, 0xa4, 0x83, 0xea, 0xcd, 0x38, 0x1f, 0x76, 0x51, + 0x00, 0x28, 0x50, 0x78, 0xa0, 0x88, 0xf0, 0xd8, 0x5d, 0x75, + 0x0d, 0x25, 0xfd, 0xd5, 0xad, 0x85, 0xba, 0x92, 0xea, 0xc2, + 0x1a, 0x32, 0x4a, 0x62, 0xe7, 0xcf, 0xb7, 0x9f, 0x47, 0x6f, + 0x17, 0x3f, 0x69, 0x41, 0x39, 0x11, 0xc9, 0xe1, 0x99, 0xb1, + 0x34, 0x1c, 0x64, 0x4c, 0x94, 0xbc, 0xc4, 0xec, 0xd3, 0xfb, + 0x83, 0xab, 0x73, 0x5b, 0x23, 0x0b, 0x8e, 0xa6, 0xde, 0xf6, + 0x2e, 0x06, 0x7e, 0x56, 0xd2, 0xfa, 0x82, 0xaa, 0x72, 0x5a, + 0x22, 0x0a, 0x8f, 0xa7, 0xdf, 0xf7, 0x2f, 0x07, 0x7f, 0x57, + 0x68, 0x40, 0x38, 0x10, 0xc8, 0xe0, 0x98, 0xb0, 0x35, 0x1d, + 0x65, 0x4d, 0x95, 0xbd, 0xc5, 0xed, 0xbb, 0x93, 0xeb, 0xc3, + 0x1b, 0x33, 0x4b, 0x63, 0xe6, 0xce, 0xb6, 0x9e, 0x46, 0x6e, + 0x16, 0x3e, 0x01, 0x29, 0x51, 0x79, 0xa1, 0x89, 0xf1, 0xd9, + 0x5c, 0x74, 0x0c, 0x24, 0xfc, 0xd4, 0xac, 0x84, 0xb9, 0x91, + 0xe9, 0xc1, 0x19, 0x31, 0x49, 0x61, 0xe4, 0xcc, 0xb4, 0x9c, + 0x44, 0x6c, 0x14, 0x3c, 0x03, 0x2b, 0x53, 0x7b, 0xa3, 0x8b, + 0xf3, 0xdb, 0x5e, 0x76, 0x0e, 0x26, 0xfe, 0xd6, 0xae, 0x86, + 0xd0, 0xf8, 0x80, 0xa8, 0x70, 0x58, 0x20, 0x08, 0x8d, 0xa5, + 0xdd, 0xf5, 0x2d, 0x05, 0x7d, 0x55, 0x6a, 0x42, 0x3a, 0x12, + 0xca, 0xe2, 0x9a, 0xb2, 0x37, 0x1f, 0x67, 0x4f, 0x97, 0xbf, + 0xc7, 0xef, 0x6b, 0x43, 0x3b, 0x13, 0xcb, 0xe3, 0x9b, 0xb3, + 0x36, 0x1e, 0x66, 0x4e, 0x96, 0xbe, 0xc6, 0xee, 0xd1, 0xf9, + 0x81, 0xa9, 0x71, 0x59, 0x21, 0x09, 0x8c, 0xa4, 0xdc, 0xf4, + 0x2c, 0x04, 0x7c, 0x54, 0x02, 0x2a, 0x52, 0x7a, 0xa2, 0x8a, + 0xf2, 0xda, 0x5f, 0x77, 0x0f, 0x27, 0xff, 0xd7, 0xaf, 0x87, + 0xb8, 0x90, 0xe8, 0xc0, 0x18, 0x30, 0x48, 0x60, 0xe5, 0xcd, + 0xb5, 0x9d, 0x45, 0x6d, 0x15, 0x3d, 0x00, 0x29, 0x52, 0x7b, + 0xa4, 0x8d, 0xf6, 0xdf, 0x55, 0x7c, 0x07, 0x2e, 0xf1, 0xd8, + 0xa3, 0x8a, 0xaa, 0x83, 0xf8, 0xd1, 0x0e, 0x27, 0x5c, 0x75, + 0xff, 0xd6, 0xad, 0x84, 0x5b, 0x72, 0x09, 0x20, 0x49, 0x60, + 0x1b, 0x32, 0xed, 0xc4, 0xbf, 0x96, 0x1c, 0x35, 0x4e, 0x67, + 0xb8, 0x91, 0xea, 0xc3, 0xe3, 0xca, 0xb1, 0x98, 0x47, 0x6e, + 0x15, 0x3c, 0xb6, 0x9f, 0xe4, 0xcd, 0x12, 0x3b, 0x40, 0x69, + 0x92, 0xbb, 0xc0, 0xe9, 0x36, 0x1f, 0x64, 0x4d, 0xc7, 0xee, + 0x95, 0xbc, 0x63, 0x4a, 0x31, 0x18, 0x38, 0x11, 0x6a, 0x43, + 0x9c, 0xb5, 0xce, 0xe7, 0x6d, 0x44, 0x3f, 0x16, 0xc9, 0xe0, + 0x9b, 0xb2, 0xdb, 0xf2, 0x89, 0xa0, 0x7f, 0x56, 0x2d, 0x04, + 0x8e, 0xa7, 0xdc, 0xf5, 0x2a, 0x03, 0x78, 0x51, 0x71, 0x58, + 0x23, 0x0a, 0xd5, 0xfc, 0x87, 0xae, 0x24, 0x0d, 0x76, 0x5f, + 0x80, 0xa9, 0xd2, 0xfb, 0x39, 0x10, 0x6b, 0x42, 0x9d, 0xb4, + 0xcf, 0xe6, 0x6c, 0x45, 0x3e, 0x17, 0xc8, 0xe1, 0x9a, 0xb3, + 0x93, 0xba, 0xc1, 0xe8, 0x37, 0x1e, 0x65, 0x4c, 0xc6, 0xef, + 0x94, 0xbd, 0x62, 0x4b, 0x30, 0x19, 0x70, 0x59, 0x22, 0x0b, + 0xd4, 0xfd, 0x86, 0xaf, 0x25, 0x0c, 0x77, 0x5e, 0x81, 0xa8, + 0xd3, 0xfa, 0xda, 0xf3, 0x88, 0xa1, 0x7e, 0x57, 0x2c, 0x05, + 0x8f, 0xa6, 0xdd, 0xf4, 0x2b, 0x02, 0x79, 0x50, 0xab, 0x82, + 0xf9, 0xd0, 0x0f, 0x26, 0x5d, 0x74, 0xfe, 0xd7, 0xac, 0x85, + 0x5a, 0x73, 0x08, 0x21, 0x01, 0x28, 0x53, 0x7a, 0xa5, 0x8c, + 0xf7, 0xde, 0x54, 0x7d, 0x06, 0x2f, 0xf0, 0xd9, 0xa2, 0x8b, + 0xe2, 0xcb, 0xb0, 0x99, 0x46, 0x6f, 0x14, 0x3d, 0xb7, 0x9e, + 0xe5, 0xcc, 0x13, 0x3a, 0x41, 0x68, 0x48, 0x61, 0x1a, 0x33, + 0xec, 0xc5, 0xbe, 0x97, 0x1d, 0x34, 0x4f, 0x66, 0xb9, 0x90, + 0xeb, 0xc2, 0x00, 0x2a, 0x54, 0x7e, 0xa8, 0x82, 0xfc, 0xd6, + 0x4d, 0x67, 0x19, 0x33, 0xe5, 0xcf, 0xb1, 0x9b, 0x9a, 0xb0, + 0xce, 0xe4, 0x32, 0x18, 0x66, 0x4c, 0xd7, 0xfd, 0x83, 0xa9, + 0x7f, 0x55, 0x2b, 0x01, 0x29, 0x03, 0x7d, 0x57, 0x81, 0xab, + 0xd5, 0xff, 0x64, 0x4e, 0x30, 0x1a, 0xcc, 0xe6, 0x98, 0xb2, + 0xb3, 0x99, 0xe7, 0xcd, 0x1b, 0x31, 0x4f, 0x65, 0xfe, 0xd4, + 0xaa, 0x80, 0x56, 0x7c, 0x02, 0x28, 0x52, 0x78, 0x06, 0x2c, + 0xfa, 0xd0, 0xae, 0x84, 0x1f, 0x35, 0x4b, 0x61, 0xb7, 0x9d, + 0xe3, 0xc9, 0xc8, 0xe2, 0x9c, 0xb6, 0x60, 0x4a, 0x34, 0x1e, + 0x85, 0xaf, 0xd1, 0xfb, 0x2d, 0x07, 0x79, 0x53, 0x7b, 0x51, + 0x2f, 0x05, 0xd3, 0xf9, 0x87, 0xad, 0x36, 0x1c, 0x62, 0x48, + 0x9e, 0xb4, 0xca, 0xe0, 0xe1, 0xcb, 0xb5, 0x9f, 0x49, 0x63, + 0x1d, 0x37, 0xac, 0x86, 0xf8, 0xd2, 0x04, 0x2e, 0x50, 0x7a, + 0xa4, 0x8e, 0xf0, 0xda, 0x0c, 0x26, 0x58, 0x72, 0xe9, 0xc3, + 0xbd, 0x97, 0x41, 0x6b, 0x15, 0x3f, 0x3e, 0x14, 0x6a, 0x40, + 0x96, 0xbc, 0xc2, 0xe8, 0x73, 0x59, 0x27, 0x0d, 0xdb, 0xf1, + 0x8f, 0xa5, 0x8d, 0xa7, 0xd9, 0xf3, 0x25, 0x0f, 0x71, 0x5b, + 0xc0, 0xea, 0x94, 0xbe, 0x68, 0x42, 0x3c, 0x16, 0x17, 0x3d, + 0x43, 0x69, 0xbf, 0x95, 0xeb, 0xc1, 0x5a, 0x70, 0x0e, 0x24, + 0xf2, 0xd8, 0xa6, 0x8c, 0xf6, 0xdc, 0xa2, 0x88, 0x5e, 0x74, + 0x0a, 0x20, 0xbb, 0x91, 0xef, 0xc5, 0x13, 0x39, 0x47, 0x6d, + 0x6c, 0x46, 0x38, 0x12, 0xc4, 0xee, 0x90, 0xba, 0x21, 0x0b, + 0x75, 0x5f, 0x89, 0xa3, 0xdd, 0xf7, 0xdf, 0xf5, 0x8b, 0xa1, + 0x77, 0x5d, 0x23, 0x09, 0x92, 0xb8, 0xc6, 0xec, 0x3a, 0x10, + 0x6e, 0x44, 0x45, 0x6f, 0x11, 0x3b, 0xed, 0xc7, 0xb9, 0x93, + 0x08, 0x22, 0x5c, 0x76, 0xa0, 0x8a, 0xf4, 0xde, 0x00, 0x2b, + 0x56, 0x7d, 0xac, 0x87, 0xfa, 0xd1, 0x45, 0x6e, 0x13, 0x38, + 0xe9, 0xc2, 0xbf, 0x94, 0x8a, 0xa1, 0xdc, 0xf7, 0x26, 0x0d, + 0x70, 0x5b, 0xcf, 0xe4, 0x99, 0xb2, 0x63, 0x48, 0x35, 0x1e, + 0x09, 0x22, 0x5f, 0x74, 0xa5, 0x8e, 0xf3, 0xd8, 0x4c, 0x67, + 0x1a, 0x31, 0xe0, 0xcb, 0xb6, 0x9d, 0x83, 0xa8, 0xd5, 0xfe, + 0x2f, 0x04, 0x79, 0x52, 0xc6, 0xed, 0x90, 0xbb, 0x6a, 0x41, + 0x3c, 0x17, 0x12, 0x39, 0x44, 0x6f, 0xbe, 0x95, 0xe8, 0xc3, + 0x57, 0x7c, 0x01, 0x2a, 0xfb, 0xd0, 0xad, 0x86, 0x98, 0xb3, + 0xce, 0xe5, 0x34, 0x1f, 0x62, 0x49, 0xdd, 0xf6, 0x8b, 0xa0, + 0x71, 0x5a, 0x27, 0x0c, 0x1b, 0x30, 0x4d, 0x66, 0xb7, 0x9c, + 0xe1, 0xca, 0x5e, 0x75, 0x08, 0x23, 0xf2, 0xd9, 0xa4, 0x8f, + 0x91, 0xba, 0xc7, 0xec, 0x3d, 0x16, 0x6b, 0x40, 0xd4, 0xff, + 0x82, 0xa9, 0x78, 0x53, 0x2e, 0x05, 0x24, 0x0f, 0x72, 0x59, + 0x88, 0xa3, 0xde, 0xf5, 0x61, 0x4a, 0x37, 0x1c, 0xcd, 0xe6, + 0x9b, 0xb0, 0xae, 0x85, 0xf8, 0xd3, 0x02, 0x29, 0x54, 0x7f, + 0xeb, 0xc0, 0xbd, 0x96, 0x47, 0x6c, 0x11, 0x3a, 0x2d, 0x06, + 0x7b, 0x50, 0x81, 0xaa, 0xd7, 0xfc, 0x68, 0x43, 0x3e, 0x15, + 0xc4, 0xef, 0x92, 0xb9, 0xa7, 0x8c, 0xf1, 0xda, 0x0b, 0x20, + 0x5d, 0x76, 0xe2, 0xc9, 0xb4, 0x9f, 0x4e, 0x65, 0x18, 0x33, + 0x36, 0x1d, 0x60, 0x4b, 0x9a, 0xb1, 0xcc, 0xe7, 0x73, 0x58, + 0x25, 0x0e, 0xdf, 0xf4, 0x89, 0xa2, 0xbc, 0x97, 0xea, 0xc1, + 0x10, 0x3b, 0x46, 0x6d, 0xf9, 0xd2, 0xaf, 0x84, 0x55, 0x7e, + 0x03, 0x28, 0x3f, 0x14, 0x69, 0x42, 0x93, 0xb8, 0xc5, 0xee, + 0x7a, 0x51, 0x2c, 0x07, 0xd6, 0xfd, 0x80, 0xab, 0xb5, 0x9e, + 0xe3, 0xc8, 0x19, 0x32, 0x4f, 0x64, 0xf0, 0xdb, 0xa6, 0x8d, + 0x5c, 0x77, 0x0a, 0x21, 0x00, 0x2c, 0x58, 0x74, 0xb0, 0x9c, + 0xe8, 0xc4, 0x7d, 0x51, 0x25, 0x09, 0xcd, 0xe1, 0x95, 0xb9, + 0xfa, 0xd6, 0xa2, 0x8e, 0x4a, 0x66, 0x12, 0x3e, 0x87, 0xab, + 0xdf, 0xf3, 0x37, 0x1b, 0x6f, 0x43, 0xe9, 0xc5, 0xb1, 0x9d, + 0x59, 0x75, 0x01, 0x2d, 0x94, 0xb8, 0xcc, 0xe0, 0x24, 0x08, + 0x7c, 0x50, 0x13, 0x3f, 0x4b, 0x67, 0xa3, 0x8f, 0xfb, 0xd7, + 0x6e, 0x42, 0x36, 0x1a, 0xde, 0xf2, 0x86, 0xaa, 0xcf, 0xe3, + 0x97, 0xbb, 0x7f, 0x53, 0x27, 0x0b, 0xb2, 0x9e, 0xea, 0xc6, + 0x02, 0x2e, 0x5a, 0x76, 0x35, 0x19, 0x6d, 0x41, 0x85, 0xa9, + 0xdd, 0xf1, 0x48, 0x64, 0x10, 0x3c, 0xf8, 0xd4, 0xa0, 0x8c, + 0x26, 0x0a, 0x7e, 0x52, 0x96, 0xba, 0xce, 0xe2, 0x5b, 0x77, + 0x03, 0x2f, 0xeb, 0xc7, 0xb3, 0x9f, 0xdc, 0xf0, 0x84, 0xa8, + 0x6c, 0x40, 0x34, 0x18, 0xa1, 0x8d, 0xf9, 0xd5, 0x11, 0x3d, + 0x49, 0x65, 0x83, 0xaf, 0xdb, 0xf7, 0x33, 0x1f, 0x6b, 0x47, + 0xfe, 0xd2, 0xa6, 0x8a, 0x4e, 0x62, 0x16, 0x3a, 0x79, 0x55, + 0x21, 0x0d, 0xc9, 0xe5, 0x91, 0xbd, 0x04, 0x28, 0x5c, 0x70, + 0xb4, 0x98, 0xec, 0xc0, 0x6a, 0x46, 0x32, 0x1e, 0xda, 0xf6, + 0x82, 0xae, 0x17, 0x3b, 0x4f, 0x63, 0xa7, 0x8b, 0xff, 0xd3, + 0x90, 0xbc, 0xc8, 0xe4, 0x20, 0x0c, 0x78, 0x54, 0xed, 0xc1, + 0xb5, 0x99, 0x5d, 0x71, 0x05, 0x29, 0x4c, 0x60, 0x14, 0x38, + 0xfc, 0xd0, 0xa4, 0x88, 0x31, 0x1d, 0x69, 0x45, 0x81, 0xad, + 0xd9, 0xf5, 0xb6, 0x9a, 0xee, 0xc2, 0x06, 0x2a, 0x5e, 0x72, + 0xcb, 0xe7, 0x93, 0xbf, 0x7b, 0x57, 0x23, 0x0f, 0xa5, 0x89, + 0xfd, 0xd1, 0x15, 0x39, 0x4d, 0x61, 0xd8, 0xf4, 0x80, 0xac, + 0x68, 0x44, 0x30, 0x1c, 0x5f, 0x73, 0x07, 0x2b, 0xef, 0xc3, + 0xb7, 0x9b, 0x22, 0x0e, 0x7a, 0x56, 0x92, 0xbe, 0xca, 0xe6, + 0x00, 0x2d, 0x5a, 0x77, 0xb4, 0x99, 0xee, 0xc3, 0x75, 0x58, + 0x2f, 0x02, 0xc1, 0xec, 0x9b, 0xb6, 0xea, 0xc7, 0xb0, 0x9d, + 0x5e, 0x73, 0x04, 0x29, 0x9f, 0xb2, 0xc5, 0xe8, 0x2b, 0x06, + 0x71, 0x5c, 0xc9, 0xe4, 0x93, 0xbe, 0x7d, 0x50, 0x27, 0x0a, + 0xbc, 0x91, 0xe6, 0xcb, 0x08, 0x25, 0x52, 0x7f, 0x23, 0x0e, + 0x79, 0x54, 0x97, 0xba, 0xcd, 0xe0, 0x56, 0x7b, 0x0c, 0x21, + 0xe2, 0xcf, 0xb8, 0x95, 0x8f, 0xa2, 0xd5, 0xf8, 0x3b, 0x16, + 0x61, 0x4c, 0xfa, 0xd7, 0xa0, 0x8d, 0x4e, 0x63, 0x14, 0x39, + 0x65, 0x48, 0x3f, 0x12, 0xd1, 0xfc, 0x8b, 0xa6, 0x10, 0x3d, + 0x4a, 0x67, 0xa4, 0x89, 0xfe, 0xd3, 0x46, 0x6b, 0x1c, 0x31, + 0xf2, 0xdf, 0xa8, 0x85, 0x33, 0x1e, 0x69, 0x44, 0x87, 0xaa, + 0xdd, 0xf0, 0xac, 0x81, 0xf6, 0xdb, 0x18, 0x35, 0x42, 0x6f, + 0xd9, 0xf4, 0x83, 0xae, 0x6d, 0x40, 0x37, 0x1a, 0x03, 0x2e, + 0x59, 0x74, 0xb7, 0x9a, 0xed, 0xc0, 0x76, 0x5b, 0x2c, 0x01, + 0xc2, 0xef, 0x98, 0xb5, 0xe9, 0xc4, 0xb3, 0x9e, 0x5d, 0x70, + 0x07, 0x2a, 0x9c, 0xb1, 0xc6, 0xeb, 0x28, 0x05, 0x72, 0x5f, + 0xca, 0xe7, 0x90, 0xbd, 0x7e, 0x53, 0x24, 0x09, 0xbf, 0x92, + 0xe5, 0xc8, 0x0b, 0x26, 0x51, 0x7c, 0x20, 0x0d, 0x7a, 0x57, + 0x94, 0xb9, 0xce, 0xe3, 0x55, 0x78, 0x0f, 0x22, 0xe1, 0xcc, + 0xbb, 0x96, 0x8c, 0xa1, 0xd6, 0xfb, 0x38, 0x15, 0x62, 0x4f, + 0xf9, 0xd4, 0xa3, 0x8e, 0x4d, 0x60, 0x17, 0x3a, 0x66, 0x4b, + 0x3c, 0x11, 0xd2, 0xff, 0x88, 0xa5, 0x13, 0x3e, 0x49, 0x64, + 0xa7, 0x8a, 0xfd, 0xd0, 0x45, 0x68, 0x1f, 0x32, 0xf1, 0xdc, + 0xab, 0x86, 0x30, 0x1d, 0x6a, 0x47, 0x84, 0xa9, 0xde, 0xf3, + 0xaf, 0x82, 0xf5, 0xd8, 0x1b, 0x36, 0x41, 0x6c, 0xda, 0xf7, + 0x80, 0xad, 0x6e, 0x43, 0x34, 0x19, 0x00, 0x2e, 0x5c, 0x72, + 0xb8, 0x96, 0xe4, 0xca, 0x6d, 0x43, 0x31, 0x1f, 0xd5, 0xfb, + 0x89, 0xa7, 0xda, 0xf4, 0x86, 0xa8, 0x62, 0x4c, 0x3e, 0x10, + 0xb7, 0x99, 0xeb, 0xc5, 0x0f, 0x21, 0x53, 0x7d, 0xa9, 0x87, + 0xf5, 0xdb, 0x11, 0x3f, 0x4d, 0x63, 0xc4, 0xea, 0x98, 0xb6, + 0x7c, 0x52, 0x20, 0x0e, 0x73, 0x5d, 0x2f, 0x01, 0xcb, 0xe5, + 0x97, 0xb9, 0x1e, 0x30, 0x42, 0x6c, 0xa6, 0x88, 0xfa, 0xd4, + 0x4f, 0x61, 0x13, 0x3d, 0xf7, 0xd9, 0xab, 0x85, 0x22, 0x0c, + 0x7e, 0x50, 0x9a, 0xb4, 0xc6, 0xe8, 0x95, 0xbb, 0xc9, 0xe7, + 0x2d, 0x03, 0x71, 0x5f, 0xf8, 0xd6, 0xa4, 0x8a, 0x40, 0x6e, + 0x1c, 0x32, 0xe6, 0xc8, 0xba, 0x94, 0x5e, 0x70, 0x02, 0x2c, + 0x8b, 0xa5, 0xd7, 0xf9, 0x33, 0x1d, 0x6f, 0x41, 0x3c, 0x12, + 0x60, 0x4e, 0x84, 0xaa, 0xd8, 0xf6, 0x51, 0x7f, 0x0d, 0x23, + 0xe9, 0xc7, 0xb5, 0x9b, 0x9e, 0xb0, 0xc2, 0xec, 0x26, 0x08, + 0x7a, 0x54, 0xf3, 0xdd, 0xaf, 0x81, 0x4b, 0x65, 0x17, 0x39, + 0x44, 0x6a, 0x18, 0x36, 0xfc, 0xd2, 0xa0, 0x8e, 0x29, 0x07, + 0x75, 0x5b, 0x91, 0xbf, 0xcd, 0xe3, 0x37, 0x19, 0x6b, 0x45, + 0x8f, 0xa1, 0xd3, 0xfd, 0x5a, 0x74, 0x06, 0x28, 0xe2, 0xcc, + 0xbe, 0x90, 0xed, 0xc3, 0xb1, 0x9f, 0x55, 0x7b, 0x09, 0x27, + 0x80, 0xae, 0xdc, 0xf2, 0x38, 0x16, 0x64, 0x4a, 0xd1, 0xff, + 0x8d, 0xa3, 0x69, 0x47, 0x35, 0x1b, 0xbc, 0x92, 0xe0, 0xce, + 0x04, 0x2a, 0x58, 0x76, 0x0b, 0x25, 0x57, 0x79, 0xb3, 0x9d, + 0xef, 0xc1, 0x66, 0x48, 0x3a, 0x14, 0xde, 0xf0, 0x82, 0xac, + 0x78, 0x56, 0x24, 0x0a, 0xc0, 0xee, 0x9c, 0xb2, 0x15, 0x3b, + 0x49, 0x67, 0xad, 0x83, 0xf1, 0xdf, 0xa2, 0x8c, 0xfe, 0xd0, + 0x1a, 0x34, 0x46, 0x68, 0xcf, 0xe1, 0x93, 0xbd, 0x77, 0x59, + 0x2b, 0x05, 0x00, 0x2f, 0x5e, 0x71, 0xbc, 0x93, 0xe2, 0xcd, + 0x65, 0x4a, 0x3b, 0x14, 0xd9, 0xf6, 0x87, 0xa8, 0xca, 0xe5, + 0x94, 0xbb, 0x76, 0x59, 0x28, 0x07, 0xaf, 0x80, 0xf1, 0xde, + 0x13, 0x3c, 0x4d, 0x62, 0x89, 0xa6, 0xd7, 0xf8, 0x35, 0x1a, + 0x6b, 0x44, 0xec, 0xc3, 0xb2, 0x9d, 0x50, 0x7f, 0x0e, 0x21, + 0x43, 0x6c, 0x1d, 0x32, 0xff, 0xd0, 0xa1, 0x8e, 0x26, 0x09, + 0x78, 0x57, 0x9a, 0xb5, 0xc4, 0xeb, 0x0f, 0x20, 0x51, 0x7e, + 0xb3, 0x9c, 0xed, 0xc2, 0x6a, 0x45, 0x34, 0x1b, 0xd6, 0xf9, + 0x88, 0xa7, 0xc5, 0xea, 0x9b, 0xb4, 0x79, 0x56, 0x27, 0x08, + 0xa0, 0x8f, 0xfe, 0xd1, 0x1c, 0x33, 0x42, 0x6d, 0x86, 0xa9, + 0xd8, 0xf7, 0x3a, 0x15, 0x64, 0x4b, 0xe3, 0xcc, 0xbd, 0x92, + 0x5f, 0x70, 0x01, 0x2e, 0x4c, 0x63, 0x12, 0x3d, 0xf0, 0xdf, + 0xae, 0x81, 0x29, 0x06, 0x77, 0x58, 0x95, 0xba, 0xcb, 0xe4, + 0x1e, 0x31, 0x40, 0x6f, 0xa2, 0x8d, 0xfc, 0xd3, 0x7b, 0x54, + 0x25, 0x0a, 0xc7, 0xe8, 0x99, 0xb6, 0xd4, 0xfb, 0x8a, 0xa5, + 0x68, 0x47, 0x36, 0x19, 0xb1, 0x9e, 0xef, 0xc0, 0x0d, 0x22, + 0x53, 0x7c, 0x97, 0xb8, 0xc9, 0xe6, 0x2b, 0x04, 0x75, 0x5a, + 0xf2, 0xdd, 0xac, 0x83, 0x4e, 0x61, 0x10, 0x3f, 0x5d, 0x72, + 0x03, 0x2c, 0xe1, 0xce, 0xbf, 0x90, 0x38, 0x17, 0x66, 0x49, + 0x84, 0xab, 0xda, 0xf5, 0x11, 0x3e, 0x4f, 0x60, 0xad, 0x82, + 0xf3, 0xdc, 0x74, 0x5b, 0x2a, 0x05, 0xc8, 0xe7, 0x96, 0xb9, + 0xdb, 0xf4, 0x85, 0xaa, 0x67, 0x48, 0x39, 0x16, 0xbe, 0x91, + 0xe0, 0xcf, 0x02, 0x2d, 0x5c, 0x73, 0x98, 0xb7, 0xc6, 0xe9, + 0x24, 0x0b, 0x7a, 0x55, 0xfd, 0xd2, 0xa3, 0x8c, 0x41, 0x6e, + 0x1f, 0x30, 0x52, 0x7d, 0x0c, 0x23, 0xee, 0xc1, 0xb0, 0x9f, + 0x37, 0x18, 0x69, 0x46, 0x8b, 0xa4, 0xd5, 0xfa, 0x00, 0x30, + 0x60, 0x50, 0xc0, 0xf0, 0xa0, 0x90, 0x9d, 0xad, 0xfd, 0xcd, + 0x5d, 0x6d, 0x3d, 0x0d, 0x27, 0x17, 0x47, 0x77, 0xe7, 0xd7, + 0x87, 0xb7, 0xba, 0x8a, 0xda, 0xea, 0x7a, 0x4a, 0x1a, 0x2a, + 0x4e, 0x7e, 0x2e, 0x1e, 0x8e, 0xbe, 0xee, 0xde, 0xd3, 0xe3, + 0xb3, 0x83, 0x13, 0x23, 0x73, 0x43, 0x69, 0x59, 0x09, 0x39, + 0xa9, 0x99, 0xc9, 0xf9, 0xf4, 0xc4, 0x94, 0xa4, 0x34, 0x04, + 0x54, 0x64, 0x9c, 0xac, 0xfc, 0xcc, 0x5c, 0x6c, 0x3c, 0x0c, + 0x01, 0x31, 0x61, 0x51, 0xc1, 0xf1, 0xa1, 0x91, 0xbb, 0x8b, + 0xdb, 0xeb, 0x7b, 0x4b, 0x1b, 0x2b, 0x26, 0x16, 0x46, 0x76, + 0xe6, 0xd6, 0x86, 0xb6, 0xd2, 0xe2, 0xb2, 0x82, 0x12, 0x22, + 0x72, 0x42, 0x4f, 0x7f, 0x2f, 0x1f, 0x8f, 0xbf, 0xef, 0xdf, + 0xf5, 0xc5, 0x95, 0xa5, 0x35, 0x05, 0x55, 0x65, 0x68, 0x58, + 0x08, 0x38, 0xa8, 0x98, 0xc8, 0xf8, 0x25, 0x15, 0x45, 0x75, + 0xe5, 0xd5, 0x85, 0xb5, 0xb8, 0x88, 0xd8, 0xe8, 0x78, 0x48, + 0x18, 0x28, 0x02, 0x32, 0x62, 0x52, 0xc2, 0xf2, 0xa2, 0x92, + 0x9f, 0xaf, 0xff, 0xcf, 0x5f, 0x6f, 0x3f, 0x0f, 0x6b, 0x5b, + 0x0b, 0x3b, 0xab, 0x9b, 0xcb, 0xfb, 0xf6, 0xc6, 0x96, 0xa6, + 0x36, 0x06, 0x56, 0x66, 0x4c, 0x7c, 0x2c, 0x1c, 0x8c, 0xbc, + 0xec, 0xdc, 0xd1, 0xe1, 0xb1, 0x81, 0x11, 0x21, 0x71, 0x41, + 0xb9, 0x89, 0xd9, 0xe9, 0x79, 0x49, 0x19, 0x29, 0x24, 0x14, + 0x44, 0x74, 0xe4, 0xd4, 0x84, 0xb4, 0x9e, 0xae, 0xfe, 0xce, + 0x5e, 0x6e, 0x3e, 0x0e, 0x03, 0x33, 0x63, 0x53, 0xc3, 0xf3, + 0xa3, 0x93, 0xf7, 0xc7, 0x97, 0xa7, 0x37, 0x07, 0x57, 0x67, + 0x6a, 0x5a, 0x0a, 0x3a, 0xaa, 0x9a, 0xca, 0xfa, 0xd0, 0xe0, + 0xb0, 0x80, 0x10, 0x20, 0x70, 0x40, 0x4d, 0x7d, 0x2d, 0x1d, + 0x8d, 0xbd, 0xed, 0xdd, 0x00, 0x31, 0x62, 0x53, 0xc4, 0xf5, + 0xa6, 0x97, 0x95, 0xa4, 0xf7, 0xc6, 0x51, 0x60, 0x33, 0x02, + 0x37, 0x06, 0x55, 0x64, 0xf3, 0xc2, 0x91, 0xa0, 0xa2, 0x93, + 0xc0, 0xf1, 0x66, 0x57, 0x04, 0x35, 0x6e, 0x5f, 0x0c, 0x3d, + 0xaa, 0x9b, 0xc8, 0xf9, 0xfb, 0xca, 0x99, 0xa8, 0x3f, 0x0e, + 0x5d, 0x6c, 0x59, 0x68, 0x3b, 0x0a, 0x9d, 0xac, 0xff, 0xce, + 0xcc, 0xfd, 0xae, 0x9f, 0x08, 0x39, 0x6a, 0x5b, 0xdc, 0xed, + 0xbe, 0x8f, 0x18, 0x29, 0x7a, 0x4b, 0x49, 0x78, 0x2b, 0x1a, + 0x8d, 0xbc, 0xef, 0xde, 0xeb, 0xda, 0x89, 0xb8, 0x2f, 0x1e, + 0x4d, 0x7c, 0x7e, 0x4f, 0x1c, 0x2d, 0xba, 0x8b, 0xd8, 0xe9, + 0xb2, 0x83, 0xd0, 0xe1, 0x76, 0x47, 0x14, 0x25, 0x27, 0x16, + 0x45, 0x74, 0xe3, 0xd2, 0x81, 0xb0, 0x85, 0xb4, 0xe7, 0xd6, + 0x41, 0x70, 0x23, 0x12, 0x10, 0x21, 0x72, 0x43, 0xd4, 0xe5, + 0xb6, 0x87, 0xa5, 0x94, 0xc7, 0xf6, 0x61, 0x50, 0x03, 0x32, + 0x30, 0x01, 0x52, 0x63, 0xf4, 0xc5, 0x96, 0xa7, 0x92, 0xa3, + 0xf0, 0xc1, 0x56, 0x67, 0x34, 0x05, 0x07, 0x36, 0x65, 0x54, + 0xc3, 0xf2, 0xa1, 0x90, 0xcb, 0xfa, 0xa9, 0x98, 0x0f, 0x3e, + 0x6d, 0x5c, 0x5e, 0x6f, 0x3c, 0x0d, 0x9a, 0xab, 0xf8, 0xc9, + 0xfc, 0xcd, 0x9e, 0xaf, 0x38, 0x09, 0x5a, 0x6b, 0x69, 0x58, + 0x0b, 0x3a, 0xad, 0x9c, 0xcf, 0xfe, 0x79, 0x48, 0x1b, 0x2a, + 0xbd, 0x8c, 0xdf, 0xee, 0xec, 0xdd, 0x8e, 0xbf, 0x28, 0x19, + 0x4a, 0x7b, 0x4e, 0x7f, 0x2c, 0x1d, 0x8a, 0xbb, 0xe8, 0xd9, + 0xdb, 0xea, 0xb9, 0x88, 0x1f, 0x2e, 0x7d, 0x4c, 0x17, 0x26, + 0x75, 0x44, 0xd3, 0xe2, 0xb1, 0x80, 0x82, 0xb3, 0xe0, 0xd1, + 0x46, 0x77, 0x24, 0x15, 0x20, 0x11, 0x42, 0x73, 0xe4, 0xd5, + 0x86, 0xb7, 0xb5, 0x84, 0xd7, 0xe6, 0x71, 0x40, 0x13, 0x22, + 0x00, 0x32, 0x64, 0x56, 0xc8, 0xfa, 0xac, 0x9e, 0x8d, 0xbf, + 0xe9, 0xdb, 0x45, 0x77, 0x21, 0x13, 0x07, 0x35, 0x63, 0x51, + 0xcf, 0xfd, 0xab, 0x99, 0x8a, 0xb8, 0xee, 0xdc, 0x42, 0x70, + 0x26, 0x14, 0x0e, 0x3c, 0x6a, 0x58, 0xc6, 0xf4, 0xa2, 0x90, + 0x83, 0xb1, 0xe7, 0xd5, 0x4b, 0x79, 0x2f, 0x1d, 0x09, 0x3b, + 0x6d, 0x5f, 0xc1, 0xf3, 0xa5, 0x97, 0x84, 0xb6, 0xe0, 0xd2, + 0x4c, 0x7e, 0x28, 0x1a, 0x1c, 0x2e, 0x78, 0x4a, 0xd4, 0xe6, + 0xb0, 0x82, 0x91, 0xa3, 0xf5, 0xc7, 0x59, 0x6b, 0x3d, 0x0f, + 0x1b, 0x29, 0x7f, 0x4d, 0xd3, 0xe1, 0xb7, 0x85, 0x96, 0xa4, + 0xf2, 0xc0, 0x5e, 0x6c, 0x3a, 0x08, 0x12, 0x20, 0x76, 0x44, + 0xda, 0xe8, 0xbe, 0x8c, 0x9f, 0xad, 0xfb, 0xc9, 0x57, 0x65, + 0x33, 0x01, 0x15, 0x27, 0x71, 0x43, 0xdd, 0xef, 0xb9, 0x8b, + 0x98, 0xaa, 0xfc, 0xce, 0x50, 0x62, 0x34, 0x06, 0x38, 0x0a, + 0x5c, 0x6e, 0xf0, 0xc2, 0x94, 0xa6, 0xb5, 0x87, 0xd1, 0xe3, + 0x7d, 0x4f, 0x19, 0x2b, 0x3f, 0x0d, 0x5b, 0x69, 0xf7, 0xc5, + 0x93, 0xa1, 0xb2, 0x80, 0xd6, 0xe4, 0x7a, 0x48, 0x1e, 0x2c, + 0x36, 0x04, 0x52, 0x60, 0xfe, 0xcc, 0x9a, 0xa8, 0xbb, 0x89, + 0xdf, 0xed, 0x73, 0x41, 0x17, 0x25, 0x31, 0x03, 0x55, 0x67, + 0xf9, 0xcb, 0x9d, 0xaf, 0xbc, 0x8e, 0xd8, 0xea, 0x74, 0x46, + 0x10, 0x22, 0x24, 0x16, 0x40, 0x72, 0xec, 0xde, 0x88, 0xba, + 0xa9, 0x9b, 0xcd, 0xff, 0x61, 0x53, 0x05, 0x37, 0x23, 0x11, + 0x47, 0x75, 0xeb, 0xd9, 0x8f, 0xbd, 0xae, 0x9c, 0xca, 0xf8, + 0x66, 0x54, 0x02, 0x30, 0x2a, 0x18, 0x4e, 0x7c, 0xe2, 0xd0, + 0x86, 0xb4, 0xa7, 0x95, 0xc3, 0xf1, 0x6f, 0x5d, 0x0b, 0x39, + 0x2d, 0x1f, 0x49, 0x7b, 0xe5, 0xd7, 0x81, 0xb3, 0xa0, 0x92, + 0xc4, 0xf6, 0x68, 0x5a, 0x0c, 0x3e, 0x00, 0x33, 0x66, 0x55, + 0xcc, 0xff, 0xaa, 0x99, 0x85, 0xb6, 0xe3, 0xd0, 0x49, 0x7a, + 0x2f, 0x1c, 0x17, 0x24, 0x71, 0x42, 0xdb, 0xe8, 0xbd, 0x8e, + 0x92, 0xa1, 0xf4, 0xc7, 0x5e, 0x6d, 0x38, 0x0b, 0x2e, 0x1d, + 0x48, 0x7b, 0xe2, 0xd1, 0x84, 0xb7, 0xab, 0x98, 0xcd, 0xfe, + 0x67, 0x54, 0x01, 0x32, 0x39, 0x0a, 0x5f, 0x6c, 0xf5, 0xc6, + 0x93, 0xa0, 0xbc, 0x8f, 0xda, 0xe9, 0x70, 0x43, 0x16, 0x25, + 0x5c, 0x6f, 0x3a, 0x09, 0x90, 0xa3, 0xf6, 0xc5, 0xd9, 0xea, + 0xbf, 0x8c, 0x15, 0x26, 0x73, 0x40, 0x4b, 0x78, 0x2d, 0x1e, + 0x87, 0xb4, 0xe1, 0xd2, 0xce, 0xfd, 0xa8, 0x9b, 0x02, 0x31, + 0x64, 0x57, 0x72, 0x41, 0x14, 0x27, 0xbe, 0x8d, 0xd8, 0xeb, + 0xf7, 0xc4, 0x91, 0xa2, 0x3b, 0x08, 0x5d, 0x6e, 0x65, 0x56, + 0x03, 0x30, 0xa9, 0x9a, 0xcf, 0xfc, 0xe0, 0xd3, 0x86, 0xb5, + 0x2c, 0x1f, 0x4a, 0x79, 0xb8, 0x8b, 0xde, 0xed, 0x74, 0x47, + 0x12, 0x21, 0x3d, 0x0e, 0x5b, 0x68, 0xf1, 0xc2, 0x97, 0xa4, + 0xaf, 0x9c, 0xc9, 0xfa, 0x63, 0x50, 0x05, 0x36, 0x2a, 0x19, + 0x4c, 0x7f, 0xe6, 0xd5, 0x80, 0xb3, 0x96, 0xa5, 0xf0, 0xc3, + 0x5a, 0x69, 0x3c, 0x0f, 0x13, 0x20, 0x75, 0x46, 0xdf, 0xec, + 0xb9, 0x8a, 0x81, 0xb2, 0xe7, 0xd4, 0x4d, 0x7e, 0x2b, 0x18, + 0x04, 0x37, 0x62, 0x51, 0xc8, 0xfb, 0xae, 0x9d, 0xe4, 0xd7, + 0x82, 0xb1, 0x28, 0x1b, 0x4e, 0x7d, 0x61, 0x52, 0x07, 0x34, + 0xad, 0x9e, 0xcb, 0xf8, 0xf3, 0xc0, 0x95, 0xa6, 0x3f, 0x0c, + 0x59, 0x6a, 0x76, 0x45, 0x10, 0x23, 0xba, 0x89, 0xdc, 0xef, + 0xca, 0xf9, 0xac, 0x9f, 0x06, 0x35, 0x60, 0x53, 0x4f, 0x7c, + 0x29, 0x1a, 0x83, 0xb0, 0xe5, 0xd6, 0xdd, 0xee, 0xbb, 0x88, + 0x11, 0x22, 0x77, 0x44, 0x58, 0x6b, 0x3e, 0x0d, 0x94, 0xa7, + 0xf2, 0xc1, 0x00, 0x34, 0x68, 0x5c, 0xd0, 0xe4, 0xb8, 0x8c, + 0xbd, 0x89, 0xd5, 0xe1, 0x6d, 0x59, 0x05, 0x31, 0x67, 0x53, + 0x0f, 0x3b, 0xb7, 0x83, 0xdf, 0xeb, 0xda, 0xee, 0xb2, 0x86, + 0x0a, 0x3e, 0x62, 0x56, 0xce, 0xfa, 0xa6, 0x92, 0x1e, 0x2a, + 0x76, 0x42, 0x73, 0x47, 0x1b, 0x2f, 0xa3, 0x97, 0xcb, 0xff, + 0xa9, 0x9d, 0xc1, 0xf5, 0x79, 0x4d, 0x11, 0x25, 0x14, 0x20, + 0x7c, 0x48, 0xc4, 0xf0, 0xac, 0x98, 0x81, 0xb5, 0xe9, 0xdd, + 0x51, 0x65, 0x39, 0x0d, 0x3c, 0x08, 0x54, 0x60, 0xec, 0xd8, + 0x84, 0xb0, 0xe6, 0xd2, 0x8e, 0xba, 0x36, 0x02, 0x5e, 0x6a, + 0x5b, 0x6f, 0x33, 0x07, 0x8b, 0xbf, 0xe3, 0xd7, 0x4f, 0x7b, + 0x27, 0x13, 0x9f, 0xab, 0xf7, 0xc3, 0xf2, 0xc6, 0x9a, 0xae, + 0x22, 0x16, 0x4a, 0x7e, 0x28, 0x1c, 0x40, 0x74, 0xf8, 0xcc, + 0x90, 0xa4, 0x95, 0xa1, 0xfd, 0xc9, 0x45, 0x71, 0x2d, 0x19, + 0x1f, 0x2b, 0x77, 0x43, 0xcf, 0xfb, 0xa7, 0x93, 0xa2, 0x96, + 0xca, 0xfe, 0x72, 0x46, 0x1a, 0x2e, 0x78, 0x4c, 0x10, 0x24, + 0xa8, 0x9c, 0xc0, 0xf4, 0xc5, 0xf1, 0xad, 0x99, 0x15, 0x21, + 0x7d, 0x49, 0xd1, 0xe5, 0xb9, 0x8d, 0x01, 0x35, 0x69, 0x5d, + 0x6c, 0x58, 0x04, 0x30, 0xbc, 0x88, 0xd4, 0xe0, 0xb6, 0x82, + 0xde, 0xea, 0x66, 0x52, 0x0e, 0x3a, 0x0b, 0x3f, 0x63, 0x57, + 0xdb, 0xef, 0xb3, 0x87, 0x9e, 0xaa, 0xf6, 0xc2, 0x4e, 0x7a, + 0x26, 0x12, 0x23, 0x17, 0x4b, 0x7f, 0xf3, 0xc7, 0x9b, 0xaf, + 0xf9, 0xcd, 0x91, 0xa5, 0x29, 0x1d, 0x41, 0x75, 0x44, 0x70, + 0x2c, 0x18, 0x94, 0xa0, 0xfc, 0xc8, 0x50, 0x64, 0x38, 0x0c, + 0x80, 0xb4, 0xe8, 0xdc, 0xed, 0xd9, 0x85, 0xb1, 0x3d, 0x09, + 0x55, 0x61, 0x37, 0x03, 0x5f, 0x6b, 0xe7, 0xd3, 0x8f, 0xbb, + 0x8a, 0xbe, 0xe2, 0xd6, 0x5a, 0x6e, 0x32, 0x06, 0x00, 0x35, + 0x6a, 0x5f, 0xd4, 0xe1, 0xbe, 0x8b, 0xb5, 0x80, 0xdf, 0xea, + 0x61, 0x54, 0x0b, 0x3e, 0x77, 0x42, 0x1d, 0x28, 0xa3, 0x96, + 0xc9, 0xfc, 0xc2, 0xf7, 0xa8, 0x9d, 0x16, 0x23, 0x7c, 0x49, + 0xee, 0xdb, 0x84, 0xb1, 0x3a, 0x0f, 0x50, 0x65, 0x5b, 0x6e, + 0x31, 0x04, 0x8f, 0xba, 0xe5, 0xd0, 0x99, 0xac, 0xf3, 0xc6, + 0x4d, 0x78, 0x27, 0x12, 0x2c, 0x19, 0x46, 0x73, 0xf8, 0xcd, + 0x92, 0xa7, 0xc1, 0xf4, 0xab, 0x9e, 0x15, 0x20, 0x7f, 0x4a, + 0x74, 0x41, 0x1e, 0x2b, 0xa0, 0x95, 0xca, 0xff, 0xb6, 0x83, + 0xdc, 0xe9, 0x62, 0x57, 0x08, 0x3d, 0x03, 0x36, 0x69, 0x5c, + 0xd7, 0xe2, 0xbd, 0x88, 0x2f, 0x1a, 0x45, 0x70, 0xfb, 0xce, + 0x91, 0xa4, 0x9a, 0xaf, 0xf0, 0xc5, 0x4e, 0x7b, 0x24, 0x11, + 0x58, 0x6d, 0x32, 0x07, 0x8c, 0xb9, 0xe6, 0xd3, 0xed, 0xd8, + 0x87, 0xb2, 0x39, 0x0c, 0x53, 0x66, 0x9f, 0xaa, 0xf5, 0xc0, + 0x4b, 0x7e, 0x21, 0x14, 0x2a, 0x1f, 0x40, 0x75, 0xfe, 0xcb, + 0x94, 0xa1, 0xe8, 0xdd, 0x82, 0xb7, 0x3c, 0x09, 0x56, 0x63, + 0x5d, 0x68, 0x37, 0x02, 0x89, 0xbc, 0xe3, 0xd6, 0x71, 0x44, + 0x1b, 0x2e, 0xa5, 0x90, 0xcf, 0xfa, 0xc4, 0xf1, 0xae, 0x9b, + 0x10, 0x25, 0x7a, 0x4f, 0x06, 0x33, 0x6c, 0x59, 0xd2, 0xe7, + 0xb8, 0x8d, 0xb3, 0x86, 0xd9, 0xec, 0x67, 0x52, 0x0d, 0x38, + 0x5e, 0x6b, 0x34, 0x01, 0x8a, 0xbf, 0xe0, 0xd5, 0xeb, 0xde, + 0x81, 0xb4, 0x3f, 0x0a, 0x55, 0x60, 0x29, 0x1c, 0x43, 0x76, + 0xfd, 0xc8, 0x97, 0xa2, 0x9c, 0xa9, 0xf6, 0xc3, 0x48, 0x7d, + 0x22, 0x17, 0xb0, 0x85, 0xda, 0xef, 0x64, 0x51, 0x0e, 0x3b, + 0x05, 0x30, 0x6f, 0x5a, 0xd1, 0xe4, 0xbb, 0x8e, 0xc7, 0xf2, + 0xad, 0x98, 0x13, 0x26, 0x79, 0x4c, 0x72, 0x47, 0x18, 0x2d, + 0xa6, 0x93, 0xcc, 0xf9, 0x00, 0x36, 0x6c, 0x5a, 0xd8, 0xee, + 0xb4, 0x82, 0xad, 0x9b, 0xc1, 0xf7, 0x75, 0x43, 0x19, 0x2f, + 0x47, 0x71, 0x2b, 0x1d, 0x9f, 0xa9, 0xf3, 0xc5, 0xea, 0xdc, + 0x86, 0xb0, 0x32, 0x04, 0x5e, 0x68, 0x8e, 0xb8, 0xe2, 0xd4, + 0x56, 0x60, 0x3a, 0x0c, 0x23, 0x15, 0x4f, 0x79, 0xfb, 0xcd, + 0x97, 0xa1, 0xc9, 0xff, 0xa5, 0x93, 0x11, 0x27, 0x7d, 0x4b, + 0x64, 0x52, 0x08, 0x3e, 0xbc, 0x8a, 0xd0, 0xe6, 0x01, 0x37, + 0x6d, 0x5b, 0xd9, 0xef, 0xb5, 0x83, 0xac, 0x9a, 0xc0, 0xf6, + 0x74, 0x42, 0x18, 0x2e, 0x46, 0x70, 0x2a, 0x1c, 0x9e, 0xa8, + 0xf2, 0xc4, 0xeb, 0xdd, 0x87, 0xb1, 0x33, 0x05, 0x5f, 0x69, + 0x8f, 0xb9, 0xe3, 0xd5, 0x57, 0x61, 0x3b, 0x0d, 0x22, 0x14, + 0x4e, 0x78, 0xfa, 0xcc, 0x96, 0xa0, 0xc8, 0xfe, 0xa4, 0x92, + 0x10, 0x26, 0x7c, 0x4a, 0x65, 0x53, 0x09, 0x3f, 0xbd, 0x8b, + 0xd1, 0xe7, 0x02, 0x34, 0x6e, 0x58, 0xda, 0xec, 0xb6, 0x80, + 0xaf, 0x99, 0xc3, 0xf5, 0x77, 0x41, 0x1b, 0x2d, 0x45, 0x73, + 0x29, 0x1f, 0x9d, 0xab, 0xf1, 0xc7, 0xe8, 0xde, 0x84, 0xb2, + 0x30, 0x06, 0x5c, 0x6a, 0x8c, 0xba, 0xe0, 0xd6, 0x54, 0x62, + 0x38, 0x0e, 0x21, 0x17, 0x4d, 0x7b, 0xf9, 0xcf, 0x95, 0xa3, + 0xcb, 0xfd, 0xa7, 0x91, 0x13, 0x25, 0x7f, 0x49, 0x66, 0x50, + 0x0a, 0x3c, 0xbe, 0x88, 0xd2, 0xe4, 0x03, 0x35, 0x6f, 0x59, + 0xdb, 0xed, 0xb7, 0x81, 0xae, 0x98, 0xc2, 0xf4, 0x76, 0x40, + 0x1a, 0x2c, 0x44, 0x72, 0x28, 0x1e, 0x9c, 0xaa, 0xf0, 0xc6, + 0xe9, 0xdf, 0x85, 0xb3, 0x31, 0x07, 0x5d, 0x6b, 0x8d, 0xbb, + 0xe1, 0xd7, 0x55, 0x63, 0x39, 0x0f, 0x20, 0x16, 0x4c, 0x7a, + 0xf8, 0xce, 0x94, 0xa2, 0xca, 0xfc, 0xa6, 0x90, 0x12, 0x24, + 0x7e, 0x48, 0x67, 0x51, 0x0b, 0x3d, 0xbf, 0x89, 0xd3, 0xe5, + 0x00, 0x37, 0x6e, 0x59, 0xdc, 0xeb, 0xb2, 0x85, 0xa5, 0x92, + 0xcb, 0xfc, 0x79, 0x4e, 0x17, 0x20, 0x57, 0x60, 0x39, 0x0e, + 0x8b, 0xbc, 0xe5, 0xd2, 0xf2, 0xc5, 0x9c, 0xab, 0x2e, 0x19, + 0x40, 0x77, 0xae, 0x99, 0xc0, 0xf7, 0x72, 0x45, 0x1c, 0x2b, + 0x0b, 0x3c, 0x65, 0x52, 0xd7, 0xe0, 0xb9, 0x8e, 0xf9, 0xce, + 0x97, 0xa0, 0x25, 0x12, 0x4b, 0x7c, 0x5c, 0x6b, 0x32, 0x05, + 0x80, 0xb7, 0xee, 0xd9, 0x41, 0x76, 0x2f, 0x18, 0x9d, 0xaa, + 0xf3, 0xc4, 0xe4, 0xd3, 0x8a, 0xbd, 0x38, 0x0f, 0x56, 0x61, + 0x16, 0x21, 0x78, 0x4f, 0xca, 0xfd, 0xa4, 0x93, 0xb3, 0x84, + 0xdd, 0xea, 0x6f, 0x58, 0x01, 0x36, 0xef, 0xd8, 0x81, 0xb6, + 0x33, 0x04, 0x5d, 0x6a, 0x4a, 0x7d, 0x24, 0x13, 0x96, 0xa1, + 0xf8, 0xcf, 0xb8, 0x8f, 0xd6, 0xe1, 0x64, 0x53, 0x0a, 0x3d, + 0x1d, 0x2a, 0x73, 0x44, 0xc1, 0xf6, 0xaf, 0x98, 0x82, 0xb5, + 0xec, 0xdb, 0x5e, 0x69, 0x30, 0x07, 0x27, 0x10, 0x49, 0x7e, + 0xfb, 0xcc, 0x95, 0xa2, 0xd5, 0xe2, 0xbb, 0x8c, 0x09, 0x3e, + 0x67, 0x50, 0x70, 0x47, 0x1e, 0x29, 0xac, 0x9b, 0xc2, 0xf5, + 0x2c, 0x1b, 0x42, 0x75, 0xf0, 0xc7, 0x9e, 0xa9, 0x89, 0xbe, + 0xe7, 0xd0, 0x55, 0x62, 0x3b, 0x0c, 0x7b, 0x4c, 0x15, 0x22, + 0xa7, 0x90, 0xc9, 0xfe, 0xde, 0xe9, 0xb0, 0x87, 0x02, 0x35, + 0x6c, 0x5b, 0xc3, 0xf4, 0xad, 0x9a, 0x1f, 0x28, 0x71, 0x46, + 0x66, 0x51, 0x08, 0x3f, 0xba, 0x8d, 0xd4, 0xe3, 0x94, 0xa3, + 0xfa, 0xcd, 0x48, 0x7f, 0x26, 0x11, 0x31, 0x06, 0x5f, 0x68, + 0xed, 0xda, 0x83, 0xb4, 0x6d, 0x5a, 0x03, 0x34, 0xb1, 0x86, + 0xdf, 0xe8, 0xc8, 0xff, 0xa6, 0x91, 0x14, 0x23, 0x7a, 0x4d, + 0x3a, 0x0d, 0x54, 0x63, 0xe6, 0xd1, 0x88, 0xbf, 0x9f, 0xa8, + 0xf1, 0xc6, 0x43, 0x74, 0x2d, 0x1a, 0x00, 0x38, 0x70, 0x48, + 0xe0, 0xd8, 0x90, 0xa8, 0xdd, 0xe5, 0xad, 0x95, 0x3d, 0x05, + 0x4d, 0x75, 0xa7, 0x9f, 0xd7, 0xef, 0x47, 0x7f, 0x37, 0x0f, + 0x7a, 0x42, 0x0a, 0x32, 0x9a, 0xa2, 0xea, 0xd2, 0x53, 0x6b, + 0x23, 0x1b, 0xb3, 0x8b, 0xc3, 0xfb, 0x8e, 0xb6, 0xfe, 0xc6, + 0x6e, 0x56, 0x1e, 0x26, 0xf4, 0xcc, 0x84, 0xbc, 0x14, 0x2c, + 0x64, 0x5c, 0x29, 0x11, 0x59, 0x61, 0xc9, 0xf1, 0xb9, 0x81, + 0xa6, 0x9e, 0xd6, 0xee, 0x46, 0x7e, 0x36, 0x0e, 0x7b, 0x43, + 0x0b, 0x33, 0x9b, 0xa3, 0xeb, 0xd3, 0x01, 0x39, 0x71, 0x49, + 0xe1, 0xd9, 0x91, 0xa9, 0xdc, 0xe4, 0xac, 0x94, 0x3c, 0x04, + 0x4c, 0x74, 0xf5, 0xcd, 0x85, 0xbd, 0x15, 0x2d, 0x65, 0x5d, + 0x28, 0x10, 0x58, 0x60, 0xc8, 0xf0, 0xb8, 0x80, 0x52, 0x6a, + 0x22, 0x1a, 0xb2, 0x8a, 0xc2, 0xfa, 0x8f, 0xb7, 0xff, 0xc7, + 0x6f, 0x57, 0x1f, 0x27, 0x51, 0x69, 0x21, 0x19, 0xb1, 0x89, + 0xc1, 0xf9, 0x8c, 0xb4, 0xfc, 0xc4, 0x6c, 0x54, 0x1c, 0x24, + 0xf6, 0xce, 0x86, 0xbe, 0x16, 0x2e, 0x66, 0x5e, 0x2b, 0x13, + 0x5b, 0x63, 0xcb, 0xf3, 0xbb, 0x83, 0x02, 0x3a, 0x72, 0x4a, + 0xe2, 0xda, 0x92, 0xaa, 0xdf, 0xe7, 0xaf, 0x97, 0x3f, 0x07, + 0x4f, 0x77, 0xa5, 0x9d, 0xd5, 0xed, 0x45, 0x7d, 0x35, 0x0d, + 0x78, 0x40, 0x08, 0x30, 0x98, 0xa0, 0xe8, 0xd0, 0xf7, 0xcf, + 0x87, 0xbf, 0x17, 0x2f, 0x67, 0x5f, 0x2a, 0x12, 0x5a, 0x62, + 0xca, 0xf2, 0xba, 0x82, 0x50, 0x68, 0x20, 0x18, 0xb0, 0x88, + 0xc0, 0xf8, 0x8d, 0xb5, 0xfd, 0xc5, 0x6d, 0x55, 0x1d, 0x25, + 0xa4, 0x9c, 0xd4, 0xec, 0x44, 0x7c, 0x34, 0x0c, 0x79, 0x41, + 0x09, 0x31, 0x99, 0xa1, 0xe9, 0xd1, 0x03, 0x3b, 0x73, 0x4b, + 0xe3, 0xdb, 0x93, 0xab, 0xde, 0xe6, 0xae, 0x96, 0x3e, 0x06, + 0x4e, 0x76, 0x00, 0x39, 0x72, 0x4b, 0xe4, 0xdd, 0x96, 0xaf, + 0xd5, 0xec, 0xa7, 0x9e, 0x31, 0x08, 0x43, 0x7a, 0xb7, 0x8e, + 0xc5, 0xfc, 0x53, 0x6a, 0x21, 0x18, 0x62, 0x5b, 0x10, 0x29, + 0x86, 0xbf, 0xf4, 0xcd, 0x73, 0x4a, 0x01, 0x38, 0x97, 0xae, + 0xe5, 0xdc, 0xa6, 0x9f, 0xd4, 0xed, 0x42, 0x7b, 0x30, 0x09, + 0xc4, 0xfd, 0xb6, 0x8f, 0x20, 0x19, 0x52, 0x6b, 0x11, 0x28, + 0x63, 0x5a, 0xf5, 0xcc, 0x87, 0xbe, 0xe6, 0xdf, 0x94, 0xad, + 0x02, 0x3b, 0x70, 0x49, 0x33, 0x0a, 0x41, 0x78, 0xd7, 0xee, + 0xa5, 0x9c, 0x51, 0x68, 0x23, 0x1a, 0xb5, 0x8c, 0xc7, 0xfe, + 0x84, 0xbd, 0xf6, 0xcf, 0x60, 0x59, 0x12, 0x2b, 0x95, 0xac, + 0xe7, 0xde, 0x71, 0x48, 0x03, 0x3a, 0x40, 0x79, 0x32, 0x0b, + 0xa4, 0x9d, 0xd6, 0xef, 0x22, 0x1b, 0x50, 0x69, 0xc6, 0xff, + 0xb4, 0x8d, 0xf7, 0xce, 0x85, 0xbc, 0x13, 0x2a, 0x61, 0x58, + 0xd1, 0xe8, 0xa3, 0x9a, 0x35, 0x0c, 0x47, 0x7e, 0x04, 0x3d, + 0x76, 0x4f, 0xe0, 0xd9, 0x92, 0xab, 0x66, 0x5f, 0x14, 0x2d, + 0x82, 0xbb, 0xf0, 0xc9, 0xb3, 0x8a, 0xc1, 0xf8, 0x57, 0x6e, + 0x25, 0x1c, 0xa2, 0x9b, 0xd0, 0xe9, 0x46, 0x7f, 0x34, 0x0d, + 0x77, 0x4e, 0x05, 0x3c, 0x93, 0xaa, 0xe1, 0xd8, 0x15, 0x2c, + 0x67, 0x5e, 0xf1, 0xc8, 0x83, 0xba, 0xc0, 0xf9, 0xb2, 0x8b, + 0x24, 0x1d, 0x56, 0x6f, 0x37, 0x0e, 0x45, 0x7c, 0xd3, 0xea, + 0xa1, 0x98, 0xe2, 0xdb, 0x90, 0xa9, 0x06, 0x3f, 0x74, 0x4d, + 0x80, 0xb9, 0xf2, 0xcb, 0x64, 0x5d, 0x16, 0x2f, 0x55, 0x6c, + 0x27, 0x1e, 0xb1, 0x88, 0xc3, 0xfa, 0x44, 0x7d, 0x36, 0x0f, + 0xa0, 0x99, 0xd2, 0xeb, 0x91, 0xa8, 0xe3, 0xda, 0x75, 0x4c, + 0x07, 0x3e, 0xf3, 0xca, 0x81, 0xb8, 0x17, 0x2e, 0x65, 0x5c, + 0x26, 0x1f, 0x54, 0x6d, 0xc2, 0xfb, 0xb0, 0x89, 0x00, 0x3a, + 0x74, 0x4e, 0xe8, 0xd2, 0x9c, 0xa6, 0xcd, 0xf7, 0xb9, 0x83, + 0x25, 0x1f, 0x51, 0x6b, 0x87, 0xbd, 0xf3, 0xc9, 0x6f, 0x55, + 0x1b, 0x21, 0x4a, 0x70, 0x3e, 0x04, 0xa2, 0x98, 0xd6, 0xec, + 0x13, 0x29, 0x67, 0x5d, 0xfb, 0xc1, 0x8f, 0xb5, 0xde, 0xe4, + 0xaa, 0x90, 0x36, 0x0c, 0x42, 0x78, 0x94, 0xae, 0xe0, 0xda, + 0x7c, 0x46, 0x08, 0x32, 0x59, 0x63, 0x2d, 0x17, 0xb1, 0x8b, + 0xc5, 0xff, 0x26, 0x1c, 0x52, 0x68, 0xce, 0xf4, 0xba, 0x80, + 0xeb, 0xd1, 0x9f, 0xa5, 0x03, 0x39, 0x77, 0x4d, 0xa1, 0x9b, + 0xd5, 0xef, 0x49, 0x73, 0x3d, 0x07, 0x6c, 0x56, 0x18, 0x22, + 0x84, 0xbe, 0xf0, 0xca, 0x35, 0x0f, 0x41, 0x7b, 0xdd, 0xe7, + 0xa9, 0x93, 0xf8, 0xc2, 0x8c, 0xb6, 0x10, 0x2a, 0x64, 0x5e, + 0xb2, 0x88, 0xc6, 0xfc, 0x5a, 0x60, 0x2e, 0x14, 0x7f, 0x45, + 0x0b, 0x31, 0x97, 0xad, 0xe3, 0xd9, 0x4c, 0x76, 0x38, 0x02, + 0xa4, 0x9e, 0xd0, 0xea, 0x81, 0xbb, 0xf5, 0xcf, 0x69, 0x53, + 0x1d, 0x27, 0xcb, 0xf1, 0xbf, 0x85, 0x23, 0x19, 0x57, 0x6d, + 0x06, 0x3c, 0x72, 0x48, 0xee, 0xd4, 0x9a, 0xa0, 0x5f, 0x65, + 0x2b, 0x11, 0xb7, 0x8d, 0xc3, 0xf9, 0x92, 0xa8, 0xe6, 0xdc, + 0x7a, 0x40, 0x0e, 0x34, 0xd8, 0xe2, 0xac, 0x96, 0x30, 0x0a, + 0x44, 0x7e, 0x15, 0x2f, 0x61, 0x5b, 0xfd, 0xc7, 0x89, 0xb3, + 0x6a, 0x50, 0x1e, 0x24, 0x82, 0xb8, 0xf6, 0xcc, 0xa7, 0x9d, + 0xd3, 0xe9, 0x4f, 0x75, 0x3b, 0x01, 0xed, 0xd7, 0x99, 0xa3, + 0x05, 0x3f, 0x71, 0x4b, 0x20, 0x1a, 0x54, 0x6e, 0xc8, 0xf2, + 0xbc, 0x86, 0x79, 0x43, 0x0d, 0x37, 0x91, 0xab, 0xe5, 0xdf, + 0xb4, 0x8e, 0xc0, 0xfa, 0x5c, 0x66, 0x28, 0x12, 0xfe, 0xc4, + 0x8a, 0xb0, 0x16, 0x2c, 0x62, 0x58, 0x33, 0x09, 0x47, 0x7d, + 0xdb, 0xe1, 0xaf, 0x95, 0x00, 0x3b, 0x76, 0x4d, 0xec, 0xd7, + 0x9a, 0xa1, 0xc5, 0xfe, 0xb3, 0x88, 0x29, 0x12, 0x5f, 0x64, + 0x97, 0xac, 0xe1, 0xda, 0x7b, 0x40, 0x0d, 0x36, 0x52, 0x69, + 0x24, 0x1f, 0xbe, 0x85, 0xc8, 0xf3, 0x33, 0x08, 0x45, 0x7e, + 0xdf, 0xe4, 0xa9, 0x92, 0xf6, 0xcd, 0x80, 0xbb, 0x1a, 0x21, + 0x6c, 0x57, 0xa4, 0x9f, 0xd2, 0xe9, 0x48, 0x73, 0x3e, 0x05, + 0x61, 0x5a, 0x17, 0x2c, 0x8d, 0xb6, 0xfb, 0xc0, 0x66, 0x5d, + 0x10, 0x2b, 0x8a, 0xb1, 0xfc, 0xc7, 0xa3, 0x98, 0xd5, 0xee, + 0x4f, 0x74, 0x39, 0x02, 0xf1, 0xca, 0x87, 0xbc, 0x1d, 0x26, + 0x6b, 0x50, 0x34, 0x0f, 0x42, 0x79, 0xd8, 0xe3, 0xae, 0x95, + 0x55, 0x6e, 0x23, 0x18, 0xb9, 0x82, 0xcf, 0xf4, 0x90, 0xab, + 0xe6, 0xdd, 0x7c, 0x47, 0x0a, 0x31, 0xc2, 0xf9, 0xb4, 0x8f, + 0x2e, 0x15, 0x58, 0x63, 0x07, 0x3c, 0x71, 0x4a, 0xeb, 0xd0, + 0x9d, 0xa6, 0xcc, 0xf7, 0xba, 0x81, 0x20, 0x1b, 0x56, 0x6d, + 0x09, 0x32, 0x7f, 0x44, 0xe5, 0xde, 0x93, 0xa8, 0x5b, 0x60, + 0x2d, 0x16, 0xb7, 0x8c, 0xc1, 0xfa, 0x9e, 0xa5, 0xe8, 0xd3, + 0x72, 0x49, 0x04, 0x3f, 0xff, 0xc4, 0x89, 0xb2, 0x13, 0x28, + 0x65, 0x5e, 0x3a, 0x01, 0x4c, 0x77, 0xd6, 0xed, 0xa0, 0x9b, + 0x68, 0x53, 0x1e, 0x25, 0x84, 0xbf, 0xf2, 0xc9, 0xad, 0x96, + 0xdb, 0xe0, 0x41, 0x7a, 0x37, 0x0c, 0xaa, 0x91, 0xdc, 0xe7, + 0x46, 0x7d, 0x30, 0x0b, 0x6f, 0x54, 0x19, 0x22, 0x83, 0xb8, + 0xf5, 0xce, 0x3d, 0x06, 0x4b, 0x70, 0xd1, 0xea, 0xa7, 0x9c, + 0xf8, 0xc3, 0x8e, 0xb5, 0x14, 0x2f, 0x62, 0x59, 0x99, 0xa2, + 0xef, 0xd4, 0x75, 0x4e, 0x03, 0x38, 0x5c, 0x67, 0x2a, 0x11, + 0xb0, 0x8b, 0xc6, 0xfd, 0x0e, 0x35, 0x78, 0x43, 0xe2, 0xd9, + 0x94, 0xaf, 0xcb, 0xf0, 0xbd, 0x86, 0x27, 0x1c, 0x51, 0x6a, + 0x00, 0x3c, 0x78, 0x44, 0xf0, 0xcc, 0x88, 0xb4, 0xfd, 0xc1, + 0x85, 0xb9, 0x0d, 0x31, 0x75, 0x49, 0xe7, 0xdb, 0x9f, 0xa3, + 0x17, 0x2b, 0x6f, 0x53, 0x1a, 0x26, 0x62, 0x5e, 0xea, 0xd6, + 0x92, 0xae, 0xd3, 0xef, 0xab, 0x97, 0x23, 0x1f, 0x5b, 0x67, + 0x2e, 0x12, 0x56, 0x6a, 0xde, 0xe2, 0xa6, 0x9a, 0x34, 0x08, + 0x4c, 0x70, 0xc4, 0xf8, 0xbc, 0x80, 0xc9, 0xf5, 0xb1, 0x8d, + 0x39, 0x05, 0x41, 0x7d, 0xbb, 0x87, 0xc3, 0xff, 0x4b, 0x77, + 0x33, 0x0f, 0x46, 0x7a, 0x3e, 0x02, 0xb6, 0x8a, 0xce, 0xf2, + 0x5c, 0x60, 0x24, 0x18, 0xac, 0x90, 0xd4, 0xe8, 0xa1, 0x9d, + 0xd9, 0xe5, 0x51, 0x6d, 0x29, 0x15, 0x68, 0x54, 0x10, 0x2c, + 0x98, 0xa4, 0xe0, 0xdc, 0x95, 0xa9, 0xed, 0xd1, 0x65, 0x59, + 0x1d, 0x21, 0x8f, 0xb3, 0xf7, 0xcb, 0x7f, 0x43, 0x07, 0x3b, + 0x72, 0x4e, 0x0a, 0x36, 0x82, 0xbe, 0xfa, 0xc6, 0x6b, 0x57, + 0x13, 0x2f, 0x9b, 0xa7, 0xe3, 0xdf, 0x96, 0xaa, 0xee, 0xd2, + 0x66, 0x5a, 0x1e, 0x22, 0x8c, 0xb0, 0xf4, 0xc8, 0x7c, 0x40, + 0x04, 0x38, 0x71, 0x4d, 0x09, 0x35, 0x81, 0xbd, 0xf9, 0xc5, + 0xb8, 0x84, 0xc0, 0xfc, 0x48, 0x74, 0x30, 0x0c, 0x45, 0x79, + 0x3d, 0x01, 0xb5, 0x89, 0xcd, 0xf1, 0x5f, 0x63, 0x27, 0x1b, + 0xaf, 0x93, 0xd7, 0xeb, 0xa2, 0x9e, 0xda, 0xe6, 0x52, 0x6e, + 0x2a, 0x16, 0xd0, 0xec, 0xa8, 0x94, 0x20, 0x1c, 0x58, 0x64, + 0x2d, 0x11, 0x55, 0x69, 0xdd, 0xe1, 0xa5, 0x99, 0x37, 0x0b, + 0x4f, 0x73, 0xc7, 0xfb, 0xbf, 0x83, 0xca, 0xf6, 0xb2, 0x8e, + 0x3a, 0x06, 0x42, 0x7e, 0x03, 0x3f, 0x7b, 0x47, 0xf3, 0xcf, + 0x8b, 0xb7, 0xfe, 0xc2, 0x86, 0xba, 0x0e, 0x32, 0x76, 0x4a, + 0xe4, 0xd8, 0x9c, 0xa0, 0x14, 0x28, 0x6c, 0x50, 0x19, 0x25, + 0x61, 0x5d, 0xe9, 0xd5, 0x91, 0xad, 0x00, 0x3d, 0x7a, 0x47, + 0xf4, 0xc9, 0x8e, 0xb3, 0xf5, 0xc8, 0x8f, 0xb2, 0x01, 0x3c, + 0x7b, 0x46, 0xf7, 0xca, 0x8d, 0xb0, 0x03, 0x3e, 0x79, 0x44, + 0x02, 0x3f, 0x78, 0x45, 0xf6, 0xcb, 0x8c, 0xb1, 0xf3, 0xce, + 0x89, 0xb4, 0x07, 0x3a, 0x7d, 0x40, 0x06, 0x3b, 0x7c, 0x41, + 0xf2, 0xcf, 0x88, 0xb5, 0x04, 0x39, 0x7e, 0x43, 0xf0, 0xcd, + 0x8a, 0xb7, 0xf1, 0xcc, 0x8b, 0xb6, 0x05, 0x38, 0x7f, 0x42, + 0xfb, 0xc6, 0x81, 0xbc, 0x0f, 0x32, 0x75, 0x48, 0x0e, 0x33, + 0x74, 0x49, 0xfa, 0xc7, 0x80, 0xbd, 0x0c, 0x31, 0x76, 0x4b, + 0xf8, 0xc5, 0x82, 0xbf, 0xf9, 0xc4, 0x83, 0xbe, 0x0d, 0x30, + 0x77, 0x4a, 0x08, 0x35, 0x72, 0x4f, 0xfc, 0xc1, 0x86, 0xbb, + 0xfd, 0xc0, 0x87, 0xba, 0x09, 0x34, 0x73, 0x4e, 0xff, 0xc2, + 0x85, 0xb8, 0x0b, 0x36, 0x71, 0x4c, 0x0a, 0x37, 0x70, 0x4d, + 0xfe, 0xc3, 0x84, 0xb9, 0xeb, 0xd6, 0x91, 0xac, 0x1f, 0x22, + 0x65, 0x58, 0x1e, 0x23, 0x64, 0x59, 0xea, 0xd7, 0x90, 0xad, + 0x1c, 0x21, 0x66, 0x5b, 0xe8, 0xd5, 0x92, 0xaf, 0xe9, 0xd4, + 0x93, 0xae, 0x1d, 0x20, 0x67, 0x5a, 0x18, 0x25, 0x62, 0x5f, + 0xec, 0xd1, 0x96, 0xab, 0xed, 0xd0, 0x97, 0xaa, 0x19, 0x24, + 0x63, 0x5e, 0xef, 0xd2, 0x95, 0xa8, 0x1b, 0x26, 0x61, 0x5c, + 0x1a, 0x27, 0x60, 0x5d, 0xee, 0xd3, 0x94, 0xa9, 0x10, 0x2d, + 0x6a, 0x57, 0xe4, 0xd9, 0x9e, 0xa3, 0xe5, 0xd8, 0x9f, 0xa2, + 0x11, 0x2c, 0x6b, 0x56, 0xe7, 0xda, 0x9d, 0xa0, 0x13, 0x2e, + 0x69, 0x54, 0x12, 0x2f, 0x68, 0x55, 0xe6, 0xdb, 0x9c, 0xa1, + 0xe3, 0xde, 0x99, 0xa4, 0x17, 0x2a, 0x6d, 0x50, 0x16, 0x2b, + 0x6c, 0x51, 0xe2, 0xdf, 0x98, 0xa5, 0x14, 0x29, 0x6e, 0x53, + 0xe0, 0xdd, 0x9a, 0xa7, 0xe1, 0xdc, 0x9b, 0xa6, 0x15, 0x28, + 0x6f, 0x52, 0x00, 0x3e, 0x7c, 0x42, 0xf8, 0xc6, 0x84, 0xba, + 0xed, 0xd3, 0x91, 0xaf, 0x15, 0x2b, 0x69, 0x57, 0xc7, 0xf9, + 0xbb, 0x85, 0x3f, 0x01, 0x43, 0x7d, 0x2a, 0x14, 0x56, 0x68, + 0xd2, 0xec, 0xae, 0x90, 0x93, 0xad, 0xef, 0xd1, 0x6b, 0x55, + 0x17, 0x29, 0x7e, 0x40, 0x02, 0x3c, 0x86, 0xb8, 0xfa, 0xc4, + 0x54, 0x6a, 0x28, 0x16, 0xac, 0x92, 0xd0, 0xee, 0xb9, 0x87, + 0xc5, 0xfb, 0x41, 0x7f, 0x3d, 0x03, 0x3b, 0x05, 0x47, 0x79, + 0xc3, 0xfd, 0xbf, 0x81, 0xd6, 0xe8, 0xaa, 0x94, 0x2e, 0x10, + 0x52, 0x6c, 0xfc, 0xc2, 0x80, 0xbe, 0x04, 0x3a, 0x78, 0x46, + 0x11, 0x2f, 0x6d, 0x53, 0xe9, 0xd7, 0x95, 0xab, 0xa8, 0x96, + 0xd4, 0xea, 0x50, 0x6e, 0x2c, 0x12, 0x45, 0x7b, 0x39, 0x07, + 0xbd, 0x83, 0xc1, 0xff, 0x6f, 0x51, 0x13, 0x2d, 0x97, 0xa9, + 0xeb, 0xd5, 0x82, 0xbc, 0xfe, 0xc0, 0x7a, 0x44, 0x06, 0x38, + 0x76, 0x48, 0x0a, 0x34, 0x8e, 0xb0, 0xf2, 0xcc, 0x9b, 0xa5, + 0xe7, 0xd9, 0x63, 0x5d, 0x1f, 0x21, 0xb1, 0x8f, 0xcd, 0xf3, + 0x49, 0x77, 0x35, 0x0b, 0x5c, 0x62, 0x20, 0x1e, 0xa4, 0x9a, + 0xd8, 0xe6, 0xe5, 0xdb, 0x99, 0xa7, 0x1d, 0x23, 0x61, 0x5f, + 0x08, 0x36, 0x74, 0x4a, 0xf0, 0xce, 0x8c, 0xb2, 0x22, 0x1c, + 0x5e, 0x60, 0xda, 0xe4, 0xa6, 0x98, 0xcf, 0xf1, 0xb3, 0x8d, + 0x37, 0x09, 0x4b, 0x75, 0x4d, 0x73, 0x31, 0x0f, 0xb5, 0x8b, + 0xc9, 0xf7, 0xa0, 0x9e, 0xdc, 0xe2, 0x58, 0x66, 0x24, 0x1a, + 0x8a, 0xb4, 0xf6, 0xc8, 0x72, 0x4c, 0x0e, 0x30, 0x67, 0x59, + 0x1b, 0x25, 0x9f, 0xa1, 0xe3, 0xdd, 0xde, 0xe0, 0xa2, 0x9c, + 0x26, 0x18, 0x5a, 0x64, 0x33, 0x0d, 0x4f, 0x71, 0xcb, 0xf5, + 0xb7, 0x89, 0x19, 0x27, 0x65, 0x5b, 0xe1, 0xdf, 0x9d, 0xa3, + 0xf4, 0xca, 0x88, 0xb6, 0x0c, 0x32, 0x70, 0x4e, 0x00, 0x3f, + 0x7e, 0x41, 0xfc, 0xc3, 0x82, 0xbd, 0xe5, 0xda, 0x9b, 0xa4, + 0x19, 0x26, 0x67, 0x58, 0xd7, 0xe8, 0xa9, 0x96, 0x2b, 0x14, + 0x55, 0x6a, 0x32, 0x0d, 0x4c, 0x73, 0xce, 0xf1, 0xb0, 0x8f, + 0xb3, 0x8c, 0xcd, 0xf2, 0x4f, 0x70, 0x31, 0x0e, 0x56, 0x69, + 0x28, 0x17, 0xaa, 0x95, 0xd4, 0xeb, 0x64, 0x5b, 0x1a, 0x25, + 0x98, 0xa7, 0xe6, 0xd9, 0x81, 0xbe, 0xff, 0xc0, 0x7d, 0x42, + 0x03, 0x3c, 0x7b, 0x44, 0x05, 0x3a, 0x87, 0xb8, 0xf9, 0xc6, + 0x9e, 0xa1, 0xe0, 0xdf, 0x62, 0x5d, 0x1c, 0x23, 0xac, 0x93, + 0xd2, 0xed, 0x50, 0x6f, 0x2e, 0x11, 0x49, 0x76, 0x37, 0x08, + 0xb5, 0x8a, 0xcb, 0xf4, 0xc8, 0xf7, 0xb6, 0x89, 0x34, 0x0b, + 0x4a, 0x75, 0x2d, 0x12, 0x53, 0x6c, 0xd1, 0xee, 0xaf, 0x90, + 0x1f, 0x20, 0x61, 0x5e, 0xe3, 0xdc, 0x9d, 0xa2, 0xfa, 0xc5, + 0x84, 0xbb, 0x06, 0x39, 0x78, 0x47, 0xf6, 0xc9, 0x88, 0xb7, + 0x0a, 0x35, 0x74, 0x4b, 0x13, 0x2c, 0x6d, 0x52, 0xef, 0xd0, + 0x91, 0xae, 0x21, 0x1e, 0x5f, 0x60, 0xdd, 0xe2, 0xa3, 0x9c, + 0xc4, 0xfb, 0xba, 0x85, 0x38, 0x07, 0x46, 0x79, 0x45, 0x7a, + 0x3b, 0x04, 0xb9, 0x86, 0xc7, 0xf8, 0xa0, 0x9f, 0xde, 0xe1, + 0x5c, 0x63, 0x22, 0x1d, 0x92, 0xad, 0xec, 0xd3, 0x6e, 0x51, + 0x10, 0x2f, 0x77, 0x48, 0x09, 0x36, 0x8b, 0xb4, 0xf5, 0xca, + 0x8d, 0xb2, 0xf3, 0xcc, 0x71, 0x4e, 0x0f, 0x30, 0x68, 0x57, + 0x16, 0x29, 0x94, 0xab, 0xea, 0xd5, 0x5a, 0x65, 0x24, 0x1b, + 0xa6, 0x99, 0xd8, 0xe7, 0xbf, 0x80, 0xc1, 0xfe, 0x43, 0x7c, + 0x3d, 0x02, 0x3e, 0x01, 0x40, 0x7f, 0xc2, 0xfd, 0xbc, 0x83, + 0xdb, 0xe4, 0xa5, 0x9a, 0x27, 0x18, 0x59, 0x66, 0xe9, 0xd6, + 0x97, 0xa8, 0x15, 0x2a, 0x6b, 0x54, 0x0c, 0x33, 0x72, 0x4d, + 0xf0, 0xcf, 0x8e, 0xb1, 0x00, 0x40, 0x80, 0xc0, 0x1d, 0x5d, + 0x9d, 0xdd, 0x3a, 0x7a, 0xba, 0xfa, 0x27, 0x67, 0xa7, 0xe7, + 0x74, 0x34, 0xf4, 0xb4, 0x69, 0x29, 0xe9, 0xa9, 0x4e, 0x0e, + 0xce, 0x8e, 0x53, 0x13, 0xd3, 0x93, 0xe8, 0xa8, 0x68, 0x28, + 0xf5, 0xb5, 0x75, 0x35, 0xd2, 0x92, 0x52, 0x12, 0xcf, 0x8f, + 0x4f, 0x0f, 0x9c, 0xdc, 0x1c, 0x5c, 0x81, 0xc1, 0x01, 0x41, + 0xa6, 0xe6, 0x26, 0x66, 0xbb, 0xfb, 0x3b, 0x7b, 0xcd, 0x8d, + 0x4d, 0x0d, 0xd0, 0x90, 0x50, 0x10, 0xf7, 0xb7, 0x77, 0x37, + 0xea, 0xaa, 0x6a, 0x2a, 0xb9, 0xf9, 0x39, 0x79, 0xa4, 0xe4, + 0x24, 0x64, 0x83, 0xc3, 0x03, 0x43, 0x9e, 0xde, 0x1e, 0x5e, + 0x25, 0x65, 0xa5, 0xe5, 0x38, 0x78, 0xb8, 0xf8, 0x1f, 0x5f, + 0x9f, 0xdf, 0x02, 0x42, 0x82, 0xc2, 0x51, 0x11, 0xd1, 0x91, + 0x4c, 0x0c, 0xcc, 0x8c, 0x6b, 0x2b, 0xeb, 0xab, 0x76, 0x36, + 0xf6, 0xb6, 0x87, 0xc7, 0x07, 0x47, 0x9a, 0xda, 0x1a, 0x5a, + 0xbd, 0xfd, 0x3d, 0x7d, 0xa0, 0xe0, 0x20, 0x60, 0xf3, 0xb3, + 0x73, 0x33, 0xee, 0xae, 0x6e, 0x2e, 0xc9, 0x89, 0x49, 0x09, + 0xd4, 0x94, 0x54, 0x14, 0x6f, 0x2f, 0xef, 0xaf, 0x72, 0x32, + 0xf2, 0xb2, 0x55, 0x15, 0xd5, 0x95, 0x48, 0x08, 0xc8, 0x88, + 0x1b, 0x5b, 0x9b, 0xdb, 0x06, 0x46, 0x86, 0xc6, 0x21, 0x61, + 0xa1, 0xe1, 0x3c, 0x7c, 0xbc, 0xfc, 0x4a, 0x0a, 0xca, 0x8a, + 0x57, 0x17, 0xd7, 0x97, 0x70, 0x30, 0xf0, 0xb0, 0x6d, 0x2d, + 0xed, 0xad, 0x3e, 0x7e, 0xbe, 0xfe, 0x23, 0x63, 0xa3, 0xe3, + 0x04, 0x44, 0x84, 0xc4, 0x19, 0x59, 0x99, 0xd9, 0xa2, 0xe2, + 0x22, 0x62, 0xbf, 0xff, 0x3f, 0x7f, 0x98, 0xd8, 0x18, 0x58, + 0x85, 0xc5, 0x05, 0x45, 0xd6, 0x96, 0x56, 0x16, 0xcb, 0x8b, + 0x4b, 0x0b, 0xec, 0xac, 0x6c, 0x2c, 0xf1, 0xb1, 0x71, 0x31, + 0x00, 0x41, 0x82, 0xc3, 0x19, 0x58, 0x9b, 0xda, 0x32, 0x73, + 0xb0, 0xf1, 0x2b, 0x6a, 0xa9, 0xe8, 0x64, 0x25, 0xe6, 0xa7, + 0x7d, 0x3c, 0xff, 0xbe, 0x56, 0x17, 0xd4, 0x95, 0x4f, 0x0e, + 0xcd, 0x8c, 0xc8, 0x89, 0x4a, 0x0b, 0xd1, 0x90, 0x53, 0x12, + 0xfa, 0xbb, 0x78, 0x39, 0xe3, 0xa2, 0x61, 0x20, 0xac, 0xed, + 0x2e, 0x6f, 0xb5, 0xf4, 0x37, 0x76, 0x9e, 0xdf, 0x1c, 0x5d, + 0x87, 0xc6, 0x05, 0x44, 0x8d, 0xcc, 0x0f, 0x4e, 0x94, 0xd5, + 0x16, 0x57, 0xbf, 0xfe, 0x3d, 0x7c, 0xa6, 0xe7, 0x24, 0x65, + 0xe9, 0xa8, 0x6b, 0x2a, 0xf0, 0xb1, 0x72, 0x33, 0xdb, 0x9a, + 0x59, 0x18, 0xc2, 0x83, 0x40, 0x01, 0x45, 0x04, 0xc7, 0x86, + 0x5c, 0x1d, 0xde, 0x9f, 0x77, 0x36, 0xf5, 0xb4, 0x6e, 0x2f, + 0xec, 0xad, 0x21, 0x60, 0xa3, 0xe2, 0x38, 0x79, 0xba, 0xfb, + 0x13, 0x52, 0x91, 0xd0, 0x0a, 0x4b, 0x88, 0xc9, 0x07, 0x46, + 0x85, 0xc4, 0x1e, 0x5f, 0x9c, 0xdd, 0x35, 0x74, 0xb7, 0xf6, + 0x2c, 0x6d, 0xae, 0xef, 0x63, 0x22, 0xe1, 0xa0, 0x7a, 0x3b, + 0xf8, 0xb9, 0x51, 0x10, 0xd3, 0x92, 0x48, 0x09, 0xca, 0x8b, + 0xcf, 0x8e, 0x4d, 0x0c, 0xd6, 0x97, 0x54, 0x15, 0xfd, 0xbc, + 0x7f, 0x3e, 0xe4, 0xa5, 0x66, 0x27, 0xab, 0xea, 0x29, 0x68, + 0xb2, 0xf3, 0x30, 0x71, 0x99, 0xd8, 0x1b, 0x5a, 0x80, 0xc1, + 0x02, 0x43, 0x8a, 0xcb, 0x08, 0x49, 0x93, 0xd2, 0x11, 0x50, + 0xb8, 0xf9, 0x3a, 0x7b, 0xa1, 0xe0, 0x23, 0x62, 0xee, 0xaf, + 0x6c, 0x2d, 0xf7, 0xb6, 0x75, 0x34, 0xdc, 0x9d, 0x5e, 0x1f, + 0xc5, 0x84, 0x47, 0x06, 0x42, 0x03, 0xc0, 0x81, 0x5b, 0x1a, + 0xd9, 0x98, 0x70, 0x31, 0xf2, 0xb3, 0x69, 0x28, 0xeb, 0xaa, + 0x26, 0x67, 0xa4, 0xe5, 0x3f, 0x7e, 0xbd, 0xfc, 0x14, 0x55, + 0x96, 0xd7, 0x0d, 0x4c, 0x8f, 0xce, 0x00, 0x42, 0x84, 0xc6, + 0x15, 0x57, 0x91, 0xd3, 0x2a, 0x68, 0xae, 0xec, 0x3f, 0x7d, + 0xbb, 0xf9, 0x54, 0x16, 0xd0, 0x92, 0x41, 0x03, 0xc5, 0x87, + 0x7e, 0x3c, 0xfa, 0xb8, 0x6b, 0x29, 0xef, 0xad, 0xa8, 0xea, + 0x2c, 0x6e, 0xbd, 0xff, 0x39, 0x7b, 0x82, 0xc0, 0x06, 0x44, + 0x97, 0xd5, 0x13, 0x51, 0xfc, 0xbe, 0x78, 0x3a, 0xe9, 0xab, + 0x6d, 0x2f, 0xd6, 0x94, 0x52, 0x10, 0xc3, 0x81, 0x47, 0x05, + 0x4d, 0x0f, 0xc9, 0x8b, 0x58, 0x1a, 0xdc, 0x9e, 0x67, 0x25, + 0xe3, 0xa1, 0x72, 0x30, 0xf6, 0xb4, 0x19, 0x5b, 0x9d, 0xdf, + 0x0c, 0x4e, 0x88, 0xca, 0x33, 0x71, 0xb7, 0xf5, 0x26, 0x64, + 0xa2, 0xe0, 0xe5, 0xa7, 0x61, 0x23, 0xf0, 0xb2, 0x74, 0x36, + 0xcf, 0x8d, 0x4b, 0x09, 0xda, 0x98, 0x5e, 0x1c, 0xb1, 0xf3, + 0x35, 0x77, 0xa4, 0xe6, 0x20, 0x62, 0x9b, 0xd9, 0x1f, 0x5d, + 0x8e, 0xcc, 0x0a, 0x48, 0x9a, 0xd8, 0x1e, 0x5c, 0x8f, 0xcd, + 0x0b, 0x49, 0xb0, 0xf2, 0x34, 0x76, 0xa5, 0xe7, 0x21, 0x63, + 0xce, 0x8c, 0x4a, 0x08, 0xdb, 0x99, 0x5f, 0x1d, 0xe4, 0xa6, + 0x60, 0x22, 0xf1, 0xb3, 0x75, 0x37, 0x32, 0x70, 0xb6, 0xf4, + 0x27, 0x65, 0xa3, 0xe1, 0x18, 0x5a, 0x9c, 0xde, 0x0d, 0x4f, + 0x89, 0xcb, 0x66, 0x24, 0xe2, 0xa0, 0x73, 0x31, 0xf7, 0xb5, + 0x4c, 0x0e, 0xc8, 0x8a, 0x59, 0x1b, 0xdd, 0x9f, 0xd7, 0x95, + 0x53, 0x11, 0xc2, 0x80, 0x46, 0x04, 0xfd, 0xbf, 0x79, 0x3b, + 0xe8, 0xaa, 0x6c, 0x2e, 0x83, 0xc1, 0x07, 0x45, 0x96, 0xd4, + 0x12, 0x50, 0xa9, 0xeb, 0x2d, 0x6f, 0xbc, 0xfe, 0x38, 0x7a, + 0x7f, 0x3d, 0xfb, 0xb9, 0x6a, 0x28, 0xee, 0xac, 0x55, 0x17, + 0xd1, 0x93, 0x40, 0x02, 0xc4, 0x86, 0x2b, 0x69, 0xaf, 0xed, + 0x3e, 0x7c, 0xba, 0xf8, 0x01, 0x43, 0x85, 0xc7, 0x14, 0x56, + 0x90, 0xd2, 0x00, 0x43, 0x86, 0xc5, 0x11, 0x52, 0x97, 0xd4, + 0x22, 0x61, 0xa4, 0xe7, 0x33, 0x70, 0xb5, 0xf6, 0x44, 0x07, + 0xc2, 0x81, 0x55, 0x16, 0xd3, 0x90, 0x66, 0x25, 0xe0, 0xa3, + 0x77, 0x34, 0xf1, 0xb2, 0x88, 0xcb, 0x0e, 0x4d, 0x99, 0xda, + 0x1f, 0x5c, 0xaa, 0xe9, 0x2c, 0x6f, 0xbb, 0xf8, 0x3d, 0x7e, + 0xcc, 0x8f, 0x4a, 0x09, 0xdd, 0x9e, 0x5b, 0x18, 0xee, 0xad, + 0x68, 0x2b, 0xff, 0xbc, 0x79, 0x3a, 0x0d, 0x4e, 0x8b, 0xc8, + 0x1c, 0x5f, 0x9a, 0xd9, 0x2f, 0x6c, 0xa9, 0xea, 0x3e, 0x7d, + 0xb8, 0xfb, 0x49, 0x0a, 0xcf, 0x8c, 0x58, 0x1b, 0xde, 0x9d, + 0x6b, 0x28, 0xed, 0xae, 0x7a, 0x39, 0xfc, 0xbf, 0x85, 0xc6, + 0x03, 0x40, 0x94, 0xd7, 0x12, 0x51, 0xa7, 0xe4, 0x21, 0x62, + 0xb6, 0xf5, 0x30, 0x73, 0xc1, 0x82, 0x47, 0x04, 0xd0, 0x93, + 0x56, 0x15, 0xe3, 0xa0, 0x65, 0x26, 0xf2, 0xb1, 0x74, 0x37, + 0x1a, 0x59, 0x9c, 0xdf, 0x0b, 0x48, 0x8d, 0xce, 0x38, 0x7b, + 0xbe, 0xfd, 0x29, 0x6a, 0xaf, 0xec, 0x5e, 0x1d, 0xd8, 0x9b, + 0x4f, 0x0c, 0xc9, 0x8a, 0x7c, 0x3f, 0xfa, 0xb9, 0x6d, 0x2e, + 0xeb, 0xa8, 0x92, 0xd1, 0x14, 0x57, 0x83, 0xc0, 0x05, 0x46, + 0xb0, 0xf3, 0x36, 0x75, 0xa1, 0xe2, 0x27, 0x64, 0xd6, 0x95, + 0x50, 0x13, 0xc7, 0x84, 0x41, 0x02, 0xf4, 0xb7, 0x72, 0x31, + 0xe5, 0xa6, 0x63, 0x20, 0x17, 0x54, 0x91, 0xd2, 0x06, 0x45, + 0x80, 0xc3, 0x35, 0x76, 0xb3, 0xf0, 0x24, 0x67, 0xa2, 0xe1, + 0x53, 0x10, 0xd5, 0x96, 0x42, 0x01, 0xc4, 0x87, 0x71, 0x32, + 0xf7, 0xb4, 0x60, 0x23, 0xe6, 0xa5, 0x9f, 0xdc, 0x19, 0x5a, + 0x8e, 0xcd, 0x08, 0x4b, 0xbd, 0xfe, 0x3b, 0x78, 0xac, 0xef, + 0x2a, 0x69, 0xdb, 0x98, 0x5d, 0x1e, 0xca, 0x89, 0x4c, 0x0f, + 0xf9, 0xba, 0x7f, 0x3c, 0xe8, 0xab, 0x6e, 0x2d, 0x00, 0x44, + 0x88, 0xcc, 0x0d, 0x49, 0x85, 0xc1, 0x1a, 0x5e, 0x92, 0xd6, + 0x17, 0x53, 0x9f, 0xdb, 0x34, 0x70, 0xbc, 0xf8, 0x39, 0x7d, + 0xb1, 0xf5, 0x2e, 0x6a, 0xa6, 0xe2, 0x23, 0x67, 0xab, 0xef, + 0x68, 0x2c, 0xe0, 0xa4, 0x65, 0x21, 0xed, 0xa9, 0x72, 0x36, + 0xfa, 0xbe, 0x7f, 0x3b, 0xf7, 0xb3, 0x5c, 0x18, 0xd4, 0x90, + 0x51, 0x15, 0xd9, 0x9d, 0x46, 0x02, 0xce, 0x8a, 0x4b, 0x0f, + 0xc3, 0x87, 0xd0, 0x94, 0x58, 0x1c, 0xdd, 0x99, 0x55, 0x11, + 0xca, 0x8e, 0x42, 0x06, 0xc7, 0x83, 0x4f, 0x0b, 0xe4, 0xa0, + 0x6c, 0x28, 0xe9, 0xad, 0x61, 0x25, 0xfe, 0xba, 0x76, 0x32, + 0xf3, 0xb7, 0x7b, 0x3f, 0xb8, 0xfc, 0x30, 0x74, 0xb5, 0xf1, + 0x3d, 0x79, 0xa2, 0xe6, 0x2a, 0x6e, 0xaf, 0xeb, 0x27, 0x63, + 0x8c, 0xc8, 0x04, 0x40, 0x81, 0xc5, 0x09, 0x4d, 0x96, 0xd2, + 0x1e, 0x5a, 0x9b, 0xdf, 0x13, 0x57, 0xbd, 0xf9, 0x35, 0x71, + 0xb0, 0xf4, 0x38, 0x7c, 0xa7, 0xe3, 0x2f, 0x6b, 0xaa, 0xee, + 0x22, 0x66, 0x89, 0xcd, 0x01, 0x45, 0x84, 0xc0, 0x0c, 0x48, + 0x93, 0xd7, 0x1b, 0x5f, 0x9e, 0xda, 0x16, 0x52, 0xd5, 0x91, + 0x5d, 0x19, 0xd8, 0x9c, 0x50, 0x14, 0xcf, 0x8b, 0x47, 0x03, + 0xc2, 0x86, 0x4a, 0x0e, 0xe1, 0xa5, 0x69, 0x2d, 0xec, 0xa8, + 0x64, 0x20, 0xfb, 0xbf, 0x73, 0x37, 0xf6, 0xb2, 0x7e, 0x3a, + 0x6d, 0x29, 0xe5, 0xa1, 0x60, 0x24, 0xe8, 0xac, 0x77, 0x33, + 0xff, 0xbb, 0x7a, 0x3e, 0xf2, 0xb6, 0x59, 0x1d, 0xd1, 0x95, + 0x54, 0x10, 0xdc, 0x98, 0x43, 0x07, 0xcb, 0x8f, 0x4e, 0x0a, + 0xc6, 0x82, 0x05, 0x41, 0x8d, 0xc9, 0x08, 0x4c, 0x80, 0xc4, + 0x1f, 0x5b, 0x97, 0xd3, 0x12, 0x56, 0x9a, 0xde, 0x31, 0x75, + 0xb9, 0xfd, 0x3c, 0x78, 0xb4, 0xf0, 0x2b, 0x6f, 0xa3, 0xe7, + 0x26, 0x62, 0xae, 0xea, 0x00, 0x45, 0x8a, 0xcf, 0x09, 0x4c, + 0x83, 0xc6, 0x12, 0x57, 0x98, 0xdd, 0x1b, 0x5e, 0x91, 0xd4, + 0x24, 0x61, 0xae, 0xeb, 0x2d, 0x68, 0xa7, 0xe2, 0x36, 0x73, + 0xbc, 0xf9, 0x3f, 0x7a, 0xb5, 0xf0, 0x48, 0x0d, 0xc2, 0x87, + 0x41, 0x04, 0xcb, 0x8e, 0x5a, 0x1f, 0xd0, 0x95, 0x53, 0x16, + 0xd9, 0x9c, 0x6c, 0x29, 0xe6, 0xa3, 0x65, 0x20, 0xef, 0xaa, + 0x7e, 0x3b, 0xf4, 0xb1, 0x77, 0x32, 0xfd, 0xb8, 0x90, 0xd5, + 0x1a, 0x5f, 0x99, 0xdc, 0x13, 0x56, 0x82, 0xc7, 0x08, 0x4d, + 0x8b, 0xce, 0x01, 0x44, 0xb4, 0xf1, 0x3e, 0x7b, 0xbd, 0xf8, + 0x37, 0x72, 0xa6, 0xe3, 0x2c, 0x69, 0xaf, 0xea, 0x25, 0x60, + 0xd8, 0x9d, 0x52, 0x17, 0xd1, 0x94, 0x5b, 0x1e, 0xca, 0x8f, + 0x40, 0x05, 0xc3, 0x86, 0x49, 0x0c, 0xfc, 0xb9, 0x76, 0x33, + 0xf5, 0xb0, 0x7f, 0x3a, 0xee, 0xab, 0x64, 0x21, 0xe7, 0xa2, + 0x6d, 0x28, 0x3d, 0x78, 0xb7, 0xf2, 0x34, 0x71, 0xbe, 0xfb, + 0x2f, 0x6a, 0xa5, 0xe0, 0x26, 0x63, 0xac, 0xe9, 0x19, 0x5c, + 0x93, 0xd6, 0x10, 0x55, 0x9a, 0xdf, 0x0b, 0x4e, 0x81, 0xc4, + 0x02, 0x47, 0x88, 0xcd, 0x75, 0x30, 0xff, 0xba, 0x7c, 0x39, + 0xf6, 0xb3, 0x67, 0x22, 0xed, 0xa8, 0x6e, 0x2b, 0xe4, 0xa1, + 0x51, 0x14, 0xdb, 0x9e, 0x58, 0x1d, 0xd2, 0x97, 0x43, 0x06, + 0xc9, 0x8c, 0x4a, 0x0f, 0xc0, 0x85, 0xad, 0xe8, 0x27, 0x62, + 0xa4, 0xe1, 0x2e, 0x6b, 0xbf, 0xfa, 0x35, 0x70, 0xb6, 0xf3, + 0x3c, 0x79, 0x89, 0xcc, 0x03, 0x46, 0x80, 0xc5, 0x0a, 0x4f, + 0x9b, 0xde, 0x11, 0x54, 0x92, 0xd7, 0x18, 0x5d, 0xe5, 0xa0, + 0x6f, 0x2a, 0xec, 0xa9, 0x66, 0x23, 0xf7, 0xb2, 0x7d, 0x38, + 0xfe, 0xbb, 0x74, 0x31, 0xc1, 0x84, 0x4b, 0x0e, 0xc8, 0x8d, + 0x42, 0x07, 0xd3, 0x96, 0x59, 0x1c, 0xda, 0x9f, 0x50, 0x15, + 0x00, 0x46, 0x8c, 0xca, 0x05, 0x43, 0x89, 0xcf, 0x0a, 0x4c, + 0x86, 0xc0, 0x0f, 0x49, 0x83, 0xc5, 0x14, 0x52, 0x98, 0xde, + 0x11, 0x57, 0x9d, 0xdb, 0x1e, 0x58, 0x92, 0xd4, 0x1b, 0x5d, + 0x97, 0xd1, 0x28, 0x6e, 0xa4, 0xe2, 0x2d, 0x6b, 0xa1, 0xe7, + 0x22, 0x64, 0xae, 0xe8, 0x27, 0x61, 0xab, 0xed, 0x3c, 0x7a, + 0xb0, 0xf6, 0x39, 0x7f, 0xb5, 0xf3, 0x36, 0x70, 0xba, 0xfc, + 0x33, 0x75, 0xbf, 0xf9, 0x50, 0x16, 0xdc, 0x9a, 0x55, 0x13, + 0xd9, 0x9f, 0x5a, 0x1c, 0xd6, 0x90, 0x5f, 0x19, 0xd3, 0x95, + 0x44, 0x02, 0xc8, 0x8e, 0x41, 0x07, 0xcd, 0x8b, 0x4e, 0x08, + 0xc2, 0x84, 0x4b, 0x0d, 0xc7, 0x81, 0x78, 0x3e, 0xf4, 0xb2, + 0x7d, 0x3b, 0xf1, 0xb7, 0x72, 0x34, 0xfe, 0xb8, 0x77, 0x31, + 0xfb, 0xbd, 0x6c, 0x2a, 0xe0, 0xa6, 0x69, 0x2f, 0xe5, 0xa3, + 0x66, 0x20, 0xea, 0xac, 0x63, 0x25, 0xef, 0xa9, 0xa0, 0xe6, + 0x2c, 0x6a, 0xa5, 0xe3, 0x29, 0x6f, 0xaa, 0xec, 0x26, 0x60, + 0xaf, 0xe9, 0x23, 0x65, 0xb4, 0xf2, 0x38, 0x7e, 0xb1, 0xf7, + 0x3d, 0x7b, 0xbe, 0xf8, 0x32, 0x74, 0xbb, 0xfd, 0x37, 0x71, + 0x88, 0xce, 0x04, 0x42, 0x8d, 0xcb, 0x01, 0x47, 0x82, 0xc4, + 0x0e, 0x48, 0x87, 0xc1, 0x0b, 0x4d, 0x9c, 0xda, 0x10, 0x56, + 0x99, 0xdf, 0x15, 0x53, 0x96, 0xd0, 0x1a, 0x5c, 0x93, 0xd5, + 0x1f, 0x59, 0xf0, 0xb6, 0x7c, 0x3a, 0xf5, 0xb3, 0x79, 0x3f, + 0xfa, 0xbc, 0x76, 0x30, 0xff, 0xb9, 0x73, 0x35, 0xe4, 0xa2, + 0x68, 0x2e, 0xe1, 0xa7, 0x6d, 0x2b, 0xee, 0xa8, 0x62, 0x24, + 0xeb, 0xad, 0x67, 0x21, 0xd8, 0x9e, 0x54, 0x12, 0xdd, 0x9b, + 0x51, 0x17, 0xd2, 0x94, 0x5e, 0x18, 0xd7, 0x91, 0x5b, 0x1d, + 0xcc, 0x8a, 0x40, 0x06, 0xc9, 0x8f, 0x45, 0x03, 0xc6, 0x80, + 0x4a, 0x0c, 0xc3, 0x85, 0x4f, 0x09, 0x00, 0x47, 0x8e, 0xc9, + 0x01, 0x46, 0x8f, 0xc8, 0x02, 0x45, 0x8c, 0xcb, 0x03, 0x44, + 0x8d, 0xca, 0x04, 0x43, 0x8a, 0xcd, 0x05, 0x42, 0x8b, 0xcc, + 0x06, 0x41, 0x88, 0xcf, 0x07, 0x40, 0x89, 0xce, 0x08, 0x4f, + 0x86, 0xc1, 0x09, 0x4e, 0x87, 0xc0, 0x0a, 0x4d, 0x84, 0xc3, + 0x0b, 0x4c, 0x85, 0xc2, 0x0c, 0x4b, 0x82, 0xc5, 0x0d, 0x4a, + 0x83, 0xc4, 0x0e, 0x49, 0x80, 0xc7, 0x0f, 0x48, 0x81, 0xc6, + 0x10, 0x57, 0x9e, 0xd9, 0x11, 0x56, 0x9f, 0xd8, 0x12, 0x55, + 0x9c, 0xdb, 0x13, 0x54, 0x9d, 0xda, 0x14, 0x53, 0x9a, 0xdd, + 0x15, 0x52, 0x9b, 0xdc, 0x16, 0x51, 0x98, 0xdf, 0x17, 0x50, + 0x99, 0xde, 0x18, 0x5f, 0x96, 0xd1, 0x19, 0x5e, 0x97, 0xd0, + 0x1a, 0x5d, 0x94, 0xd3, 0x1b, 0x5c, 0x95, 0xd2, 0x1c, 0x5b, + 0x92, 0xd5, 0x1d, 0x5a, 0x93, 0xd4, 0x1e, 0x59, 0x90, 0xd7, + 0x1f, 0x58, 0x91, 0xd6, 0x20, 0x67, 0xae, 0xe9, 0x21, 0x66, + 0xaf, 0xe8, 0x22, 0x65, 0xac, 0xeb, 0x23, 0x64, 0xad, 0xea, + 0x24, 0x63, 0xaa, 0xed, 0x25, 0x62, 0xab, 0xec, 0x26, 0x61, + 0xa8, 0xef, 0x27, 0x60, 0xa9, 0xee, 0x28, 0x6f, 0xa6, 0xe1, + 0x29, 0x6e, 0xa7, 0xe0, 0x2a, 0x6d, 0xa4, 0xe3, 0x2b, 0x6c, + 0xa5, 0xe2, 0x2c, 0x6b, 0xa2, 0xe5, 0x2d, 0x6a, 0xa3, 0xe4, + 0x2e, 0x69, 0xa0, 0xe7, 0x2f, 0x68, 0xa1, 0xe6, 0x30, 0x77, + 0xbe, 0xf9, 0x31, 0x76, 0xbf, 0xf8, 0x32, 0x75, 0xbc, 0xfb, + 0x33, 0x74, 0xbd, 0xfa, 0x34, 0x73, 0xba, 0xfd, 0x35, 0x72, + 0xbb, 0xfc, 0x36, 0x71, 0xb8, 0xff, 0x37, 0x70, 0xb9, 0xfe, + 0x38, 0x7f, 0xb6, 0xf1, 0x39, 0x7e, 0xb7, 0xf0, 0x3a, 0x7d, + 0xb4, 0xf3, 0x3b, 0x7c, 0xb5, 0xf2, 0x3c, 0x7b, 0xb2, 0xf5, + 0x3d, 0x7a, 0xb3, 0xf4, 0x3e, 0x79, 0xb0, 0xf7, 0x3f, 0x78, + 0xb1, 0xf6, 0x00, 0x48, 0x90, 0xd8, 0x3d, 0x75, 0xad, 0xe5, + 0x7a, 0x32, 0xea, 0xa2, 0x47, 0x0f, 0xd7, 0x9f, 0xf4, 0xbc, + 0x64, 0x2c, 0xc9, 0x81, 0x59, 0x11, 0x8e, 0xc6, 0x1e, 0x56, + 0xb3, 0xfb, 0x23, 0x6b, 0xf5, 0xbd, 0x65, 0x2d, 0xc8, 0x80, + 0x58, 0x10, 0x8f, 0xc7, 0x1f, 0x57, 0xb2, 0xfa, 0x22, 0x6a, + 0x01, 0x49, 0x91, 0xd9, 0x3c, 0x74, 0xac, 0xe4, 0x7b, 0x33, + 0xeb, 0xa3, 0x46, 0x0e, 0xd6, 0x9e, 0xf7, 0xbf, 0x67, 0x2f, + 0xca, 0x82, 0x5a, 0x12, 0x8d, 0xc5, 0x1d, 0x55, 0xb0, 0xf8, + 0x20, 0x68, 0x03, 0x4b, 0x93, 0xdb, 0x3e, 0x76, 0xae, 0xe6, + 0x79, 0x31, 0xe9, 0xa1, 0x44, 0x0c, 0xd4, 0x9c, 0x02, 0x4a, + 0x92, 0xda, 0x3f, 0x77, 0xaf, 0xe7, 0x78, 0x30, 0xe8, 0xa0, + 0x45, 0x0d, 0xd5, 0x9d, 0xf6, 0xbe, 0x66, 0x2e, 0xcb, 0x83, + 0x5b, 0x13, 0x8c, 0xc4, 0x1c, 0x54, 0xb1, 0xf9, 0x21, 0x69, + 0xf3, 0xbb, 0x63, 0x2b, 0xce, 0x86, 0x5e, 0x16, 0x89, 0xc1, + 0x19, 0x51, 0xb4, 0xfc, 0x24, 0x6c, 0x07, 0x4f, 0x97, 0xdf, + 0x3a, 0x72, 0xaa, 0xe2, 0x7d, 0x35, 0xed, 0xa5, 0x40, 0x08, + 0xd0, 0x98, 0x06, 0x4e, 0x96, 0xde, 0x3b, 0x73, 0xab, 0xe3, + 0x7c, 0x34, 0xec, 0xa4, 0x41, 0x09, 0xd1, 0x99, 0xf2, 0xba, + 0x62, 0x2a, 0xcf, 0x87, 0x5f, 0x17, 0x88, 0xc0, 0x18, 0x50, + 0xb5, 0xfd, 0x25, 0x6d, 0x04, 0x4c, 0x94, 0xdc, 0x39, 0x71, + 0xa9, 0xe1, 0x7e, 0x36, 0xee, 0xa6, 0x43, 0x0b, 0xd3, 0x9b, + 0xf0, 0xb8, 0x60, 0x28, 0xcd, 0x85, 0x5d, 0x15, 0x8a, 0xc2, + 0x1a, 0x52, 0xb7, 0xff, 0x27, 0x6f, 0xf1, 0xb9, 0x61, 0x29, + 0xcc, 0x84, 0x5c, 0x14, 0x8b, 0xc3, 0x1b, 0x53, 0xb6, 0xfe, + 0x26, 0x6e, 0x05, 0x4d, 0x95, 0xdd, 0x38, 0x70, 0xa8, 0xe0, + 0x7f, 0x37, 0xef, 0xa7, 0x42, 0x0a, 0xd2, 0x9a, 0x00, 0x49, + 0x92, 0xdb, 0x39, 0x70, 0xab, 0xe2, 0x72, 0x3b, 0xe0, 0xa9, + 0x4b, 0x02, 0xd9, 0x90, 0xe4, 0xad, 0x76, 0x3f, 0xdd, 0x94, + 0x4f, 0x06, 0x96, 0xdf, 0x04, 0x4d, 0xaf, 0xe6, 0x3d, 0x74, + 0xd5, 0x9c, 0x47, 0x0e, 0xec, 0xa5, 0x7e, 0x37, 0xa7, 0xee, + 0x35, 0x7c, 0x9e, 0xd7, 0x0c, 0x45, 0x31, 0x78, 0xa3, 0xea, + 0x08, 0x41, 0x9a, 0xd3, 0x43, 0x0a, 0xd1, 0x98, 0x7a, 0x33, + 0xe8, 0xa1, 0xb7, 0xfe, 0x25, 0x6c, 0x8e, 0xc7, 0x1c, 0x55, + 0xc5, 0x8c, 0x57, 0x1e, 0xfc, 0xb5, 0x6e, 0x27, 0x53, 0x1a, + 0xc1, 0x88, 0x6a, 0x23, 0xf8, 0xb1, 0x21, 0x68, 0xb3, 0xfa, + 0x18, 0x51, 0x8a, 0xc3, 0x62, 0x2b, 0xf0, 0xb9, 0x5b, 0x12, + 0xc9, 0x80, 0x10, 0x59, 0x82, 0xcb, 0x29, 0x60, 0xbb, 0xf2, + 0x86, 0xcf, 0x14, 0x5d, 0xbf, 0xf6, 0x2d, 0x64, 0xf4, 0xbd, + 0x66, 0x2f, 0xcd, 0x84, 0x5f, 0x16, 0x73, 0x3a, 0xe1, 0xa8, + 0x4a, 0x03, 0xd8, 0x91, 0x01, 0x48, 0x93, 0xda, 0x38, 0x71, + 0xaa, 0xe3, 0x97, 0xde, 0x05, 0x4c, 0xae, 0xe7, 0x3c, 0x75, + 0xe5, 0xac, 0x77, 0x3e, 0xdc, 0x95, 0x4e, 0x07, 0xa6, 0xef, + 0x34, 0x7d, 0x9f, 0xd6, 0x0d, 0x44, 0xd4, 0x9d, 0x46, 0x0f, + 0xed, 0xa4, 0x7f, 0x36, 0x42, 0x0b, 0xd0, 0x99, 0x7b, 0x32, + 0xe9, 0xa0, 0x30, 0x79, 0xa2, 0xeb, 0x09, 0x40, 0x9b, 0xd2, + 0xc4, 0x8d, 0x56, 0x1f, 0xfd, 0xb4, 0x6f, 0x26, 0xb6, 0xff, + 0x24, 0x6d, 0x8f, 0xc6, 0x1d, 0x54, 0x20, 0x69, 0xb2, 0xfb, + 0x19, 0x50, 0x8b, 0xc2, 0x52, 0x1b, 0xc0, 0x89, 0x6b, 0x22, + 0xf9, 0xb0, 0x11, 0x58, 0x83, 0xca, 0x28, 0x61, 0xba, 0xf3, + 0x63, 0x2a, 0xf1, 0xb8, 0x5a, 0x13, 0xc8, 0x81, 0xf5, 0xbc, + 0x67, 0x2e, 0xcc, 0x85, 0x5e, 0x17, 0x87, 0xce, 0x15, 0x5c, + 0xbe, 0xf7, 0x2c, 0x65, 0x00, 0x4a, 0x94, 0xde, 0x35, 0x7f, + 0xa1, 0xeb, 0x6a, 0x20, 0xfe, 0xb4, 0x5f, 0x15, 0xcb, 0x81, + 0xd4, 0x9e, 0x40, 0x0a, 0xe1, 0xab, 0x75, 0x3f, 0xbe, 0xf4, + 0x2a, 0x60, 0x8b, 0xc1, 0x1f, 0x55, 0xb5, 0xff, 0x21, 0x6b, + 0x80, 0xca, 0x14, 0x5e, 0xdf, 0x95, 0x4b, 0x01, 0xea, 0xa0, + 0x7e, 0x34, 0x61, 0x2b, 0xf5, 0xbf, 0x54, 0x1e, 0xc0, 0x8a, + 0x0b, 0x41, 0x9f, 0xd5, 0x3e, 0x74, 0xaa, 0xe0, 0x77, 0x3d, + 0xe3, 0xa9, 0x42, 0x08, 0xd6, 0x9c, 0x1d, 0x57, 0x89, 0xc3, + 0x28, 0x62, 0xbc, 0xf6, 0xa3, 0xe9, 0x37, 0x7d, 0x96, 0xdc, + 0x02, 0x48, 0xc9, 0x83, 0x5d, 0x17, 0xfc, 0xb6, 0x68, 0x22, + 0xc2, 0x88, 0x56, 0x1c, 0xf7, 0xbd, 0x63, 0x29, 0xa8, 0xe2, + 0x3c, 0x76, 0x9d, 0xd7, 0x09, 0x43, 0x16, 0x5c, 0x82, 0xc8, + 0x23, 0x69, 0xb7, 0xfd, 0x7c, 0x36, 0xe8, 0xa2, 0x49, 0x03, + 0xdd, 0x97, 0xee, 0xa4, 0x7a, 0x30, 0xdb, 0x91, 0x4f, 0x05, + 0x84, 0xce, 0x10, 0x5a, 0xb1, 0xfb, 0x25, 0x6f, 0x3a, 0x70, + 0xae, 0xe4, 0x0f, 0x45, 0x9b, 0xd1, 0x50, 0x1a, 0xc4, 0x8e, + 0x65, 0x2f, 0xf1, 0xbb, 0x5b, 0x11, 0xcf, 0x85, 0x6e, 0x24, + 0xfa, 0xb0, 0x31, 0x7b, 0xa5, 0xef, 0x04, 0x4e, 0x90, 0xda, + 0x8f, 0xc5, 0x1b, 0x51, 0xba, 0xf0, 0x2e, 0x64, 0xe5, 0xaf, + 0x71, 0x3b, 0xd0, 0x9a, 0x44, 0x0e, 0x99, 0xd3, 0x0d, 0x47, + 0xac, 0xe6, 0x38, 0x72, 0xf3, 0xb9, 0x67, 0x2d, 0xc6, 0x8c, + 0x52, 0x18, 0x4d, 0x07, 0xd9, 0x93, 0x78, 0x32, 0xec, 0xa6, + 0x27, 0x6d, 0xb3, 0xf9, 0x12, 0x58, 0x86, 0xcc, 0x2c, 0x66, + 0xb8, 0xf2, 0x19, 0x53, 0x8d, 0xc7, 0x46, 0x0c, 0xd2, 0x98, + 0x73, 0x39, 0xe7, 0xad, 0xf8, 0xb2, 0x6c, 0x26, 0xcd, 0x87, + 0x59, 0x13, 0x92, 0xd8, 0x06, 0x4c, 0xa7, 0xed, 0x33, 0x79, + 0x00, 0x4b, 0x96, 0xdd, 0x31, 0x7a, 0xa7, 0xec, 0x62, 0x29, + 0xf4, 0xbf, 0x53, 0x18, 0xc5, 0x8e, 0xc4, 0x8f, 0x52, 0x19, + 0xf5, 0xbe, 0x63, 0x28, 0xa6, 0xed, 0x30, 0x7b, 0x97, 0xdc, + 0x01, 0x4a, 0x95, 0xde, 0x03, 0x48, 0xa4, 0xef, 0x32, 0x79, + 0xf7, 0xbc, 0x61, 0x2a, 0xc6, 0x8d, 0x50, 0x1b, 0x51, 0x1a, + 0xc7, 0x8c, 0x60, 0x2b, 0xf6, 0xbd, 0x33, 0x78, 0xa5, 0xee, + 0x02, 0x49, 0x94, 0xdf, 0x37, 0x7c, 0xa1, 0xea, 0x06, 0x4d, + 0x90, 0xdb, 0x55, 0x1e, 0xc3, 0x88, 0x64, 0x2f, 0xf2, 0xb9, + 0xf3, 0xb8, 0x65, 0x2e, 0xc2, 0x89, 0x54, 0x1f, 0x91, 0xda, + 0x07, 0x4c, 0xa0, 0xeb, 0x36, 0x7d, 0xa2, 0xe9, 0x34, 0x7f, + 0x93, 0xd8, 0x05, 0x4e, 0xc0, 0x8b, 0x56, 0x1d, 0xf1, 0xba, + 0x67, 0x2c, 0x66, 0x2d, 0xf0, 0xbb, 0x57, 0x1c, 0xc1, 0x8a, + 0x04, 0x4f, 0x92, 0xd9, 0x35, 0x7e, 0xa3, 0xe8, 0x6e, 0x25, + 0xf8, 0xb3, 0x5f, 0x14, 0xc9, 0x82, 0x0c, 0x47, 0x9a, 0xd1, + 0x3d, 0x76, 0xab, 0xe0, 0xaa, 0xe1, 0x3c, 0x77, 0x9b, 0xd0, + 0x0d, 0x46, 0xc8, 0x83, 0x5e, 0x15, 0xf9, 0xb2, 0x6f, 0x24, + 0xfb, 0xb0, 0x6d, 0x26, 0xca, 0x81, 0x5c, 0x17, 0x99, 0xd2, + 0x0f, 0x44, 0xa8, 0xe3, 0x3e, 0x75, 0x3f, 0x74, 0xa9, 0xe2, + 0x0e, 0x45, 0x98, 0xd3, 0x5d, 0x16, 0xcb, 0x80, 0x6c, 0x27, + 0xfa, 0xb1, 0x59, 0x12, 0xcf, 0x84, 0x68, 0x23, 0xfe, 0xb5, + 0x3b, 0x70, 0xad, 0xe6, 0x0a, 0x41, 0x9c, 0xd7, 0x9d, 0xd6, + 0x0b, 0x40, 0xac, 0xe7, 0x3a, 0x71, 0xff, 0xb4, 0x69, 0x22, + 0xce, 0x85, 0x58, 0x13, 0xcc, 0x87, 0x5a, 0x11, 0xfd, 0xb6, + 0x6b, 0x20, 0xae, 0xe5, 0x38, 0x73, 0x9f, 0xd4, 0x09, 0x42, + 0x08, 0x43, 0x9e, 0xd5, 0x39, 0x72, 0xaf, 0xe4, 0x6a, 0x21, + 0xfc, 0xb7, 0x5b, 0x10, 0xcd, 0x86, 0x00, 0x4c, 0x98, 0xd4, + 0x2d, 0x61, 0xb5, 0xf9, 0x5a, 0x16, 0xc2, 0x8e, 0x77, 0x3b, + 0xef, 0xa3, 0xb4, 0xf8, 0x2c, 0x60, 0x99, 0xd5, 0x01, 0x4d, + 0xee, 0xa2, 0x76, 0x3a, 0xc3, 0x8f, 0x5b, 0x17, 0x75, 0x39, + 0xed, 0xa1, 0x58, 0x14, 0xc0, 0x8c, 0x2f, 0x63, 0xb7, 0xfb, + 0x02, 0x4e, 0x9a, 0xd6, 0xc1, 0x8d, 0x59, 0x15, 0xec, 0xa0, + 0x74, 0x38, 0x9b, 0xd7, 0x03, 0x4f, 0xb6, 0xfa, 0x2e, 0x62, + 0xea, 0xa6, 0x72, 0x3e, 0xc7, 0x8b, 0x5f, 0x13, 0xb0, 0xfc, + 0x28, 0x64, 0x9d, 0xd1, 0x05, 0x49, 0x5e, 0x12, 0xc6, 0x8a, + 0x73, 0x3f, 0xeb, 0xa7, 0x04, 0x48, 0x9c, 0xd0, 0x29, 0x65, + 0xb1, 0xfd, 0x9f, 0xd3, 0x07, 0x4b, 0xb2, 0xfe, 0x2a, 0x66, + 0xc5, 0x89, 0x5d, 0x11, 0xe8, 0xa4, 0x70, 0x3c, 0x2b, 0x67, + 0xb3, 0xff, 0x06, 0x4a, 0x9e, 0xd2, 0x71, 0x3d, 0xe9, 0xa5, + 0x5c, 0x10, 0xc4, 0x88, 0xc9, 0x85, 0x51, 0x1d, 0xe4, 0xa8, + 0x7c, 0x30, 0x93, 0xdf, 0x0b, 0x47, 0xbe, 0xf2, 0x26, 0x6a, + 0x7d, 0x31, 0xe5, 0xa9, 0x50, 0x1c, 0xc8, 0x84, 0x27, 0x6b, + 0xbf, 0xf3, 0x0a, 0x46, 0x92, 0xde, 0xbc, 0xf0, 0x24, 0x68, + 0x91, 0xdd, 0x09, 0x45, 0xe6, 0xaa, 0x7e, 0x32, 0xcb, 0x87, + 0x53, 0x1f, 0x08, 0x44, 0x90, 0xdc, 0x25, 0x69, 0xbd, 0xf1, + 0x52, 0x1e, 0xca, 0x86, 0x7f, 0x33, 0xe7, 0xab, 0x23, 0x6f, + 0xbb, 0xf7, 0x0e, 0x42, 0x96, 0xda, 0x79, 0x35, 0xe1, 0xad, + 0x54, 0x18, 0xcc, 0x80, 0x97, 0xdb, 0x0f, 0x43, 0xba, 0xf6, + 0x22, 0x6e, 0xcd, 0x81, 0x55, 0x19, 0xe0, 0xac, 0x78, 0x34, + 0x56, 0x1a, 0xce, 0x82, 0x7b, 0x37, 0xe3, 0xaf, 0x0c, 0x40, + 0x94, 0xd8, 0x21, 0x6d, 0xb9, 0xf5, 0xe2, 0xae, 0x7a, 0x36, + 0xcf, 0x83, 0x57, 0x1b, 0xb8, 0xf4, 0x20, 0x6c, 0x95, 0xd9, + 0x0d, 0x41, 0x00, 0x4d, 0x9a, 0xd7, 0x29, 0x64, 0xb3, 0xfe, + 0x52, 0x1f, 0xc8, 0x85, 0x7b, 0x36, 0xe1, 0xac, 0xa4, 0xe9, + 0x3e, 0x73, 0x8d, 0xc0, 0x17, 0x5a, 0xf6, 0xbb, 0x6c, 0x21, + 0xdf, 0x92, 0x45, 0x08, 0x55, 0x18, 0xcf, 0x82, 0x7c, 0x31, + 0xe6, 0xab, 0x07, 0x4a, 0x9d, 0xd0, 0x2e, 0x63, 0xb4, 0xf9, + 0xf1, 0xbc, 0x6b, 0x26, 0xd8, 0x95, 0x42, 0x0f, 0xa3, 0xee, + 0x39, 0x74, 0x8a, 0xc7, 0x10, 0x5d, 0xaa, 0xe7, 0x30, 0x7d, + 0x83, 0xce, 0x19, 0x54, 0xf8, 0xb5, 0x62, 0x2f, 0xd1, 0x9c, + 0x4b, 0x06, 0x0e, 0x43, 0x94, 0xd9, 0x27, 0x6a, 0xbd, 0xf0, + 0x5c, 0x11, 0xc6, 0x8b, 0x75, 0x38, 0xef, 0xa2, 0xff, 0xb2, + 0x65, 0x28, 0xd6, 0x9b, 0x4c, 0x01, 0xad, 0xe0, 0x37, 0x7a, + 0x84, 0xc9, 0x1e, 0x53, 0x5b, 0x16, 0xc1, 0x8c, 0x72, 0x3f, + 0xe8, 0xa5, 0x09, 0x44, 0x93, 0xde, 0x20, 0x6d, 0xba, 0xf7, + 0x49, 0x04, 0xd3, 0x9e, 0x60, 0x2d, 0xfa, 0xb7, 0x1b, 0x56, + 0x81, 0xcc, 0x32, 0x7f, 0xa8, 0xe5, 0xed, 0xa0, 0x77, 0x3a, + 0xc4, 0x89, 0x5e, 0x13, 0xbf, 0xf2, 0x25, 0x68, 0x96, 0xdb, + 0x0c, 0x41, 0x1c, 0x51, 0x86, 0xcb, 0x35, 0x78, 0xaf, 0xe2, + 0x4e, 0x03, 0xd4, 0x99, 0x67, 0x2a, 0xfd, 0xb0, 0xb8, 0xf5, + 0x22, 0x6f, 0x91, 0xdc, 0x0b, 0x46, 0xea, 0xa7, 0x70, 0x3d, + 0xc3, 0x8e, 0x59, 0x14, 0xe3, 0xae, 0x79, 0x34, 0xca, 0x87, + 0x50, 0x1d, 0xb1, 0xfc, 0x2b, 0x66, 0x98, 0xd5, 0x02, 0x4f, + 0x47, 0x0a, 0xdd, 0x90, 0x6e, 0x23, 0xf4, 0xb9, 0x15, 0x58, + 0x8f, 0xc2, 0x3c, 0x71, 0xa6, 0xeb, 0xb6, 0xfb, 0x2c, 0x61, + 0x9f, 0xd2, 0x05, 0x48, 0xe4, 0xa9, 0x7e, 0x33, 0xcd, 0x80, + 0x57, 0x1a, 0x12, 0x5f, 0x88, 0xc5, 0x3b, 0x76, 0xa1, 0xec, + 0x40, 0x0d, 0xda, 0x97, 0x69, 0x24, 0xf3, 0xbe, 0x00, 0x4e, + 0x9c, 0xd2, 0x25, 0x6b, 0xb9, 0xf7, 0x4a, 0x04, 0xd6, 0x98, + 0x6f, 0x21, 0xf3, 0xbd, 0x94, 0xda, 0x08, 0x46, 0xb1, 0xff, + 0x2d, 0x63, 0xde, 0x90, 0x42, 0x0c, 0xfb, 0xb5, 0x67, 0x29, + 0x35, 0x7b, 0xa9, 0xe7, 0x10, 0x5e, 0x8c, 0xc2, 0x7f, 0x31, + 0xe3, 0xad, 0x5a, 0x14, 0xc6, 0x88, 0xa1, 0xef, 0x3d, 0x73, + 0x84, 0xca, 0x18, 0x56, 0xeb, 0xa5, 0x77, 0x39, 0xce, 0x80, + 0x52, 0x1c, 0x6a, 0x24, 0xf6, 0xb8, 0x4f, 0x01, 0xd3, 0x9d, + 0x20, 0x6e, 0xbc, 0xf2, 0x05, 0x4b, 0x99, 0xd7, 0xfe, 0xb0, + 0x62, 0x2c, 0xdb, 0x95, 0x47, 0x09, 0xb4, 0xfa, 0x28, 0x66, + 0x91, 0xdf, 0x0d, 0x43, 0x5f, 0x11, 0xc3, 0x8d, 0x7a, 0x34, + 0xe6, 0xa8, 0x15, 0x5b, 0x89, 0xc7, 0x30, 0x7e, 0xac, 0xe2, + 0xcb, 0x85, 0x57, 0x19, 0xee, 0xa0, 0x72, 0x3c, 0x81, 0xcf, + 0x1d, 0x53, 0xa4, 0xea, 0x38, 0x76, 0xd4, 0x9a, 0x48, 0x06, + 0xf1, 0xbf, 0x6d, 0x23, 0x9e, 0xd0, 0x02, 0x4c, 0xbb, 0xf5, + 0x27, 0x69, 0x40, 0x0e, 0xdc, 0x92, 0x65, 0x2b, 0xf9, 0xb7, + 0x0a, 0x44, 0x96, 0xd8, 0x2f, 0x61, 0xb3, 0xfd, 0xe1, 0xaf, + 0x7d, 0x33, 0xc4, 0x8a, 0x58, 0x16, 0xab, 0xe5, 0x37, 0x79, + 0x8e, 0xc0, 0x12, 0x5c, 0x75, 0x3b, 0xe9, 0xa7, 0x50, 0x1e, + 0xcc, 0x82, 0x3f, 0x71, 0xa3, 0xed, 0x1a, 0x54, 0x86, 0xc8, + 0xbe, 0xf0, 0x22, 0x6c, 0x9b, 0xd5, 0x07, 0x49, 0xf4, 0xba, + 0x68, 0x26, 0xd1, 0x9f, 0x4d, 0x03, 0x2a, 0x64, 0xb6, 0xf8, + 0x0f, 0x41, 0x93, 0xdd, 0x60, 0x2e, 0xfc, 0xb2, 0x45, 0x0b, + 0xd9, 0x97, 0x8b, 0xc5, 0x17, 0x59, 0xae, 0xe0, 0x32, 0x7c, + 0xc1, 0x8f, 0x5d, 0x13, 0xe4, 0xaa, 0x78, 0x36, 0x1f, 0x51, + 0x83, 0xcd, 0x3a, 0x74, 0xa6, 0xe8, 0x55, 0x1b, 0xc9, 0x87, + 0x70, 0x3e, 0xec, 0xa2, 0x00, 0x4f, 0x9e, 0xd1, 0x21, 0x6e, + 0xbf, 0xf0, 0x42, 0x0d, 0xdc, 0x93, 0x63, 0x2c, 0xfd, 0xb2, + 0x84, 0xcb, 0x1a, 0x55, 0xa5, 0xea, 0x3b, 0x74, 0xc6, 0x89, + 0x58, 0x17, 0xe7, 0xa8, 0x79, 0x36, 0x15, 0x5a, 0x8b, 0xc4, + 0x34, 0x7b, 0xaa, 0xe5, 0x57, 0x18, 0xc9, 0x86, 0x76, 0x39, + 0xe8, 0xa7, 0x91, 0xde, 0x0f, 0x40, 0xb0, 0xff, 0x2e, 0x61, + 0xd3, 0x9c, 0x4d, 0x02, 0xf2, 0xbd, 0x6c, 0x23, 0x2a, 0x65, + 0xb4, 0xfb, 0x0b, 0x44, 0x95, 0xda, 0x68, 0x27, 0xf6, 0xb9, + 0x49, 0x06, 0xd7, 0x98, 0xae, 0xe1, 0x30, 0x7f, 0x8f, 0xc0, + 0x11, 0x5e, 0xec, 0xa3, 0x72, 0x3d, 0xcd, 0x82, 0x53, 0x1c, + 0x3f, 0x70, 0xa1, 0xee, 0x1e, 0x51, 0x80, 0xcf, 0x7d, 0x32, + 0xe3, 0xac, 0x5c, 0x13, 0xc2, 0x8d, 0xbb, 0xf4, 0x25, 0x6a, + 0x9a, 0xd5, 0x04, 0x4b, 0xf9, 0xb6, 0x67, 0x28, 0xd8, 0x97, + 0x46, 0x09, 0x54, 0x1b, 0xca, 0x85, 0x75, 0x3a, 0xeb, 0xa4, + 0x16, 0x59, 0x88, 0xc7, 0x37, 0x78, 0xa9, 0xe6, 0xd0, 0x9f, + 0x4e, 0x01, 0xf1, 0xbe, 0x6f, 0x20, 0x92, 0xdd, 0x0c, 0x43, + 0xb3, 0xfc, 0x2d, 0x62, 0x41, 0x0e, 0xdf, 0x90, 0x60, 0x2f, + 0xfe, 0xb1, 0x03, 0x4c, 0x9d, 0xd2, 0x22, 0x6d, 0xbc, 0xf3, + 0xc5, 0x8a, 0x5b, 0x14, 0xe4, 0xab, 0x7a, 0x35, 0x87, 0xc8, + 0x19, 0x56, 0xa6, 0xe9, 0x38, 0x77, 0x7e, 0x31, 0xe0, 0xaf, + 0x5f, 0x10, 0xc1, 0x8e, 0x3c, 0x73, 0xa2, 0xed, 0x1d, 0x52, + 0x83, 0xcc, 0xfa, 0xb5, 0x64, 0x2b, 0xdb, 0x94, 0x45, 0x0a, + 0xb8, 0xf7, 0x26, 0x69, 0x99, 0xd6, 0x07, 0x48, 0x6b, 0x24, + 0xf5, 0xba, 0x4a, 0x05, 0xd4, 0x9b, 0x29, 0x66, 0xb7, 0xf8, + 0x08, 0x47, 0x96, 0xd9, 0xef, 0xa0, 0x71, 0x3e, 0xce, 0x81, + 0x50, 0x1f, 0xad, 0xe2, 0x33, 0x7c, 0x8c, 0xc3, 0x12, 0x5d, + 0x00, 0x50, 0xa0, 0xf0, 0x5d, 0x0d, 0xfd, 0xad, 0xba, 0xea, + 0x1a, 0x4a, 0xe7, 0xb7, 0x47, 0x17, 0x69, 0x39, 0xc9, 0x99, + 0x34, 0x64, 0x94, 0xc4, 0xd3, 0x83, 0x73, 0x23, 0x8e, 0xde, + 0x2e, 0x7e, 0xd2, 0x82, 0x72, 0x22, 0x8f, 0xdf, 0x2f, 0x7f, + 0x68, 0x38, 0xc8, 0x98, 0x35, 0x65, 0x95, 0xc5, 0xbb, 0xeb, + 0x1b, 0x4b, 0xe6, 0xb6, 0x46, 0x16, 0x01, 0x51, 0xa1, 0xf1, + 0x5c, 0x0c, 0xfc, 0xac, 0xb9, 0xe9, 0x19, 0x49, 0xe4, 0xb4, + 0x44, 0x14, 0x03, 0x53, 0xa3, 0xf3, 0x5e, 0x0e, 0xfe, 0xae, + 0xd0, 0x80, 0x70, 0x20, 0x8d, 0xdd, 0x2d, 0x7d, 0x6a, 0x3a, + 0xca, 0x9a, 0x37, 0x67, 0x97, 0xc7, 0x6b, 0x3b, 0xcb, 0x9b, + 0x36, 0x66, 0x96, 0xc6, 0xd1, 0x81, 0x71, 0x21, 0x8c, 0xdc, + 0x2c, 0x7c, 0x02, 0x52, 0xa2, 0xf2, 0x5f, 0x0f, 0xff, 0xaf, + 0xb8, 0xe8, 0x18, 0x48, 0xe5, 0xb5, 0x45, 0x15, 0x6f, 0x3f, + 0xcf, 0x9f, 0x32, 0x62, 0x92, 0xc2, 0xd5, 0x85, 0x75, 0x25, + 0x88, 0xd8, 0x28, 0x78, 0x06, 0x56, 0xa6, 0xf6, 0x5b, 0x0b, + 0xfb, 0xab, 0xbc, 0xec, 0x1c, 0x4c, 0xe1, 0xb1, 0x41, 0x11, + 0xbd, 0xed, 0x1d, 0x4d, 0xe0, 0xb0, 0x40, 0x10, 0x07, 0x57, + 0xa7, 0xf7, 0x5a, 0x0a, 0xfa, 0xaa, 0xd4, 0x84, 0x74, 0x24, + 0x89, 0xd9, 0x29, 0x79, 0x6e, 0x3e, 0xce, 0x9e, 0x33, 0x63, + 0x93, 0xc3, 0xd6, 0x86, 0x76, 0x26, 0x8b, 0xdb, 0x2b, 0x7b, + 0x6c, 0x3c, 0xcc, 0x9c, 0x31, 0x61, 0x91, 0xc1, 0xbf, 0xef, + 0x1f, 0x4f, 0xe2, 0xb2, 0x42, 0x12, 0x05, 0x55, 0xa5, 0xf5, + 0x58, 0x08, 0xf8, 0xa8, 0x04, 0x54, 0xa4, 0xf4, 0x59, 0x09, + 0xf9, 0xa9, 0xbe, 0xee, 0x1e, 0x4e, 0xe3, 0xb3, 0x43, 0x13, + 0x6d, 0x3d, 0xcd, 0x9d, 0x30, 0x60, 0x90, 0xc0, 0xd7, 0x87, + 0x77, 0x27, 0x8a, 0xda, 0x2a, 0x7a, 0x00, 0x51, 0xa2, 0xf3, + 0x59, 0x08, 0xfb, 0xaa, 0xb2, 0xe3, 0x10, 0x41, 0xeb, 0xba, + 0x49, 0x18, 0x79, 0x28, 0xdb, 0x8a, 0x20, 0x71, 0x82, 0xd3, + 0xcb, 0x9a, 0x69, 0x38, 0x92, 0xc3, 0x30, 0x61, 0xf2, 0xa3, + 0x50, 0x01, 0xab, 0xfa, 0x09, 0x58, 0x40, 0x11, 0xe2, 0xb3, + 0x19, 0x48, 0xbb, 0xea, 0x8b, 0xda, 0x29, 0x78, 0xd2, 0x83, + 0x70, 0x21, 0x39, 0x68, 0x9b, 0xca, 0x60, 0x31, 0xc2, 0x93, + 0xf9, 0xa8, 0x5b, 0x0a, 0xa0, 0xf1, 0x02, 0x53, 0x4b, 0x1a, + 0xe9, 0xb8, 0x12, 0x43, 0xb0, 0xe1, 0x80, 0xd1, 0x22, 0x73, + 0xd9, 0x88, 0x7b, 0x2a, 0x32, 0x63, 0x90, 0xc1, 0x6b, 0x3a, + 0xc9, 0x98, 0x0b, 0x5a, 0xa9, 0xf8, 0x52, 0x03, 0xf0, 0xa1, + 0xb9, 0xe8, 0x1b, 0x4a, 0xe0, 0xb1, 0x42, 0x13, 0x72, 0x23, + 0xd0, 0x81, 0x2b, 0x7a, 0x89, 0xd8, 0xc0, 0x91, 0x62, 0x33, + 0x99, 0xc8, 0x3b, 0x6a, 0xef, 0xbe, 0x4d, 0x1c, 0xb6, 0xe7, + 0x14, 0x45, 0x5d, 0x0c, 0xff, 0xae, 0x04, 0x55, 0xa6, 0xf7, + 0x96, 0xc7, 0x34, 0x65, 0xcf, 0x9e, 0x6d, 0x3c, 0x24, 0x75, + 0x86, 0xd7, 0x7d, 0x2c, 0xdf, 0x8e, 0x1d, 0x4c, 0xbf, 0xee, + 0x44, 0x15, 0xe6, 0xb7, 0xaf, 0xfe, 0x0d, 0x5c, 0xf6, 0xa7, + 0x54, 0x05, 0x64, 0x35, 0xc6, 0x97, 0x3d, 0x6c, 0x9f, 0xce, + 0xd6, 0x87, 0x74, 0x25, 0x8f, 0xde, 0x2d, 0x7c, 0x16, 0x47, + 0xb4, 0xe5, 0x4f, 0x1e, 0xed, 0xbc, 0xa4, 0xf5, 0x06, 0x57, + 0xfd, 0xac, 0x5f, 0x0e, 0x6f, 0x3e, 0xcd, 0x9c, 0x36, 0x67, + 0x94, 0xc5, 0xdd, 0x8c, 0x7f, 0x2e, 0x84, 0xd5, 0x26, 0x77, + 0xe4, 0xb5, 0x46, 0x17, 0xbd, 0xec, 0x1f, 0x4e, 0x56, 0x07, + 0xf4, 0xa5, 0x0f, 0x5e, 0xad, 0xfc, 0x9d, 0xcc, 0x3f, 0x6e, + 0xc4, 0x95, 0x66, 0x37, 0x2f, 0x7e, 0x8d, 0xdc, 0x76, 0x27, + 0xd4, 0x85, 0x00, 0x52, 0xa4, 0xf6, 0x55, 0x07, 0xf1, 0xa3, + 0xaa, 0xf8, 0x0e, 0x5c, 0xff, 0xad, 0x5b, 0x09, 0x49, 0x1b, + 0xed, 0xbf, 0x1c, 0x4e, 0xb8, 0xea, 0xe3, 0xb1, 0x47, 0x15, + 0xb6, 0xe4, 0x12, 0x40, 0x92, 0xc0, 0x36, 0x64, 0xc7, 0x95, + 0x63, 0x31, 0x38, 0x6a, 0x9c, 0xce, 0x6d, 0x3f, 0xc9, 0x9b, + 0xdb, 0x89, 0x7f, 0x2d, 0x8e, 0xdc, 0x2a, 0x78, 0x71, 0x23, + 0xd5, 0x87, 0x24, 0x76, 0x80, 0xd2, 0x39, 0x6b, 0x9d, 0xcf, + 0x6c, 0x3e, 0xc8, 0x9a, 0x93, 0xc1, 0x37, 0x65, 0xc6, 0x94, + 0x62, 0x30, 0x70, 0x22, 0xd4, 0x86, 0x25, 0x77, 0x81, 0xd3, + 0xda, 0x88, 0x7e, 0x2c, 0x8f, 0xdd, 0x2b, 0x79, 0xab, 0xf9, + 0x0f, 0x5d, 0xfe, 0xac, 0x5a, 0x08, 0x01, 0x53, 0xa5, 0xf7, + 0x54, 0x06, 0xf0, 0xa2, 0xe2, 0xb0, 0x46, 0x14, 0xb7, 0xe5, + 0x13, 0x41, 0x48, 0x1a, 0xec, 0xbe, 0x1d, 0x4f, 0xb9, 0xeb, + 0x72, 0x20, 0xd6, 0x84, 0x27, 0x75, 0x83, 0xd1, 0xd8, 0x8a, + 0x7c, 0x2e, 0x8d, 0xdf, 0x29, 0x7b, 0x3b, 0x69, 0x9f, 0xcd, + 0x6e, 0x3c, 0xca, 0x98, 0x91, 0xc3, 0x35, 0x67, 0xc4, 0x96, + 0x60, 0x32, 0xe0, 0xb2, 0x44, 0x16, 0xb5, 0xe7, 0x11, 0x43, + 0x4a, 0x18, 0xee, 0xbc, 0x1f, 0x4d, 0xbb, 0xe9, 0xa9, 0xfb, + 0x0d, 0x5f, 0xfc, 0xae, 0x58, 0x0a, 0x03, 0x51, 0xa7, 0xf5, + 0x56, 0x04, 0xf2, 0xa0, 0x4b, 0x19, 0xef, 0xbd, 0x1e, 0x4c, + 0xba, 0xe8, 0xe1, 0xb3, 0x45, 0x17, 0xb4, 0xe6, 0x10, 0x42, + 0x02, 0x50, 0xa6, 0xf4, 0x57, 0x05, 0xf3, 0xa1, 0xa8, 0xfa, + 0x0c, 0x5e, 0xfd, 0xaf, 0x59, 0x0b, 0xd9, 0x8b, 0x7d, 0x2f, + 0x8c, 0xde, 0x28, 0x7a, 0x73, 0x21, 0xd7, 0x85, 0x26, 0x74, + 0x82, 0xd0, 0x90, 0xc2, 0x34, 0x66, 0xc5, 0x97, 0x61, 0x33, + 0x3a, 0x68, 0x9e, 0xcc, 0x6f, 0x3d, 0xcb, 0x99, 0x00, 0x53, + 0xa6, 0xf5, 0x51, 0x02, 0xf7, 0xa4, 0xa2, 0xf1, 0x04, 0x57, + 0xf3, 0xa0, 0x55, 0x06, 0x59, 0x0a, 0xff, 0xac, 0x08, 0x5b, + 0xae, 0xfd, 0xfb, 0xa8, 0x5d, 0x0e, 0xaa, 0xf9, 0x0c, 0x5f, + 0xb2, 0xe1, 0x14, 0x47, 0xe3, 0xb0, 0x45, 0x16, 0x10, 0x43, + 0xb6, 0xe5, 0x41, 0x12, 0xe7, 0xb4, 0xeb, 0xb8, 0x4d, 0x1e, + 0xba, 0xe9, 0x1c, 0x4f, 0x49, 0x1a, 0xef, 0xbc, 0x18, 0x4b, + 0xbe, 0xed, 0x79, 0x2a, 0xdf, 0x8c, 0x28, 0x7b, 0x8e, 0xdd, + 0xdb, 0x88, 0x7d, 0x2e, 0x8a, 0xd9, 0x2c, 0x7f, 0x20, 0x73, + 0x86, 0xd5, 0x71, 0x22, 0xd7, 0x84, 0x82, 0xd1, 0x24, 0x77, + 0xd3, 0x80, 0x75, 0x26, 0xcb, 0x98, 0x6d, 0x3e, 0x9a, 0xc9, + 0x3c, 0x6f, 0x69, 0x3a, 0xcf, 0x9c, 0x38, 0x6b, 0x9e, 0xcd, + 0x92, 0xc1, 0x34, 0x67, 0xc3, 0x90, 0x65, 0x36, 0x30, 0x63, + 0x96, 0xc5, 0x61, 0x32, 0xc7, 0x94, 0xf2, 0xa1, 0x54, 0x07, + 0xa3, 0xf0, 0x05, 0x56, 0x50, 0x03, 0xf6, 0xa5, 0x01, 0x52, + 0xa7, 0xf4, 0xab, 0xf8, 0x0d, 0x5e, 0xfa, 0xa9, 0x5c, 0x0f, + 0x09, 0x5a, 0xaf, 0xfc, 0x58, 0x0b, 0xfe, 0xad, 0x40, 0x13, + 0xe6, 0xb5, 0x11, 0x42, 0xb7, 0xe4, 0xe2, 0xb1, 0x44, 0x17, + 0xb3, 0xe0, 0x15, 0x46, 0x19, 0x4a, 0xbf, 0xec, 0x48, 0x1b, + 0xee, 0xbd, 0xbb, 0xe8, 0x1d, 0x4e, 0xea, 0xb9, 0x4c, 0x1f, + 0x8b, 0xd8, 0x2d, 0x7e, 0xda, 0x89, 0x7c, 0x2f, 0x29, 0x7a, + 0x8f, 0xdc, 0x78, 0x2b, 0xde, 0x8d, 0xd2, 0x81, 0x74, 0x27, + 0x83, 0xd0, 0x25, 0x76, 0x70, 0x23, 0xd6, 0x85, 0x21, 0x72, + 0x87, 0xd4, 0x39, 0x6a, 0x9f, 0xcc, 0x68, 0x3b, 0xce, 0x9d, + 0x9b, 0xc8, 0x3d, 0x6e, 0xca, 0x99, 0x6c, 0x3f, 0x60, 0x33, + 0xc6, 0x95, 0x31, 0x62, 0x97, 0xc4, 0xc2, 0x91, 0x64, 0x37, + 0x93, 0xc0, 0x35, 0x66, 0x00, 0x54, 0xa8, 0xfc, 0x4d, 0x19, + 0xe5, 0xb1, 0x9a, 0xce, 0x32, 0x66, 0xd7, 0x83, 0x7f, 0x2b, + 0x29, 0x7d, 0x81, 0xd5, 0x64, 0x30, 0xcc, 0x98, 0xb3, 0xe7, + 0x1b, 0x4f, 0xfe, 0xaa, 0x56, 0x02, 0x52, 0x06, 0xfa, 0xae, + 0x1f, 0x4b, 0xb7, 0xe3, 0xc8, 0x9c, 0x60, 0x34, 0x85, 0xd1, + 0x2d, 0x79, 0x7b, 0x2f, 0xd3, 0x87, 0x36, 0x62, 0x9e, 0xca, + 0xe1, 0xb5, 0x49, 0x1d, 0xac, 0xf8, 0x04, 0x50, 0xa4, 0xf0, + 0x0c, 0x58, 0xe9, 0xbd, 0x41, 0x15, 0x3e, 0x6a, 0x96, 0xc2, + 0x73, 0x27, 0xdb, 0x8f, 0x8d, 0xd9, 0x25, 0x71, 0xc0, 0x94, + 0x68, 0x3c, 0x17, 0x43, 0xbf, 0xeb, 0x5a, 0x0e, 0xf2, 0xa6, + 0xf6, 0xa2, 0x5e, 0x0a, 0xbb, 0xef, 0x13, 0x47, 0x6c, 0x38, + 0xc4, 0x90, 0x21, 0x75, 0x89, 0xdd, 0xdf, 0x8b, 0x77, 0x23, + 0x92, 0xc6, 0x3a, 0x6e, 0x45, 0x11, 0xed, 0xb9, 0x08, 0x5c, + 0xa0, 0xf4, 0x55, 0x01, 0xfd, 0xa9, 0x18, 0x4c, 0xb0, 0xe4, + 0xcf, 0x9b, 0x67, 0x33, 0x82, 0xd6, 0x2a, 0x7e, 0x7c, 0x28, + 0xd4, 0x80, 0x31, 0x65, 0x99, 0xcd, 0xe6, 0xb2, 0x4e, 0x1a, + 0xab, 0xff, 0x03, 0x57, 0x07, 0x53, 0xaf, 0xfb, 0x4a, 0x1e, + 0xe2, 0xb6, 0x9d, 0xc9, 0x35, 0x61, 0xd0, 0x84, 0x78, 0x2c, + 0x2e, 0x7a, 0x86, 0xd2, 0x63, 0x37, 0xcb, 0x9f, 0xb4, 0xe0, + 0x1c, 0x48, 0xf9, 0xad, 0x51, 0x05, 0xf1, 0xa5, 0x59, 0x0d, + 0xbc, 0xe8, 0x14, 0x40, 0x6b, 0x3f, 0xc3, 0x97, 0x26, 0x72, + 0x8e, 0xda, 0xd8, 0x8c, 0x70, 0x24, 0x95, 0xc1, 0x3d, 0x69, + 0x42, 0x16, 0xea, 0xbe, 0x0f, 0x5b, 0xa7, 0xf3, 0xa3, 0xf7, + 0x0b, 0x5f, 0xee, 0xba, 0x46, 0x12, 0x39, 0x6d, 0x91, 0xc5, + 0x74, 0x20, 0xdc, 0x88, 0x8a, 0xde, 0x22, 0x76, 0xc7, 0x93, + 0x6f, 0x3b, 0x10, 0x44, 0xb8, 0xec, 0x5d, 0x09, 0xf5, 0xa1, + 0x00, 0x55, 0xaa, 0xff, 0x49, 0x1c, 0xe3, 0xb6, 0x92, 0xc7, + 0x38, 0x6d, 0xdb, 0x8e, 0x71, 0x24, 0x39, 0x6c, 0x93, 0xc6, + 0x70, 0x25, 0xda, 0x8f, 0xab, 0xfe, 0x01, 0x54, 0xe2, 0xb7, + 0x48, 0x1d, 0x72, 0x27, 0xd8, 0x8d, 0x3b, 0x6e, 0x91, 0xc4, + 0xe0, 0xb5, 0x4a, 0x1f, 0xa9, 0xfc, 0x03, 0x56, 0x4b, 0x1e, + 0xe1, 0xb4, 0x02, 0x57, 0xa8, 0xfd, 0xd9, 0x8c, 0x73, 0x26, + 0x90, 0xc5, 0x3a, 0x6f, 0xe4, 0xb1, 0x4e, 0x1b, 0xad, 0xf8, + 0x07, 0x52, 0x76, 0x23, 0xdc, 0x89, 0x3f, 0x6a, 0x95, 0xc0, + 0xdd, 0x88, 0x77, 0x22, 0x94, 0xc1, 0x3e, 0x6b, 0x4f, 0x1a, + 0xe5, 0xb0, 0x06, 0x53, 0xac, 0xf9, 0x96, 0xc3, 0x3c, 0x69, + 0xdf, 0x8a, 0x75, 0x20, 0x04, 0x51, 0xae, 0xfb, 0x4d, 0x18, + 0xe7, 0xb2, 0xaf, 0xfa, 0x05, 0x50, 0xe6, 0xb3, 0x4c, 0x19, + 0x3d, 0x68, 0x97, 0xc2, 0x74, 0x21, 0xde, 0x8b, 0xd5, 0x80, + 0x7f, 0x2a, 0x9c, 0xc9, 0x36, 0x63, 0x47, 0x12, 0xed, 0xb8, + 0x0e, 0x5b, 0xa4, 0xf1, 0xec, 0xb9, 0x46, 0x13, 0xa5, 0xf0, + 0x0f, 0x5a, 0x7e, 0x2b, 0xd4, 0x81, 0x37, 0x62, 0x9d, 0xc8, + 0xa7, 0xf2, 0x0d, 0x58, 0xee, 0xbb, 0x44, 0x11, 0x35, 0x60, + 0x9f, 0xca, 0x7c, 0x29, 0xd6, 0x83, 0x9e, 0xcb, 0x34, 0x61, + 0xd7, 0x82, 0x7d, 0x28, 0x0c, 0x59, 0xa6, 0xf3, 0x45, 0x10, + 0xef, 0xba, 0x31, 0x64, 0x9b, 0xce, 0x78, 0x2d, 0xd2, 0x87, + 0xa3, 0xf6, 0x09, 0x5c, 0xea, 0xbf, 0x40, 0x15, 0x08, 0x5d, + 0xa2, 0xf7, 0x41, 0x14, 0xeb, 0xbe, 0x9a, 0xcf, 0x30, 0x65, + 0xd3, 0x86, 0x79, 0x2c, 0x43, 0x16, 0xe9, 0xbc, 0x0a, 0x5f, + 0xa0, 0xf5, 0xd1, 0x84, 0x7b, 0x2e, 0x98, 0xcd, 0x32, 0x67, + 0x7a, 0x2f, 0xd0, 0x85, 0x33, 0x66, 0x99, 0xcc, 0xe8, 0xbd, + 0x42, 0x17, 0xa1, 0xf4, 0x0b, 0x5e, 0x00, 0x56, 0xac, 0xfa, + 0x45, 0x13, 0xe9, 0xbf, 0x8a, 0xdc, 0x26, 0x70, 0xcf, 0x99, + 0x63, 0x35, 0x09, 0x5f, 0xa5, 0xf3, 0x4c, 0x1a, 0xe0, 0xb6, + 0x83, 0xd5, 0x2f, 0x79, 0xc6, 0x90, 0x6a, 0x3c, 0x12, 0x44, + 0xbe, 0xe8, 0x57, 0x01, 0xfb, 0xad, 0x98, 0xce, 0x34, 0x62, + 0xdd, 0x8b, 0x71, 0x27, 0x1b, 0x4d, 0xb7, 0xe1, 0x5e, 0x08, + 0xf2, 0xa4, 0x91, 0xc7, 0x3d, 0x6b, 0xd4, 0x82, 0x78, 0x2e, + 0x24, 0x72, 0x88, 0xde, 0x61, 0x37, 0xcd, 0x9b, 0xae, 0xf8, + 0x02, 0x54, 0xeb, 0xbd, 0x47, 0x11, 0x2d, 0x7b, 0x81, 0xd7, + 0x68, 0x3e, 0xc4, 0x92, 0xa7, 0xf1, 0x0b, 0x5d, 0xe2, 0xb4, + 0x4e, 0x18, 0x36, 0x60, 0x9a, 0xcc, 0x73, 0x25, 0xdf, 0x89, + 0xbc, 0xea, 0x10, 0x46, 0xf9, 0xaf, 0x55, 0x03, 0x3f, 0x69, + 0x93, 0xc5, 0x7a, 0x2c, 0xd6, 0x80, 0xb5, 0xe3, 0x19, 0x4f, + 0xf0, 0xa6, 0x5c, 0x0a, 0x48, 0x1e, 0xe4, 0xb2, 0x0d, 0x5b, + 0xa1, 0xf7, 0xc2, 0x94, 0x6e, 0x38, 0x87, 0xd1, 0x2b, 0x7d, + 0x41, 0x17, 0xed, 0xbb, 0x04, 0x52, 0xa8, 0xfe, 0xcb, 0x9d, + 0x67, 0x31, 0x8e, 0xd8, 0x22, 0x74, 0x5a, 0x0c, 0xf6, 0xa0, + 0x1f, 0x49, 0xb3, 0xe5, 0xd0, 0x86, 0x7c, 0x2a, 0x95, 0xc3, + 0x39, 0x6f, 0x53, 0x05, 0xff, 0xa9, 0x16, 0x40, 0xba, 0xec, + 0xd9, 0x8f, 0x75, 0x23, 0x9c, 0xca, 0x30, 0x66, 0x6c, 0x3a, + 0xc0, 0x96, 0x29, 0x7f, 0x85, 0xd3, 0xe6, 0xb0, 0x4a, 0x1c, + 0xa3, 0xf5, 0x0f, 0x59, 0x65, 0x33, 0xc9, 0x9f, 0x20, 0x76, + 0x8c, 0xda, 0xef, 0xb9, 0x43, 0x15, 0xaa, 0xfc, 0x06, 0x50, + 0x7e, 0x28, 0xd2, 0x84, 0x3b, 0x6d, 0x97, 0xc1, 0xf4, 0xa2, + 0x58, 0x0e, 0xb1, 0xe7, 0x1d, 0x4b, 0x77, 0x21, 0xdb, 0x8d, + 0x32, 0x64, 0x9e, 0xc8, 0xfd, 0xab, 0x51, 0x07, 0xb8, 0xee, + 0x14, 0x42, 0x00, 0x57, 0xae, 0xf9, 0x41, 0x16, 0xef, 0xb8, + 0x82, 0xd5, 0x2c, 0x7b, 0xc3, 0x94, 0x6d, 0x3a, 0x19, 0x4e, + 0xb7, 0xe0, 0x58, 0x0f, 0xf6, 0xa1, 0x9b, 0xcc, 0x35, 0x62, + 0xda, 0x8d, 0x74, 0x23, 0x32, 0x65, 0x9c, 0xcb, 0x73, 0x24, + 0xdd, 0x8a, 0xb0, 0xe7, 0x1e, 0x49, 0xf1, 0xa6, 0x5f, 0x08, + 0x2b, 0x7c, 0x85, 0xd2, 0x6a, 0x3d, 0xc4, 0x93, 0xa9, 0xfe, + 0x07, 0x50, 0xe8, 0xbf, 0x46, 0x11, 0x64, 0x33, 0xca, 0x9d, + 0x25, 0x72, 0x8b, 0xdc, 0xe6, 0xb1, 0x48, 0x1f, 0xa7, 0xf0, + 0x09, 0x5e, 0x7d, 0x2a, 0xd3, 0x84, 0x3c, 0x6b, 0x92, 0xc5, + 0xff, 0xa8, 0x51, 0x06, 0xbe, 0xe9, 0x10, 0x47, 0x56, 0x01, + 0xf8, 0xaf, 0x17, 0x40, 0xb9, 0xee, 0xd4, 0x83, 0x7a, 0x2d, + 0x95, 0xc2, 0x3b, 0x6c, 0x4f, 0x18, 0xe1, 0xb6, 0x0e, 0x59, + 0xa0, 0xf7, 0xcd, 0x9a, 0x63, 0x34, 0x8c, 0xdb, 0x22, 0x75, + 0xc8, 0x9f, 0x66, 0x31, 0x89, 0xde, 0x27, 0x70, 0x4a, 0x1d, + 0xe4, 0xb3, 0x0b, 0x5c, 0xa5, 0xf2, 0xd1, 0x86, 0x7f, 0x28, + 0x90, 0xc7, 0x3e, 0x69, 0x53, 0x04, 0xfd, 0xaa, 0x12, 0x45, + 0xbc, 0xeb, 0xfa, 0xad, 0x54, 0x03, 0xbb, 0xec, 0x15, 0x42, + 0x78, 0x2f, 0xd6, 0x81, 0x39, 0x6e, 0x97, 0xc0, 0xe3, 0xb4, + 0x4d, 0x1a, 0xa2, 0xf5, 0x0c, 0x5b, 0x61, 0x36, 0xcf, 0x98, + 0x20, 0x77, 0x8e, 0xd9, 0xac, 0xfb, 0x02, 0x55, 0xed, 0xba, + 0x43, 0x14, 0x2e, 0x79, 0x80, 0xd7, 0x6f, 0x38, 0xc1, 0x96, + 0xb5, 0xe2, 0x1b, 0x4c, 0xf4, 0xa3, 0x5a, 0x0d, 0x37, 0x60, + 0x99, 0xce, 0x76, 0x21, 0xd8, 0x8f, 0x9e, 0xc9, 0x30, 0x67, + 0xdf, 0x88, 0x71, 0x26, 0x1c, 0x4b, 0xb2, 0xe5, 0x5d, 0x0a, + 0xf3, 0xa4, 0x87, 0xd0, 0x29, 0x7e, 0xc6, 0x91, 0x68, 0x3f, + 0x05, 0x52, 0xab, 0xfc, 0x44, 0x13, 0xea, 0xbd, 0x00, 0x58, + 0xb0, 0xe8, 0x7d, 0x25, 0xcd, 0x95, 0xfa, 0xa2, 0x4a, 0x12, + 0x87, 0xdf, 0x37, 0x6f, 0xe9, 0xb1, 0x59, 0x01, 0x94, 0xcc, + 0x24, 0x7c, 0x13, 0x4b, 0xa3, 0xfb, 0x6e, 0x36, 0xde, 0x86, + 0xcf, 0x97, 0x7f, 0x27, 0xb2, 0xea, 0x02, 0x5a, 0x35, 0x6d, + 0x85, 0xdd, 0x48, 0x10, 0xf8, 0xa0, 0x26, 0x7e, 0x96, 0xce, + 0x5b, 0x03, 0xeb, 0xb3, 0xdc, 0x84, 0x6c, 0x34, 0xa1, 0xf9, + 0x11, 0x49, 0x83, 0xdb, 0x33, 0x6b, 0xfe, 0xa6, 0x4e, 0x16, + 0x79, 0x21, 0xc9, 0x91, 0x04, 0x5c, 0xb4, 0xec, 0x6a, 0x32, + 0xda, 0x82, 0x17, 0x4f, 0xa7, 0xff, 0x90, 0xc8, 0x20, 0x78, + 0xed, 0xb5, 0x5d, 0x05, 0x4c, 0x14, 0xfc, 0xa4, 0x31, 0x69, + 0x81, 0xd9, 0xb6, 0xee, 0x06, 0x5e, 0xcb, 0x93, 0x7b, 0x23, + 0xa5, 0xfd, 0x15, 0x4d, 0xd8, 0x80, 0x68, 0x30, 0x5f, 0x07, + 0xef, 0xb7, 0x22, 0x7a, 0x92, 0xca, 0x1b, 0x43, 0xab, 0xf3, + 0x66, 0x3e, 0xd6, 0x8e, 0xe1, 0xb9, 0x51, 0x09, 0x9c, 0xc4, + 0x2c, 0x74, 0xf2, 0xaa, 0x42, 0x1a, 0x8f, 0xd7, 0x3f, 0x67, + 0x08, 0x50, 0xb8, 0xe0, 0x75, 0x2d, 0xc5, 0x9d, 0xd4, 0x8c, + 0x64, 0x3c, 0xa9, 0xf1, 0x19, 0x41, 0x2e, 0x76, 0x9e, 0xc6, + 0x53, 0x0b, 0xe3, 0xbb, 0x3d, 0x65, 0x8d, 0xd5, 0x40, 0x18, + 0xf0, 0xa8, 0xc7, 0x9f, 0x77, 0x2f, 0xba, 0xe2, 0x0a, 0x52, + 0x98, 0xc0, 0x28, 0x70, 0xe5, 0xbd, 0x55, 0x0d, 0x62, 0x3a, + 0xd2, 0x8a, 0x1f, 0x47, 0xaf, 0xf7, 0x71, 0x29, 0xc1, 0x99, + 0x0c, 0x54, 0xbc, 0xe4, 0x8b, 0xd3, 0x3b, 0x63, 0xf6, 0xae, + 0x46, 0x1e, 0x57, 0x0f, 0xe7, 0xbf, 0x2a, 0x72, 0x9a, 0xc2, + 0xad, 0xf5, 0x1d, 0x45, 0xd0, 0x88, 0x60, 0x38, 0xbe, 0xe6, + 0x0e, 0x56, 0xc3, 0x9b, 0x73, 0x2b, 0x44, 0x1c, 0xf4, 0xac, + 0x39, 0x61, 0x89, 0xd1, 0x00, 0x59, 0xb2, 0xeb, 0x79, 0x20, + 0xcb, 0x92, 0xf2, 0xab, 0x40, 0x19, 0x8b, 0xd2, 0x39, 0x60, + 0xf9, 0xa0, 0x4b, 0x12, 0x80, 0xd9, 0x32, 0x6b, 0x0b, 0x52, + 0xb9, 0xe0, 0x72, 0x2b, 0xc0, 0x99, 0xef, 0xb6, 0x5d, 0x04, + 0x96, 0xcf, 0x24, 0x7d, 0x1d, 0x44, 0xaf, 0xf6, 0x64, 0x3d, + 0xd6, 0x8f, 0x16, 0x4f, 0xa4, 0xfd, 0x6f, 0x36, 0xdd, 0x84, + 0xe4, 0xbd, 0x56, 0x0f, 0x9d, 0xc4, 0x2f, 0x76, 0xc3, 0x9a, + 0x71, 0x28, 0xba, 0xe3, 0x08, 0x51, 0x31, 0x68, 0x83, 0xda, + 0x48, 0x11, 0xfa, 0xa3, 0x3a, 0x63, 0x88, 0xd1, 0x43, 0x1a, + 0xf1, 0xa8, 0xc8, 0x91, 0x7a, 0x23, 0xb1, 0xe8, 0x03, 0x5a, + 0x2c, 0x75, 0x9e, 0xc7, 0x55, 0x0c, 0xe7, 0xbe, 0xde, 0x87, + 0x6c, 0x35, 0xa7, 0xfe, 0x15, 0x4c, 0xd5, 0x8c, 0x67, 0x3e, + 0xac, 0xf5, 0x1e, 0x47, 0x27, 0x7e, 0x95, 0xcc, 0x5e, 0x07, + 0xec, 0xb5, 0x9b, 0xc2, 0x29, 0x70, 0xe2, 0xbb, 0x50, 0x09, + 0x69, 0x30, 0xdb, 0x82, 0x10, 0x49, 0xa2, 0xfb, 0x62, 0x3b, + 0xd0, 0x89, 0x1b, 0x42, 0xa9, 0xf0, 0x90, 0xc9, 0x22, 0x7b, + 0xe9, 0xb0, 0x5b, 0x02, 0x74, 0x2d, 0xc6, 0x9f, 0x0d, 0x54, + 0xbf, 0xe6, 0x86, 0xdf, 0x34, 0x6d, 0xff, 0xa6, 0x4d, 0x14, + 0x8d, 0xd4, 0x3f, 0x66, 0xf4, 0xad, 0x46, 0x1f, 0x7f, 0x26, + 0xcd, 0x94, 0x06, 0x5f, 0xb4, 0xed, 0x58, 0x01, 0xea, 0xb3, + 0x21, 0x78, 0x93, 0xca, 0xaa, 0xf3, 0x18, 0x41, 0xd3, 0x8a, + 0x61, 0x38, 0xa1, 0xf8, 0x13, 0x4a, 0xd8, 0x81, 0x6a, 0x33, + 0x53, 0x0a, 0xe1, 0xb8, 0x2a, 0x73, 0x98, 0xc1, 0xb7, 0xee, + 0x05, 0x5c, 0xce, 0x97, 0x7c, 0x25, 0x45, 0x1c, 0xf7, 0xae, + 0x3c, 0x65, 0x8e, 0xd7, 0x4e, 0x17, 0xfc, 0xa5, 0x37, 0x6e, + 0x85, 0xdc, 0xbc, 0xe5, 0x0e, 0x57, 0xc5, 0x9c, 0x77, 0x2e, + 0x00, 0x5a, 0xb4, 0xee, 0x75, 0x2f, 0xc1, 0x9b, 0xea, 0xb0, + 0x5e, 0x04, 0x9f, 0xc5, 0x2b, 0x71, 0xc9, 0x93, 0x7d, 0x27, + 0xbc, 0xe6, 0x08, 0x52, 0x23, 0x79, 0x97, 0xcd, 0x56, 0x0c, + 0xe2, 0xb8, 0x8f, 0xd5, 0x3b, 0x61, 0xfa, 0xa0, 0x4e, 0x14, + 0x65, 0x3f, 0xd1, 0x8b, 0x10, 0x4a, 0xa4, 0xfe, 0x46, 0x1c, + 0xf2, 0xa8, 0x33, 0x69, 0x87, 0xdd, 0xac, 0xf6, 0x18, 0x42, + 0xd9, 0x83, 0x6d, 0x37, 0x03, 0x59, 0xb7, 0xed, 0x76, 0x2c, + 0xc2, 0x98, 0xe9, 0xb3, 0x5d, 0x07, 0x9c, 0xc6, 0x28, 0x72, + 0xca, 0x90, 0x7e, 0x24, 0xbf, 0xe5, 0x0b, 0x51, 0x20, 0x7a, + 0x94, 0xce, 0x55, 0x0f, 0xe1, 0xbb, 0x8c, 0xd6, 0x38, 0x62, + 0xf9, 0xa3, 0x4d, 0x17, 0x66, 0x3c, 0xd2, 0x88, 0x13, 0x49, + 0xa7, 0xfd, 0x45, 0x1f, 0xf1, 0xab, 0x30, 0x6a, 0x84, 0xde, + 0xaf, 0xf5, 0x1b, 0x41, 0xda, 0x80, 0x6e, 0x34, 0x06, 0x5c, + 0xb2, 0xe8, 0x73, 0x29, 0xc7, 0x9d, 0xec, 0xb6, 0x58, 0x02, + 0x99, 0xc3, 0x2d, 0x77, 0xcf, 0x95, 0x7b, 0x21, 0xba, 0xe0, + 0x0e, 0x54, 0x25, 0x7f, 0x91, 0xcb, 0x50, 0x0a, 0xe4, 0xbe, + 0x89, 0xd3, 0x3d, 0x67, 0xfc, 0xa6, 0x48, 0x12, 0x63, 0x39, + 0xd7, 0x8d, 0x16, 0x4c, 0xa2, 0xf8, 0x40, 0x1a, 0xf4, 0xae, + 0x35, 0x6f, 0x81, 0xdb, 0xaa, 0xf0, 0x1e, 0x44, 0xdf, 0x85, + 0x6b, 0x31, 0x05, 0x5f, 0xb1, 0xeb, 0x70, 0x2a, 0xc4, 0x9e, + 0xef, 0xb5, 0x5b, 0x01, 0x9a, 0xc0, 0x2e, 0x74, 0xcc, 0x96, + 0x78, 0x22, 0xb9, 0xe3, 0x0d, 0x57, 0x26, 0x7c, 0x92, 0xc8, + 0x53, 0x09, 0xe7, 0xbd, 0x8a, 0xd0, 0x3e, 0x64, 0xff, 0xa5, + 0x4b, 0x11, 0x60, 0x3a, 0xd4, 0x8e, 0x15, 0x4f, 0xa1, 0xfb, + 0x43, 0x19, 0xf7, 0xad, 0x36, 0x6c, 0x82, 0xd8, 0xa9, 0xf3, + 0x1d, 0x47, 0xdc, 0x86, 0x68, 0x32, 0x00, 0x5b, 0xb6, 0xed, + 0x71, 0x2a, 0xc7, 0x9c, 0xe2, 0xb9, 0x54, 0x0f, 0x93, 0xc8, + 0x25, 0x7e, 0xd9, 0x82, 0x6f, 0x34, 0xa8, 0xf3, 0x1e, 0x45, + 0x3b, 0x60, 0x8d, 0xd6, 0x4a, 0x11, 0xfc, 0xa7, 0xaf, 0xf4, + 0x19, 0x42, 0xde, 0x85, 0x68, 0x33, 0x4d, 0x16, 0xfb, 0xa0, + 0x3c, 0x67, 0x8a, 0xd1, 0x76, 0x2d, 0xc0, 0x9b, 0x07, 0x5c, + 0xb1, 0xea, 0x94, 0xcf, 0x22, 0x79, 0xe5, 0xbe, 0x53, 0x08, + 0x43, 0x18, 0xf5, 0xae, 0x32, 0x69, 0x84, 0xdf, 0xa1, 0xfa, + 0x17, 0x4c, 0xd0, 0x8b, 0x66, 0x3d, 0x9a, 0xc1, 0x2c, 0x77, + 0xeb, 0xb0, 0x5d, 0x06, 0x78, 0x23, 0xce, 0x95, 0x09, 0x52, + 0xbf, 0xe4, 0xec, 0xb7, 0x5a, 0x01, 0x9d, 0xc6, 0x2b, 0x70, + 0x0e, 0x55, 0xb8, 0xe3, 0x7f, 0x24, 0xc9, 0x92, 0x35, 0x6e, + 0x83, 0xd8, 0x44, 0x1f, 0xf2, 0xa9, 0xd7, 0x8c, 0x61, 0x3a, + 0xa6, 0xfd, 0x10, 0x4b, 0x86, 0xdd, 0x30, 0x6b, 0xf7, 0xac, + 0x41, 0x1a, 0x64, 0x3f, 0xd2, 0x89, 0x15, 0x4e, 0xa3, 0xf8, + 0x5f, 0x04, 0xe9, 0xb2, 0x2e, 0x75, 0x98, 0xc3, 0xbd, 0xe6, + 0x0b, 0x50, 0xcc, 0x97, 0x7a, 0x21, 0x29, 0x72, 0x9f, 0xc4, + 0x58, 0x03, 0xee, 0xb5, 0xcb, 0x90, 0x7d, 0x26, 0xba, 0xe1, + 0x0c, 0x57, 0xf0, 0xab, 0x46, 0x1d, 0x81, 0xda, 0x37, 0x6c, + 0x12, 0x49, 0xa4, 0xff, 0x63, 0x38, 0xd5, 0x8e, 0xc5, 0x9e, + 0x73, 0x28, 0xb4, 0xef, 0x02, 0x59, 0x27, 0x7c, 0x91, 0xca, + 0x56, 0x0d, 0xe0, 0xbb, 0x1c, 0x47, 0xaa, 0xf1, 0x6d, 0x36, + 0xdb, 0x80, 0xfe, 0xa5, 0x48, 0x13, 0x8f, 0xd4, 0x39, 0x62, + 0x6a, 0x31, 0xdc, 0x87, 0x1b, 0x40, 0xad, 0xf6, 0x88, 0xd3, + 0x3e, 0x65, 0xf9, 0xa2, 0x4f, 0x14, 0xb3, 0xe8, 0x05, 0x5e, + 0xc2, 0x99, 0x74, 0x2f, 0x51, 0x0a, 0xe7, 0xbc, 0x20, 0x7b, + 0x96, 0xcd, 0x00, 0x5c, 0xb8, 0xe4, 0x6d, 0x31, 0xd5, 0x89, + 0xda, 0x86, 0x62, 0x3e, 0xb7, 0xeb, 0x0f, 0x53, 0xa9, 0xf5, + 0x11, 0x4d, 0xc4, 0x98, 0x7c, 0x20, 0x73, 0x2f, 0xcb, 0x97, + 0x1e, 0x42, 0xa6, 0xfa, 0x4f, 0x13, 0xf7, 0xab, 0x22, 0x7e, + 0x9a, 0xc6, 0x95, 0xc9, 0x2d, 0x71, 0xf8, 0xa4, 0x40, 0x1c, + 0xe6, 0xba, 0x5e, 0x02, 0x8b, 0xd7, 0x33, 0x6f, 0x3c, 0x60, + 0x84, 0xd8, 0x51, 0x0d, 0xe9, 0xb5, 0x9e, 0xc2, 0x26, 0x7a, + 0xf3, 0xaf, 0x4b, 0x17, 0x44, 0x18, 0xfc, 0xa0, 0x29, 0x75, + 0x91, 0xcd, 0x37, 0x6b, 0x8f, 0xd3, 0x5a, 0x06, 0xe2, 0xbe, + 0xed, 0xb1, 0x55, 0x09, 0x80, 0xdc, 0x38, 0x64, 0xd1, 0x8d, + 0x69, 0x35, 0xbc, 0xe0, 0x04, 0x58, 0x0b, 0x57, 0xb3, 0xef, + 0x66, 0x3a, 0xde, 0x82, 0x78, 0x24, 0xc0, 0x9c, 0x15, 0x49, + 0xad, 0xf1, 0xa2, 0xfe, 0x1a, 0x46, 0xcf, 0x93, 0x77, 0x2b, + 0x21, 0x7d, 0x99, 0xc5, 0x4c, 0x10, 0xf4, 0xa8, 0xfb, 0xa7, + 0x43, 0x1f, 0x96, 0xca, 0x2e, 0x72, 0x88, 0xd4, 0x30, 0x6c, + 0xe5, 0xb9, 0x5d, 0x01, 0x52, 0x0e, 0xea, 0xb6, 0x3f, 0x63, + 0x87, 0xdb, 0x6e, 0x32, 0xd6, 0x8a, 0x03, 0x5f, 0xbb, 0xe7, + 0xb4, 0xe8, 0x0c, 0x50, 0xd9, 0x85, 0x61, 0x3d, 0xc7, 0x9b, + 0x7f, 0x23, 0xaa, 0xf6, 0x12, 0x4e, 0x1d, 0x41, 0xa5, 0xf9, + 0x70, 0x2c, 0xc8, 0x94, 0xbf, 0xe3, 0x07, 0x5b, 0xd2, 0x8e, + 0x6a, 0x36, 0x65, 0x39, 0xdd, 0x81, 0x08, 0x54, 0xb0, 0xec, + 0x16, 0x4a, 0xae, 0xf2, 0x7b, 0x27, 0xc3, 0x9f, 0xcc, 0x90, + 0x74, 0x28, 0xa1, 0xfd, 0x19, 0x45, 0xf0, 0xac, 0x48, 0x14, + 0x9d, 0xc1, 0x25, 0x79, 0x2a, 0x76, 0x92, 0xce, 0x47, 0x1b, + 0xff, 0xa3, 0x59, 0x05, 0xe1, 0xbd, 0x34, 0x68, 0x8c, 0xd0, + 0x83, 0xdf, 0x3b, 0x67, 0xee, 0xb2, 0x56, 0x0a, 0x00, 0x5d, + 0xba, 0xe7, 0x69, 0x34, 0xd3, 0x8e, 0xd2, 0x8f, 0x68, 0x35, + 0xbb, 0xe6, 0x01, 0x5c, 0xb9, 0xe4, 0x03, 0x5e, 0xd0, 0x8d, + 0x6a, 0x37, 0x6b, 0x36, 0xd1, 0x8c, 0x02, 0x5f, 0xb8, 0xe5, + 0x6f, 0x32, 0xd5, 0x88, 0x06, 0x5b, 0xbc, 0xe1, 0xbd, 0xe0, + 0x07, 0x5a, 0xd4, 0x89, 0x6e, 0x33, 0xd6, 0x8b, 0x6c, 0x31, + 0xbf, 0xe2, 0x05, 0x58, 0x04, 0x59, 0xbe, 0xe3, 0x6d, 0x30, + 0xd7, 0x8a, 0xde, 0x83, 0x64, 0x39, 0xb7, 0xea, 0x0d, 0x50, + 0x0c, 0x51, 0xb6, 0xeb, 0x65, 0x38, 0xdf, 0x82, 0x67, 0x3a, + 0xdd, 0x80, 0x0e, 0x53, 0xb4, 0xe9, 0xb5, 0xe8, 0x0f, 0x52, + 0xdc, 0x81, 0x66, 0x3b, 0xb1, 0xec, 0x0b, 0x56, 0xd8, 0x85, + 0x62, 0x3f, 0x63, 0x3e, 0xd9, 0x84, 0x0a, 0x57, 0xb0, 0xed, + 0x08, 0x55, 0xb2, 0xef, 0x61, 0x3c, 0xdb, 0x86, 0xda, 0x87, + 0x60, 0x3d, 0xb3, 0xee, 0x09, 0x54, 0xa1, 0xfc, 0x1b, 0x46, + 0xc8, 0x95, 0x72, 0x2f, 0x73, 0x2e, 0xc9, 0x94, 0x1a, 0x47, + 0xa0, 0xfd, 0x18, 0x45, 0xa2, 0xff, 0x71, 0x2c, 0xcb, 0x96, + 0xca, 0x97, 0x70, 0x2d, 0xa3, 0xfe, 0x19, 0x44, 0xce, 0x93, + 0x74, 0x29, 0xa7, 0xfa, 0x1d, 0x40, 0x1c, 0x41, 0xa6, 0xfb, + 0x75, 0x28, 0xcf, 0x92, 0x77, 0x2a, 0xcd, 0x90, 0x1e, 0x43, + 0xa4, 0xf9, 0xa5, 0xf8, 0x1f, 0x42, 0xcc, 0x91, 0x76, 0x2b, + 0x7f, 0x22, 0xc5, 0x98, 0x16, 0x4b, 0xac, 0xf1, 0xad, 0xf0, + 0x17, 0x4a, 0xc4, 0x99, 0x7e, 0x23, 0xc6, 0x9b, 0x7c, 0x21, + 0xaf, 0xf2, 0x15, 0x48, 0x14, 0x49, 0xae, 0xf3, 0x7d, 0x20, + 0xc7, 0x9a, 0x10, 0x4d, 0xaa, 0xf7, 0x79, 0x24, 0xc3, 0x9e, + 0xc2, 0x9f, 0x78, 0x25, 0xab, 0xf6, 0x11, 0x4c, 0xa9, 0xf4, + 0x13, 0x4e, 0xc0, 0x9d, 0x7a, 0x27, 0x7b, 0x26, 0xc1, 0x9c, + 0x12, 0x4f, 0xa8, 0xf5, 0x00, 0x5e, 0xbc, 0xe2, 0x65, 0x3b, + 0xd9, 0x87, 0xca, 0x94, 0x76, 0x28, 0xaf, 0xf1, 0x13, 0x4d, + 0x89, 0xd7, 0x35, 0x6b, 0xec, 0xb2, 0x50, 0x0e, 0x43, 0x1d, + 0xff, 0xa1, 0x26, 0x78, 0x9a, 0xc4, 0x0f, 0x51, 0xb3, 0xed, + 0x6a, 0x34, 0xd6, 0x88, 0xc5, 0x9b, 0x79, 0x27, 0xa0, 0xfe, + 0x1c, 0x42, 0x86, 0xd8, 0x3a, 0x64, 0xe3, 0xbd, 0x5f, 0x01, + 0x4c, 0x12, 0xf0, 0xae, 0x29, 0x77, 0x95, 0xcb, 0x1e, 0x40, + 0xa2, 0xfc, 0x7b, 0x25, 0xc7, 0x99, 0xd4, 0x8a, 0x68, 0x36, + 0xb1, 0xef, 0x0d, 0x53, 0x97, 0xc9, 0x2b, 0x75, 0xf2, 0xac, + 0x4e, 0x10, 0x5d, 0x03, 0xe1, 0xbf, 0x38, 0x66, 0x84, 0xda, + 0x11, 0x4f, 0xad, 0xf3, 0x74, 0x2a, 0xc8, 0x96, 0xdb, 0x85, + 0x67, 0x39, 0xbe, 0xe0, 0x02, 0x5c, 0x98, 0xc6, 0x24, 0x7a, + 0xfd, 0xa3, 0x41, 0x1f, 0x52, 0x0c, 0xee, 0xb0, 0x37, 0x69, + 0x8b, 0xd5, 0x3c, 0x62, 0x80, 0xde, 0x59, 0x07, 0xe5, 0xbb, + 0xf6, 0xa8, 0x4a, 0x14, 0x93, 0xcd, 0x2f, 0x71, 0xb5, 0xeb, + 0x09, 0x57, 0xd0, 0x8e, 0x6c, 0x32, 0x7f, 0x21, 0xc3, 0x9d, + 0x1a, 0x44, 0xa6, 0xf8, 0x33, 0x6d, 0x8f, 0xd1, 0x56, 0x08, + 0xea, 0xb4, 0xf9, 0xa7, 0x45, 0x1b, 0x9c, 0xc2, 0x20, 0x7e, + 0xba, 0xe4, 0x06, 0x58, 0xdf, 0x81, 0x63, 0x3d, 0x70, 0x2e, + 0xcc, 0x92, 0x15, 0x4b, 0xa9, 0xf7, 0x22, 0x7c, 0x9e, 0xc0, + 0x47, 0x19, 0xfb, 0xa5, 0xe8, 0xb6, 0x54, 0x0a, 0x8d, 0xd3, + 0x31, 0x6f, 0xab, 0xf5, 0x17, 0x49, 0xce, 0x90, 0x72, 0x2c, + 0x61, 0x3f, 0xdd, 0x83, 0x04, 0x5a, 0xb8, 0xe6, 0x2d, 0x73, + 0x91, 0xcf, 0x48, 0x16, 0xf4, 0xaa, 0xe7, 0xb9, 0x5b, 0x05, + 0x82, 0xdc, 0x3e, 0x60, 0xa4, 0xfa, 0x18, 0x46, 0xc1, 0x9f, + 0x7d, 0x23, 0x6e, 0x30, 0xd2, 0x8c, 0x0b, 0x55, 0xb7, 0xe9, + 0x00, 0x5f, 0xbe, 0xe1, 0x61, 0x3e, 0xdf, 0x80, 0xc2, 0x9d, + 0x7c, 0x23, 0xa3, 0xfc, 0x1d, 0x42, 0x99, 0xc6, 0x27, 0x78, + 0xf8, 0xa7, 0x46, 0x19, 0x5b, 0x04, 0xe5, 0xba, 0x3a, 0x65, + 0x84, 0xdb, 0x2f, 0x70, 0x91, 0xce, 0x4e, 0x11, 0xf0, 0xaf, + 0xed, 0xb2, 0x53, 0x0c, 0x8c, 0xd3, 0x32, 0x6d, 0xb6, 0xe9, + 0x08, 0x57, 0xd7, 0x88, 0x69, 0x36, 0x74, 0x2b, 0xca, 0x95, + 0x15, 0x4a, 0xab, 0xf4, 0x5e, 0x01, 0xe0, 0xbf, 0x3f, 0x60, + 0x81, 0xde, 0x9c, 0xc3, 0x22, 0x7d, 0xfd, 0xa2, 0x43, 0x1c, + 0xc7, 0x98, 0x79, 0x26, 0xa6, 0xf9, 0x18, 0x47, 0x05, 0x5a, + 0xbb, 0xe4, 0x64, 0x3b, 0xda, 0x85, 0x71, 0x2e, 0xcf, 0x90, + 0x10, 0x4f, 0xae, 0xf1, 0xb3, 0xec, 0x0d, 0x52, 0xd2, 0x8d, + 0x6c, 0x33, 0xe8, 0xb7, 0x56, 0x09, 0x89, 0xd6, 0x37, 0x68, + 0x2a, 0x75, 0x94, 0xcb, 0x4b, 0x14, 0xf5, 0xaa, 0xbc, 0xe3, + 0x02, 0x5d, 0xdd, 0x82, 0x63, 0x3c, 0x7e, 0x21, 0xc0, 0x9f, + 0x1f, 0x40, 0xa1, 0xfe, 0x25, 0x7a, 0x9b, 0xc4, 0x44, 0x1b, + 0xfa, 0xa5, 0xe7, 0xb8, 0x59, 0x06, 0x86, 0xd9, 0x38, 0x67, + 0x93, 0xcc, 0x2d, 0x72, 0xf2, 0xad, 0x4c, 0x13, 0x51, 0x0e, + 0xef, 0xb0, 0x30, 0x6f, 0x8e, 0xd1, 0x0a, 0x55, 0xb4, 0xeb, + 0x6b, 0x34, 0xd5, 0x8a, 0xc8, 0x97, 0x76, 0x29, 0xa9, 0xf6, + 0x17, 0x48, 0xe2, 0xbd, 0x5c, 0x03, 0x83, 0xdc, 0x3d, 0x62, + 0x20, 0x7f, 0x9e, 0xc1, 0x41, 0x1e, 0xff, 0xa0, 0x7b, 0x24, + 0xc5, 0x9a, 0x1a, 0x45, 0xa4, 0xfb, 0xb9, 0xe6, 0x07, 0x58, + 0xd8, 0x87, 0x66, 0x39, 0xcd, 0x92, 0x73, 0x2c, 0xac, 0xf3, + 0x12, 0x4d, 0x0f, 0x50, 0xb1, 0xee, 0x6e, 0x31, 0xd0, 0x8f, + 0x54, 0x0b, 0xea, 0xb5, 0x35, 0x6a, 0x8b, 0xd4, 0x96, 0xc9, + 0x28, 0x77, 0xf7, 0xa8, 0x49, 0x16, 0x00, 0x60, 0xc0, 0xa0, + 0x9d, 0xfd, 0x5d, 0x3d, 0x27, 0x47, 0xe7, 0x87, 0xba, 0xda, + 0x7a, 0x1a, 0x4e, 0x2e, 0x8e, 0xee, 0xd3, 0xb3, 0x13, 0x73, + 0x69, 0x09, 0xa9, 0xc9, 0xf4, 0x94, 0x34, 0x54, 0x9c, 0xfc, + 0x5c, 0x3c, 0x01, 0x61, 0xc1, 0xa1, 0xbb, 0xdb, 0x7b, 0x1b, + 0x26, 0x46, 0xe6, 0x86, 0xd2, 0xb2, 0x12, 0x72, 0x4f, 0x2f, + 0x8f, 0xef, 0xf5, 0x95, 0x35, 0x55, 0x68, 0x08, 0xa8, 0xc8, + 0x25, 0x45, 0xe5, 0x85, 0xb8, 0xd8, 0x78, 0x18, 0x02, 0x62, + 0xc2, 0xa2, 0x9f, 0xff, 0x5f, 0x3f, 0x6b, 0x0b, 0xab, 0xcb, + 0xf6, 0x96, 0x36, 0x56, 0x4c, 0x2c, 0x8c, 0xec, 0xd1, 0xb1, + 0x11, 0x71, 0xb9, 0xd9, 0x79, 0x19, 0x24, 0x44, 0xe4, 0x84, + 0x9e, 0xfe, 0x5e, 0x3e, 0x03, 0x63, 0xc3, 0xa3, 0xf7, 0x97, + 0x37, 0x57, 0x6a, 0x0a, 0xaa, 0xca, 0xd0, 0xb0, 0x10, 0x70, + 0x4d, 0x2d, 0x8d, 0xed, 0x4a, 0x2a, 0x8a, 0xea, 0xd7, 0xb7, + 0x17, 0x77, 0x6d, 0x0d, 0xad, 0xcd, 0xf0, 0x90, 0x30, 0x50, + 0x04, 0x64, 0xc4, 0xa4, 0x99, 0xf9, 0x59, 0x39, 0x23, 0x43, + 0xe3, 0x83, 0xbe, 0xde, 0x7e, 0x1e, 0xd6, 0xb6, 0x16, 0x76, + 0x4b, 0x2b, 0x8b, 0xeb, 0xf1, 0x91, 0x31, 0x51, 0x6c, 0x0c, + 0xac, 0xcc, 0x98, 0xf8, 0x58, 0x38, 0x05, 0x65, 0xc5, 0xa5, + 0xbf, 0xdf, 0x7f, 0x1f, 0x22, 0x42, 0xe2, 0x82, 0x6f, 0x0f, + 0xaf, 0xcf, 0xf2, 0x92, 0x32, 0x52, 0x48, 0x28, 0x88, 0xe8, + 0xd5, 0xb5, 0x15, 0x75, 0x21, 0x41, 0xe1, 0x81, 0xbc, 0xdc, + 0x7c, 0x1c, 0x06, 0x66, 0xc6, 0xa6, 0x9b, 0xfb, 0x5b, 0x3b, + 0xf3, 0x93, 0x33, 0x53, 0x6e, 0x0e, 0xae, 0xce, 0xd4, 0xb4, + 0x14, 0x74, 0x49, 0x29, 0x89, 0xe9, 0xbd, 0xdd, 0x7d, 0x1d, + 0x20, 0x40, 0xe0, 0x80, 0x9a, 0xfa, 0x5a, 0x3a, 0x07, 0x67, + 0xc7, 0xa7, 0x00, 0x61, 0xc2, 0xa3, 0x99, 0xf8, 0x5b, 0x3a, + 0x2f, 0x4e, 0xed, 0x8c, 0xb6, 0xd7, 0x74, 0x15, 0x5e, 0x3f, + 0x9c, 0xfd, 0xc7, 0xa6, 0x05, 0x64, 0x71, 0x10, 0xb3, 0xd2, + 0xe8, 0x89, 0x2a, 0x4b, 0xbc, 0xdd, 0x7e, 0x1f, 0x25, 0x44, + 0xe7, 0x86, 0x93, 0xf2, 0x51, 0x30, 0x0a, 0x6b, 0xc8, 0xa9, + 0xe2, 0x83, 0x20, 0x41, 0x7b, 0x1a, 0xb9, 0xd8, 0xcd, 0xac, + 0x0f, 0x6e, 0x54, 0x35, 0x96, 0xf7, 0x65, 0x04, 0xa7, 0xc6, + 0xfc, 0x9d, 0x3e, 0x5f, 0x4a, 0x2b, 0x88, 0xe9, 0xd3, 0xb2, + 0x11, 0x70, 0x3b, 0x5a, 0xf9, 0x98, 0xa2, 0xc3, 0x60, 0x01, + 0x14, 0x75, 0xd6, 0xb7, 0x8d, 0xec, 0x4f, 0x2e, 0xd9, 0xb8, + 0x1b, 0x7a, 0x40, 0x21, 0x82, 0xe3, 0xf6, 0x97, 0x34, 0x55, + 0x6f, 0x0e, 0xad, 0xcc, 0x87, 0xe6, 0x45, 0x24, 0x1e, 0x7f, + 0xdc, 0xbd, 0xa8, 0xc9, 0x6a, 0x0b, 0x31, 0x50, 0xf3, 0x92, + 0xca, 0xab, 0x08, 0x69, 0x53, 0x32, 0x91, 0xf0, 0xe5, 0x84, + 0x27, 0x46, 0x7c, 0x1d, 0xbe, 0xdf, 0x94, 0xf5, 0x56, 0x37, + 0x0d, 0x6c, 0xcf, 0xae, 0xbb, 0xda, 0x79, 0x18, 0x22, 0x43, + 0xe0, 0x81, 0x76, 0x17, 0xb4, 0xd5, 0xef, 0x8e, 0x2d, 0x4c, + 0x59, 0x38, 0x9b, 0xfa, 0xc0, 0xa1, 0x02, 0x63, 0x28, 0x49, + 0xea, 0x8b, 0xb1, 0xd0, 0x73, 0x12, 0x07, 0x66, 0xc5, 0xa4, + 0x9e, 0xff, 0x5c, 0x3d, 0xaf, 0xce, 0x6d, 0x0c, 0x36, 0x57, + 0xf4, 0x95, 0x80, 0xe1, 0x42, 0x23, 0x19, 0x78, 0xdb, 0xba, + 0xf1, 0x90, 0x33, 0x52, 0x68, 0x09, 0xaa, 0xcb, 0xde, 0xbf, + 0x1c, 0x7d, 0x47, 0x26, 0x85, 0xe4, 0x13, 0x72, 0xd1, 0xb0, + 0x8a, 0xeb, 0x48, 0x29, 0x3c, 0x5d, 0xfe, 0x9f, 0xa5, 0xc4, + 0x67, 0x06, 0x4d, 0x2c, 0x8f, 0xee, 0xd4, 0xb5, 0x16, 0x77, + 0x62, 0x03, 0xa0, 0xc1, 0xfb, 0x9a, 0x39, 0x58, 0x00, 0x62, + 0xc4, 0xa6, 0x95, 0xf7, 0x51, 0x33, 0x37, 0x55, 0xf3, 0x91, + 0xa2, 0xc0, 0x66, 0x04, 0x6e, 0x0c, 0xaa, 0xc8, 0xfb, 0x99, + 0x3f, 0x5d, 0x59, 0x3b, 0x9d, 0xff, 0xcc, 0xae, 0x08, 0x6a, + 0xdc, 0xbe, 0x18, 0x7a, 0x49, 0x2b, 0x8d, 0xef, 0xeb, 0x89, + 0x2f, 0x4d, 0x7e, 0x1c, 0xba, 0xd8, 0xb2, 0xd0, 0x76, 0x14, + 0x27, 0x45, 0xe3, 0x81, 0x85, 0xe7, 0x41, 0x23, 0x10, 0x72, + 0xd4, 0xb6, 0xa5, 0xc7, 0x61, 0x03, 0x30, 0x52, 0xf4, 0x96, + 0x92, 0xf0, 0x56, 0x34, 0x07, 0x65, 0xc3, 0xa1, 0xcb, 0xa9, + 0x0f, 0x6d, 0x5e, 0x3c, 0x9a, 0xf8, 0xfc, 0x9e, 0x38, 0x5a, + 0x69, 0x0b, 0xad, 0xcf, 0x79, 0x1b, 0xbd, 0xdf, 0xec, 0x8e, + 0x28, 0x4a, 0x4e, 0x2c, 0x8a, 0xe8, 0xdb, 0xb9, 0x1f, 0x7d, + 0x17, 0x75, 0xd3, 0xb1, 0x82, 0xe0, 0x46, 0x24, 0x20, 0x42, + 0xe4, 0x86, 0xb5, 0xd7, 0x71, 0x13, 0x57, 0x35, 0x93, 0xf1, + 0xc2, 0xa0, 0x06, 0x64, 0x60, 0x02, 0xa4, 0xc6, 0xf5, 0x97, + 0x31, 0x53, 0x39, 0x5b, 0xfd, 0x9f, 0xac, 0xce, 0x68, 0x0a, + 0x0e, 0x6c, 0xca, 0xa8, 0x9b, 0xf9, 0x5f, 0x3d, 0x8b, 0xe9, + 0x4f, 0x2d, 0x1e, 0x7c, 0xda, 0xb8, 0xbc, 0xde, 0x78, 0x1a, + 0x29, 0x4b, 0xed, 0x8f, 0xe5, 0x87, 0x21, 0x43, 0x70, 0x12, + 0xb4, 0xd6, 0xd2, 0xb0, 0x16, 0x74, 0x47, 0x25, 0x83, 0xe1, + 0xf2, 0x90, 0x36, 0x54, 0x67, 0x05, 0xa3, 0xc1, 0xc5, 0xa7, + 0x01, 0x63, 0x50, 0x32, 0x94, 0xf6, 0x9c, 0xfe, 0x58, 0x3a, + 0x09, 0x6b, 0xcd, 0xaf, 0xab, 0xc9, 0x6f, 0x0d, 0x3e, 0x5c, + 0xfa, 0x98, 0x2e, 0x4c, 0xea, 0x88, 0xbb, 0xd9, 0x7f, 0x1d, + 0x19, 0x7b, 0xdd, 0xbf, 0x8c, 0xee, 0x48, 0x2a, 0x40, 0x22, + 0x84, 0xe6, 0xd5, 0xb7, 0x11, 0x73, 0x77, 0x15, 0xb3, 0xd1, + 0xe2, 0x80, 0x26, 0x44, 0x00, 0x63, 0xc6, 0xa5, 0x91, 0xf2, + 0x57, 0x34, 0x3f, 0x5c, 0xf9, 0x9a, 0xae, 0xcd, 0x68, 0x0b, + 0x7e, 0x1d, 0xb8, 0xdb, 0xef, 0x8c, 0x29, 0x4a, 0x41, 0x22, + 0x87, 0xe4, 0xd0, 0xb3, 0x16, 0x75, 0xfc, 0x9f, 0x3a, 0x59, + 0x6d, 0x0e, 0xab, 0xc8, 0xc3, 0xa0, 0x05, 0x66, 0x52, 0x31, + 0x94, 0xf7, 0x82, 0xe1, 0x44, 0x27, 0x13, 0x70, 0xd5, 0xb6, + 0xbd, 0xde, 0x7b, 0x18, 0x2c, 0x4f, 0xea, 0x89, 0xe5, 0x86, + 0x23, 0x40, 0x74, 0x17, 0xb2, 0xd1, 0xda, 0xb9, 0x1c, 0x7f, + 0x4b, 0x28, 0x8d, 0xee, 0x9b, 0xf8, 0x5d, 0x3e, 0x0a, 0x69, + 0xcc, 0xaf, 0xa4, 0xc7, 0x62, 0x01, 0x35, 0x56, 0xf3, 0x90, + 0x19, 0x7a, 0xdf, 0xbc, 0x88, 0xeb, 0x4e, 0x2d, 0x26, 0x45, + 0xe0, 0x83, 0xb7, 0xd4, 0x71, 0x12, 0x67, 0x04, 0xa1, 0xc2, + 0xf6, 0x95, 0x30, 0x53, 0x58, 0x3b, 0x9e, 0xfd, 0xc9, 0xaa, + 0x0f, 0x6c, 0xd7, 0xb4, 0x11, 0x72, 0x46, 0x25, 0x80, 0xe3, + 0xe8, 0x8b, 0x2e, 0x4d, 0x79, 0x1a, 0xbf, 0xdc, 0xa9, 0xca, + 0x6f, 0x0c, 0x38, 0x5b, 0xfe, 0x9d, 0x96, 0xf5, 0x50, 0x33, + 0x07, 0x64, 0xc1, 0xa2, 0x2b, 0x48, 0xed, 0x8e, 0xba, 0xd9, + 0x7c, 0x1f, 0x14, 0x77, 0xd2, 0xb1, 0x85, 0xe6, 0x43, 0x20, + 0x55, 0x36, 0x93, 0xf0, 0xc4, 0xa7, 0x02, 0x61, 0x6a, 0x09, + 0xac, 0xcf, 0xfb, 0x98, 0x3d, 0x5e, 0x32, 0x51, 0xf4, 0x97, + 0xa3, 0xc0, 0x65, 0x06, 0x0d, 0x6e, 0xcb, 0xa8, 0x9c, 0xff, + 0x5a, 0x39, 0x4c, 0x2f, 0x8a, 0xe9, 0xdd, 0xbe, 0x1b, 0x78, + 0x73, 0x10, 0xb5, 0xd6, 0xe2, 0x81, 0x24, 0x47, 0xce, 0xad, + 0x08, 0x6b, 0x5f, 0x3c, 0x99, 0xfa, 0xf1, 0x92, 0x37, 0x54, + 0x60, 0x03, 0xa6, 0xc5, 0xb0, 0xd3, 0x76, 0x15, 0x21, 0x42, + 0xe7, 0x84, 0x8f, 0xec, 0x49, 0x2a, 0x1e, 0x7d, 0xd8, 0xbb, + 0x00, 0x64, 0xc8, 0xac, 0x8d, 0xe9, 0x45, 0x21, 0x07, 0x63, + 0xcf, 0xab, 0x8a, 0xee, 0x42, 0x26, 0x0e, 0x6a, 0xc6, 0xa2, + 0x83, 0xe7, 0x4b, 0x2f, 0x09, 0x6d, 0xc1, 0xa5, 0x84, 0xe0, + 0x4c, 0x28, 0x1c, 0x78, 0xd4, 0xb0, 0x91, 0xf5, 0x59, 0x3d, + 0x1b, 0x7f, 0xd3, 0xb7, 0x96, 0xf2, 0x5e, 0x3a, 0x12, 0x76, + 0xda, 0xbe, 0x9f, 0xfb, 0x57, 0x33, 0x15, 0x71, 0xdd, 0xb9, + 0x98, 0xfc, 0x50, 0x34, 0x38, 0x5c, 0xf0, 0x94, 0xb5, 0xd1, + 0x7d, 0x19, 0x3f, 0x5b, 0xf7, 0x93, 0xb2, 0xd6, 0x7a, 0x1e, + 0x36, 0x52, 0xfe, 0x9a, 0xbb, 0xdf, 0x73, 0x17, 0x31, 0x55, + 0xf9, 0x9d, 0xbc, 0xd8, 0x74, 0x10, 0x24, 0x40, 0xec, 0x88, + 0xa9, 0xcd, 0x61, 0x05, 0x23, 0x47, 0xeb, 0x8f, 0xae, 0xca, + 0x66, 0x02, 0x2a, 0x4e, 0xe2, 0x86, 0xa7, 0xc3, 0x6f, 0x0b, + 0x2d, 0x49, 0xe5, 0x81, 0xa0, 0xc4, 0x68, 0x0c, 0x70, 0x14, + 0xb8, 0xdc, 0xfd, 0x99, 0x35, 0x51, 0x77, 0x13, 0xbf, 0xdb, + 0xfa, 0x9e, 0x32, 0x56, 0x7e, 0x1a, 0xb6, 0xd2, 0xf3, 0x97, + 0x3b, 0x5f, 0x79, 0x1d, 0xb1, 0xd5, 0xf4, 0x90, 0x3c, 0x58, + 0x6c, 0x08, 0xa4, 0xc0, 0xe1, 0x85, 0x29, 0x4d, 0x6b, 0x0f, + 0xa3, 0xc7, 0xe6, 0x82, 0x2e, 0x4a, 0x62, 0x06, 0xaa, 0xce, + 0xef, 0x8b, 0x27, 0x43, 0x65, 0x01, 0xad, 0xc9, 0xe8, 0x8c, + 0x20, 0x44, 0x48, 0x2c, 0x80, 0xe4, 0xc5, 0xa1, 0x0d, 0x69, + 0x4f, 0x2b, 0x87, 0xe3, 0xc2, 0xa6, 0x0a, 0x6e, 0x46, 0x22, + 0x8e, 0xea, 0xcb, 0xaf, 0x03, 0x67, 0x41, 0x25, 0x89, 0xed, + 0xcc, 0xa8, 0x04, 0x60, 0x54, 0x30, 0x9c, 0xf8, 0xd9, 0xbd, + 0x11, 0x75, 0x53, 0x37, 0x9b, 0xff, 0xde, 0xba, 0x16, 0x72, + 0x5a, 0x3e, 0x92, 0xf6, 0xd7, 0xb3, 0x1f, 0x7b, 0x5d, 0x39, + 0x95, 0xf1, 0xd0, 0xb4, 0x18, 0x7c, 0x00, 0x65, 0xca, 0xaf, + 0x89, 0xec, 0x43, 0x26, 0x0f, 0x6a, 0xc5, 0xa0, 0x86, 0xe3, + 0x4c, 0x29, 0x1e, 0x7b, 0xd4, 0xb1, 0x97, 0xf2, 0x5d, 0x38, + 0x11, 0x74, 0xdb, 0xbe, 0x98, 0xfd, 0x52, 0x37, 0x3c, 0x59, + 0xf6, 0x93, 0xb5, 0xd0, 0x7f, 0x1a, 0x33, 0x56, 0xf9, 0x9c, + 0xba, 0xdf, 0x70, 0x15, 0x22, 0x47, 0xe8, 0x8d, 0xab, 0xce, + 0x61, 0x04, 0x2d, 0x48, 0xe7, 0x82, 0xa4, 0xc1, 0x6e, 0x0b, + 0x78, 0x1d, 0xb2, 0xd7, 0xf1, 0x94, 0x3b, 0x5e, 0x77, 0x12, + 0xbd, 0xd8, 0xfe, 0x9b, 0x34, 0x51, 0x66, 0x03, 0xac, 0xc9, + 0xef, 0x8a, 0x25, 0x40, 0x69, 0x0c, 0xa3, 0xc6, 0xe0, 0x85, + 0x2a, 0x4f, 0x44, 0x21, 0x8e, 0xeb, 0xcd, 0xa8, 0x07, 0x62, + 0x4b, 0x2e, 0x81, 0xe4, 0xc2, 0xa7, 0x08, 0x6d, 0x5a, 0x3f, + 0x90, 0xf5, 0xd3, 0xb6, 0x19, 0x7c, 0x55, 0x30, 0x9f, 0xfa, + 0xdc, 0xb9, 0x16, 0x73, 0xf0, 0x95, 0x3a, 0x5f, 0x79, 0x1c, + 0xb3, 0xd6, 0xff, 0x9a, 0x35, 0x50, 0x76, 0x13, 0xbc, 0xd9, + 0xee, 0x8b, 0x24, 0x41, 0x67, 0x02, 0xad, 0xc8, 0xe1, 0x84, + 0x2b, 0x4e, 0x68, 0x0d, 0xa2, 0xc7, 0xcc, 0xa9, 0x06, 0x63, + 0x45, 0x20, 0x8f, 0xea, 0xc3, 0xa6, 0x09, 0x6c, 0x4a, 0x2f, + 0x80, 0xe5, 0xd2, 0xb7, 0x18, 0x7d, 0x5b, 0x3e, 0x91, 0xf4, + 0xdd, 0xb8, 0x17, 0x72, 0x54, 0x31, 0x9e, 0xfb, 0x88, 0xed, + 0x42, 0x27, 0x01, 0x64, 0xcb, 0xae, 0x87, 0xe2, 0x4d, 0x28, + 0x0e, 0x6b, 0xc4, 0xa1, 0x96, 0xf3, 0x5c, 0x39, 0x1f, 0x7a, + 0xd5, 0xb0, 0x99, 0xfc, 0x53, 0x36, 0x10, 0x75, 0xda, 0xbf, + 0xb4, 0xd1, 0x7e, 0x1b, 0x3d, 0x58, 0xf7, 0x92, 0xbb, 0xde, + 0x71, 0x14, 0x32, 0x57, 0xf8, 0x9d, 0xaa, 0xcf, 0x60, 0x05, + 0x23, 0x46, 0xe9, 0x8c, 0xa5, 0xc0, 0x6f, 0x0a, 0x2c, 0x49, + 0xe6, 0x83, 0x00, 0x66, 0xcc, 0xaa, 0x85, 0xe3, 0x49, 0x2f, + 0x17, 0x71, 0xdb, 0xbd, 0x92, 0xf4, 0x5e, 0x38, 0x2e, 0x48, + 0xe2, 0x84, 0xab, 0xcd, 0x67, 0x01, 0x39, 0x5f, 0xf5, 0x93, + 0xbc, 0xda, 0x70, 0x16, 0x5c, 0x3a, 0x90, 0xf6, 0xd9, 0xbf, + 0x15, 0x73, 0x4b, 0x2d, 0x87, 0xe1, 0xce, 0xa8, 0x02, 0x64, + 0x72, 0x14, 0xbe, 0xd8, 0xf7, 0x91, 0x3b, 0x5d, 0x65, 0x03, + 0xa9, 0xcf, 0xe0, 0x86, 0x2c, 0x4a, 0xb8, 0xde, 0x74, 0x12, + 0x3d, 0x5b, 0xf1, 0x97, 0xaf, 0xc9, 0x63, 0x05, 0x2a, 0x4c, + 0xe6, 0x80, 0x96, 0xf0, 0x5a, 0x3c, 0x13, 0x75, 0xdf, 0xb9, + 0x81, 0xe7, 0x4d, 0x2b, 0x04, 0x62, 0xc8, 0xae, 0xe4, 0x82, + 0x28, 0x4e, 0x61, 0x07, 0xad, 0xcb, 0xf3, 0x95, 0x3f, 0x59, + 0x76, 0x10, 0xba, 0xdc, 0xca, 0xac, 0x06, 0x60, 0x4f, 0x29, + 0x83, 0xe5, 0xdd, 0xbb, 0x11, 0x77, 0x58, 0x3e, 0x94, 0xf2, + 0x6d, 0x0b, 0xa1, 0xc7, 0xe8, 0x8e, 0x24, 0x42, 0x7a, 0x1c, + 0xb6, 0xd0, 0xff, 0x99, 0x33, 0x55, 0x43, 0x25, 0x8f, 0xe9, + 0xc6, 0xa0, 0x0a, 0x6c, 0x54, 0x32, 0x98, 0xfe, 0xd1, 0xb7, + 0x1d, 0x7b, 0x31, 0x57, 0xfd, 0x9b, 0xb4, 0xd2, 0x78, 0x1e, + 0x26, 0x40, 0xea, 0x8c, 0xa3, 0xc5, 0x6f, 0x09, 0x1f, 0x79, + 0xd3, 0xb5, 0x9a, 0xfc, 0x56, 0x30, 0x08, 0x6e, 0xc4, 0xa2, + 0x8d, 0xeb, 0x41, 0x27, 0xd5, 0xb3, 0x19, 0x7f, 0x50, 0x36, + 0x9c, 0xfa, 0xc2, 0xa4, 0x0e, 0x68, 0x47, 0x21, 0x8b, 0xed, + 0xfb, 0x9d, 0x37, 0x51, 0x7e, 0x18, 0xb2, 0xd4, 0xec, 0x8a, + 0x20, 0x46, 0x69, 0x0f, 0xa5, 0xc3, 0x89, 0xef, 0x45, 0x23, + 0x0c, 0x6a, 0xc0, 0xa6, 0x9e, 0xf8, 0x52, 0x34, 0x1b, 0x7d, + 0xd7, 0xb1, 0xa7, 0xc1, 0x6b, 0x0d, 0x22, 0x44, 0xee, 0x88, + 0xb0, 0xd6, 0x7c, 0x1a, 0x35, 0x53, 0xf9, 0x9f, 0x00, 0x67, + 0xce, 0xa9, 0x81, 0xe6, 0x4f, 0x28, 0x1f, 0x78, 0xd1, 0xb6, + 0x9e, 0xf9, 0x50, 0x37, 0x3e, 0x59, 0xf0, 0x97, 0xbf, 0xd8, + 0x71, 0x16, 0x21, 0x46, 0xef, 0x88, 0xa0, 0xc7, 0x6e, 0x09, + 0x7c, 0x1b, 0xb2, 0xd5, 0xfd, 0x9a, 0x33, 0x54, 0x63, 0x04, + 0xad, 0xca, 0xe2, 0x85, 0x2c, 0x4b, 0x42, 0x25, 0x8c, 0xeb, + 0xc3, 0xa4, 0x0d, 0x6a, 0x5d, 0x3a, 0x93, 0xf4, 0xdc, 0xbb, + 0x12, 0x75, 0xf8, 0x9f, 0x36, 0x51, 0x79, 0x1e, 0xb7, 0xd0, + 0xe7, 0x80, 0x29, 0x4e, 0x66, 0x01, 0xa8, 0xcf, 0xc6, 0xa1, + 0x08, 0x6f, 0x47, 0x20, 0x89, 0xee, 0xd9, 0xbe, 0x17, 0x70, + 0x58, 0x3f, 0x96, 0xf1, 0x84, 0xe3, 0x4a, 0x2d, 0x05, 0x62, + 0xcb, 0xac, 0x9b, 0xfc, 0x55, 0x32, 0x1a, 0x7d, 0xd4, 0xb3, + 0xba, 0xdd, 0x74, 0x13, 0x3b, 0x5c, 0xf5, 0x92, 0xa5, 0xc2, + 0x6b, 0x0c, 0x24, 0x43, 0xea, 0x8d, 0xed, 0x8a, 0x23, 0x44, + 0x6c, 0x0b, 0xa2, 0xc5, 0xf2, 0x95, 0x3c, 0x5b, 0x73, 0x14, + 0xbd, 0xda, 0xd3, 0xb4, 0x1d, 0x7a, 0x52, 0x35, 0x9c, 0xfb, + 0xcc, 0xab, 0x02, 0x65, 0x4d, 0x2a, 0x83, 0xe4, 0x91, 0xf6, + 0x5f, 0x38, 0x10, 0x77, 0xde, 0xb9, 0x8e, 0xe9, 0x40, 0x27, + 0x0f, 0x68, 0xc1, 0xa6, 0xaf, 0xc8, 0x61, 0x06, 0x2e, 0x49, + 0xe0, 0x87, 0xb0, 0xd7, 0x7e, 0x19, 0x31, 0x56, 0xff, 0x98, + 0x15, 0x72, 0xdb, 0xbc, 0x94, 0xf3, 0x5a, 0x3d, 0x0a, 0x6d, + 0xc4, 0xa3, 0x8b, 0xec, 0x45, 0x22, 0x2b, 0x4c, 0xe5, 0x82, + 0xaa, 0xcd, 0x64, 0x03, 0x34, 0x53, 0xfa, 0x9d, 0xb5, 0xd2, + 0x7b, 0x1c, 0x69, 0x0e, 0xa7, 0xc0, 0xe8, 0x8f, 0x26, 0x41, + 0x76, 0x11, 0xb8, 0xdf, 0xf7, 0x90, 0x39, 0x5e, 0x57, 0x30, + 0x99, 0xfe, 0xd6, 0xb1, 0x18, 0x7f, 0x48, 0x2f, 0x86, 0xe1, + 0xc9, 0xae, 0x07, 0x60, 0x00, 0x68, 0xd0, 0xb8, 0xbd, 0xd5, + 0x6d, 0x05, 0x67, 0x0f, 0xb7, 0xdf, 0xda, 0xb2, 0x0a, 0x62, + 0xce, 0xa6, 0x1e, 0x76, 0x73, 0x1b, 0xa3, 0xcb, 0xa9, 0xc1, + 0x79, 0x11, 0x14, 0x7c, 0xc4, 0xac, 0x81, 0xe9, 0x51, 0x39, + 0x3c, 0x54, 0xec, 0x84, 0xe6, 0x8e, 0x36, 0x5e, 0x5b, 0x33, + 0x8b, 0xe3, 0x4f, 0x27, 0x9f, 0xf7, 0xf2, 0x9a, 0x22, 0x4a, + 0x28, 0x40, 0xf8, 0x90, 0x95, 0xfd, 0x45, 0x2d, 0x1f, 0x77, + 0xcf, 0xa7, 0xa2, 0xca, 0x72, 0x1a, 0x78, 0x10, 0xa8, 0xc0, + 0xc5, 0xad, 0x15, 0x7d, 0xd1, 0xb9, 0x01, 0x69, 0x6c, 0x04, + 0xbc, 0xd4, 0xb6, 0xde, 0x66, 0x0e, 0x0b, 0x63, 0xdb, 0xb3, + 0x9e, 0xf6, 0x4e, 0x26, 0x23, 0x4b, 0xf3, 0x9b, 0xf9, 0x91, + 0x29, 0x41, 0x44, 0x2c, 0x94, 0xfc, 0x50, 0x38, 0x80, 0xe8, + 0xed, 0x85, 0x3d, 0x55, 0x37, 0x5f, 0xe7, 0x8f, 0x8a, 0xe2, + 0x5a, 0x32, 0x3e, 0x56, 0xee, 0x86, 0x83, 0xeb, 0x53, 0x3b, + 0x59, 0x31, 0x89, 0xe1, 0xe4, 0x8c, 0x34, 0x5c, 0xf0, 0x98, + 0x20, 0x48, 0x4d, 0x25, 0x9d, 0xf5, 0x97, 0xff, 0x47, 0x2f, + 0x2a, 0x42, 0xfa, 0x92, 0xbf, 0xd7, 0x6f, 0x07, 0x02, 0x6a, + 0xd2, 0xba, 0xd8, 0xb0, 0x08, 0x60, 0x65, 0x0d, 0xb5, 0xdd, + 0x71, 0x19, 0xa1, 0xc9, 0xcc, 0xa4, 0x1c, 0x74, 0x16, 0x7e, + 0xc6, 0xae, 0xab, 0xc3, 0x7b, 0x13, 0x21, 0x49, 0xf1, 0x99, + 0x9c, 0xf4, 0x4c, 0x24, 0x46, 0x2e, 0x96, 0xfe, 0xfb, 0x93, + 0x2b, 0x43, 0xef, 0x87, 0x3f, 0x57, 0x52, 0x3a, 0x82, 0xea, + 0x88, 0xe0, 0x58, 0x30, 0x35, 0x5d, 0xe5, 0x8d, 0xa0, 0xc8, + 0x70, 0x18, 0x1d, 0x75, 0xcd, 0xa5, 0xc7, 0xaf, 0x17, 0x7f, + 0x7a, 0x12, 0xaa, 0xc2, 0x6e, 0x06, 0xbe, 0xd6, 0xd3, 0xbb, + 0x03, 0x6b, 0x09, 0x61, 0xd9, 0xb1, 0xb4, 0xdc, 0x64, 0x0c, + 0x00, 0x69, 0xd2, 0xbb, 0xb9, 0xd0, 0x6b, 0x02, 0x6f, 0x06, + 0xbd, 0xd4, 0xd6, 0xbf, 0x04, 0x6d, 0xde, 0xb7, 0x0c, 0x65, + 0x67, 0x0e, 0xb5, 0xdc, 0xb1, 0xd8, 0x63, 0x0a, 0x08, 0x61, + 0xda, 0xb3, 0xa1, 0xc8, 0x73, 0x1a, 0x18, 0x71, 0xca, 0xa3, + 0xce, 0xa7, 0x1c, 0x75, 0x77, 0x1e, 0xa5, 0xcc, 0x7f, 0x16, + 0xad, 0xc4, 0xc6, 0xaf, 0x14, 0x7d, 0x10, 0x79, 0xc2, 0xab, + 0xa9, 0xc0, 0x7b, 0x12, 0x5f, 0x36, 0x8d, 0xe4, 0xe6, 0x8f, + 0x34, 0x5d, 0x30, 0x59, 0xe2, 0x8b, 0x89, 0xe0, 0x5b, 0x32, + 0x81, 0xe8, 0x53, 0x3a, 0x38, 0x51, 0xea, 0x83, 0xee, 0x87, + 0x3c, 0x55, 0x57, 0x3e, 0x85, 0xec, 0xfe, 0x97, 0x2c, 0x45, + 0x47, 0x2e, 0x95, 0xfc, 0x91, 0xf8, 0x43, 0x2a, 0x28, 0x41, + 0xfa, 0x93, 0x20, 0x49, 0xf2, 0x9b, 0x99, 0xf0, 0x4b, 0x22, + 0x4f, 0x26, 0x9d, 0xf4, 0xf6, 0x9f, 0x24, 0x4d, 0xbe, 0xd7, + 0x6c, 0x05, 0x07, 0x6e, 0xd5, 0xbc, 0xd1, 0xb8, 0x03, 0x6a, + 0x68, 0x01, 0xba, 0xd3, 0x60, 0x09, 0xb2, 0xdb, 0xd9, 0xb0, + 0x0b, 0x62, 0x0f, 0x66, 0xdd, 0xb4, 0xb6, 0xdf, 0x64, 0x0d, + 0x1f, 0x76, 0xcd, 0xa4, 0xa6, 0xcf, 0x74, 0x1d, 0x70, 0x19, + 0xa2, 0xcb, 0xc9, 0xa0, 0x1b, 0x72, 0xc1, 0xa8, 0x13, 0x7a, + 0x78, 0x11, 0xaa, 0xc3, 0xae, 0xc7, 0x7c, 0x15, 0x17, 0x7e, + 0xc5, 0xac, 0xe1, 0x88, 0x33, 0x5a, 0x58, 0x31, 0x8a, 0xe3, + 0x8e, 0xe7, 0x5c, 0x35, 0x37, 0x5e, 0xe5, 0x8c, 0x3f, 0x56, + 0xed, 0x84, 0x86, 0xef, 0x54, 0x3d, 0x50, 0x39, 0x82, 0xeb, + 0xe9, 0x80, 0x3b, 0x52, 0x40, 0x29, 0x92, 0xfb, 0xf9, 0x90, + 0x2b, 0x42, 0x2f, 0x46, 0xfd, 0x94, 0x96, 0xff, 0x44, 0x2d, + 0x9e, 0xf7, 0x4c, 0x25, 0x27, 0x4e, 0xf5, 0x9c, 0xf1, 0x98, + 0x23, 0x4a, 0x48, 0x21, 0x9a, 0xf3, 0x00, 0x6a, 0xd4, 0xbe, + 0xb5, 0xdf, 0x61, 0x0b, 0x77, 0x1d, 0xa3, 0xc9, 0xc2, 0xa8, + 0x16, 0x7c, 0xee, 0x84, 0x3a, 0x50, 0x5b, 0x31, 0x8f, 0xe5, + 0x99, 0xf3, 0x4d, 0x27, 0x2c, 0x46, 0xf8, 0x92, 0xc1, 0xab, + 0x15, 0x7f, 0x74, 0x1e, 0xa0, 0xca, 0xb6, 0xdc, 0x62, 0x08, + 0x03, 0x69, 0xd7, 0xbd, 0x2f, 0x45, 0xfb, 0x91, 0x9a, 0xf0, + 0x4e, 0x24, 0x58, 0x32, 0x8c, 0xe6, 0xed, 0x87, 0x39, 0x53, + 0x9f, 0xf5, 0x4b, 0x21, 0x2a, 0x40, 0xfe, 0x94, 0xe8, 0x82, + 0x3c, 0x56, 0x5d, 0x37, 0x89, 0xe3, 0x71, 0x1b, 0xa5, 0xcf, + 0xc4, 0xae, 0x10, 0x7a, 0x06, 0x6c, 0xd2, 0xb8, 0xb3, 0xd9, + 0x67, 0x0d, 0x5e, 0x34, 0x8a, 0xe0, 0xeb, 0x81, 0x3f, 0x55, + 0x29, 0x43, 0xfd, 0x97, 0x9c, 0xf6, 0x48, 0x22, 0xb0, 0xda, + 0x64, 0x0e, 0x05, 0x6f, 0xd1, 0xbb, 0xc7, 0xad, 0x13, 0x79, + 0x72, 0x18, 0xa6, 0xcc, 0x23, 0x49, 0xf7, 0x9d, 0x96, 0xfc, + 0x42, 0x28, 0x54, 0x3e, 0x80, 0xea, 0xe1, 0x8b, 0x35, 0x5f, + 0xcd, 0xa7, 0x19, 0x73, 0x78, 0x12, 0xac, 0xc6, 0xba, 0xd0, + 0x6e, 0x04, 0x0f, 0x65, 0xdb, 0xb1, 0xe2, 0x88, 0x36, 0x5c, + 0x57, 0x3d, 0x83, 0xe9, 0x95, 0xff, 0x41, 0x2b, 0x20, 0x4a, + 0xf4, 0x9e, 0x0c, 0x66, 0xd8, 0xb2, 0xb9, 0xd3, 0x6d, 0x07, + 0x7b, 0x11, 0xaf, 0xc5, 0xce, 0xa4, 0x1a, 0x70, 0xbc, 0xd6, + 0x68, 0x02, 0x09, 0x63, 0xdd, 0xb7, 0xcb, 0xa1, 0x1f, 0x75, + 0x7e, 0x14, 0xaa, 0xc0, 0x52, 0x38, 0x86, 0xec, 0xe7, 0x8d, + 0x33, 0x59, 0x25, 0x4f, 0xf1, 0x9b, 0x90, 0xfa, 0x44, 0x2e, + 0x7d, 0x17, 0xa9, 0xc3, 0xc8, 0xa2, 0x1c, 0x76, 0x0a, 0x60, + 0xde, 0xb4, 0xbf, 0xd5, 0x6b, 0x01, 0x93, 0xf9, 0x47, 0x2d, + 0x26, 0x4c, 0xf2, 0x98, 0xe4, 0x8e, 0x30, 0x5a, 0x51, 0x3b, + 0x85, 0xef, 0x00, 0x6b, 0xd6, 0xbd, 0xb1, 0xda, 0x67, 0x0c, + 0x7f, 0x14, 0xa9, 0xc2, 0xce, 0xa5, 0x18, 0x73, 0xfe, 0x95, + 0x28, 0x43, 0x4f, 0x24, 0x99, 0xf2, 0x81, 0xea, 0x57, 0x3c, + 0x30, 0x5b, 0xe6, 0x8d, 0xe1, 0x8a, 0x37, 0x5c, 0x50, 0x3b, + 0x86, 0xed, 0x9e, 0xf5, 0x48, 0x23, 0x2f, 0x44, 0xf9, 0x92, + 0x1f, 0x74, 0xc9, 0xa2, 0xae, 0xc5, 0x78, 0x13, 0x60, 0x0b, + 0xb6, 0xdd, 0xd1, 0xba, 0x07, 0x6c, 0xdf, 0xb4, 0x09, 0x62, + 0x6e, 0x05, 0xb8, 0xd3, 0xa0, 0xcb, 0x76, 0x1d, 0x11, 0x7a, + 0xc7, 0xac, 0x21, 0x4a, 0xf7, 0x9c, 0x90, 0xfb, 0x46, 0x2d, + 0x5e, 0x35, 0x88, 0xe3, 0xef, 0x84, 0x39, 0x52, 0x3e, 0x55, + 0xe8, 0x83, 0x8f, 0xe4, 0x59, 0x32, 0x41, 0x2a, 0x97, 0xfc, + 0xf0, 0x9b, 0x26, 0x4d, 0xc0, 0xab, 0x16, 0x7d, 0x71, 0x1a, + 0xa7, 0xcc, 0xbf, 0xd4, 0x69, 0x02, 0x0e, 0x65, 0xd8, 0xb3, + 0xa3, 0xc8, 0x75, 0x1e, 0x12, 0x79, 0xc4, 0xaf, 0xdc, 0xb7, + 0x0a, 0x61, 0x6d, 0x06, 0xbb, 0xd0, 0x5d, 0x36, 0x8b, 0xe0, + 0xec, 0x87, 0x3a, 0x51, 0x22, 0x49, 0xf4, 0x9f, 0x93, 0xf8, + 0x45, 0x2e, 0x42, 0x29, 0x94, 0xff, 0xf3, 0x98, 0x25, 0x4e, + 0x3d, 0x56, 0xeb, 0x80, 0x8c, 0xe7, 0x5a, 0x31, 0xbc, 0xd7, + 0x6a, 0x01, 0x0d, 0x66, 0xdb, 0xb0, 0xc3, 0xa8, 0x15, 0x7e, + 0x72, 0x19, 0xa4, 0xcf, 0x7c, 0x17, 0xaa, 0xc1, 0xcd, 0xa6, + 0x1b, 0x70, 0x03, 0x68, 0xd5, 0xbe, 0xb2, 0xd9, 0x64, 0x0f, + 0x82, 0xe9, 0x54, 0x3f, 0x33, 0x58, 0xe5, 0x8e, 0xfd, 0x96, + 0x2b, 0x40, 0x4c, 0x27, 0x9a, 0xf1, 0x9d, 0xf6, 0x4b, 0x20, + 0x2c, 0x47, 0xfa, 0x91, 0xe2, 0x89, 0x34, 0x5f, 0x53, 0x38, + 0x85, 0xee, 0x63, 0x08, 0xb5, 0xde, 0xd2, 0xb9, 0x04, 0x6f, + 0x1c, 0x77, 0xca, 0xa1, 0xad, 0xc6, 0x7b, 0x10, 0x00, 0x6c, + 0xd8, 0xb4, 0xad, 0xc1, 0x75, 0x19, 0x47, 0x2b, 0x9f, 0xf3, + 0xea, 0x86, 0x32, 0x5e, 0x8e, 0xe2, 0x56, 0x3a, 0x23, 0x4f, + 0xfb, 0x97, 0xc9, 0xa5, 0x11, 0x7d, 0x64, 0x08, 0xbc, 0xd0, + 0x01, 0x6d, 0xd9, 0xb5, 0xac, 0xc0, 0x74, 0x18, 0x46, 0x2a, + 0x9e, 0xf2, 0xeb, 0x87, 0x33, 0x5f, 0x8f, 0xe3, 0x57, 0x3b, + 0x22, 0x4e, 0xfa, 0x96, 0xc8, 0xa4, 0x10, 0x7c, 0x65, 0x09, + 0xbd, 0xd1, 0x02, 0x6e, 0xda, 0xb6, 0xaf, 0xc3, 0x77, 0x1b, + 0x45, 0x29, 0x9d, 0xf1, 0xe8, 0x84, 0x30, 0x5c, 0x8c, 0xe0, + 0x54, 0x38, 0x21, 0x4d, 0xf9, 0x95, 0xcb, 0xa7, 0x13, 0x7f, + 0x66, 0x0a, 0xbe, 0xd2, 0x03, 0x6f, 0xdb, 0xb7, 0xae, 0xc2, + 0x76, 0x1a, 0x44, 0x28, 0x9c, 0xf0, 0xe9, 0x85, 0x31, 0x5d, + 0x8d, 0xe1, 0x55, 0x39, 0x20, 0x4c, 0xf8, 0x94, 0xca, 0xa6, + 0x12, 0x7e, 0x67, 0x0b, 0xbf, 0xd3, 0x04, 0x68, 0xdc, 0xb0, + 0xa9, 0xc5, 0x71, 0x1d, 0x43, 0x2f, 0x9b, 0xf7, 0xee, 0x82, + 0x36, 0x5a, 0x8a, 0xe6, 0x52, 0x3e, 0x27, 0x4b, 0xff, 0x93, + 0xcd, 0xa1, 0x15, 0x79, 0x60, 0x0c, 0xb8, 0xd4, 0x05, 0x69, + 0xdd, 0xb1, 0xa8, 0xc4, 0x70, 0x1c, 0x42, 0x2e, 0x9a, 0xf6, + 0xef, 0x83, 0x37, 0x5b, 0x8b, 0xe7, 0x53, 0x3f, 0x26, 0x4a, + 0xfe, 0x92, 0xcc, 0xa0, 0x14, 0x78, 0x61, 0x0d, 0xb9, 0xd5, + 0x06, 0x6a, 0xde, 0xb2, 0xab, 0xc7, 0x73, 0x1f, 0x41, 0x2d, + 0x99, 0xf5, 0xec, 0x80, 0x34, 0x58, 0x88, 0xe4, 0x50, 0x3c, + 0x25, 0x49, 0xfd, 0x91, 0xcf, 0xa3, 0x17, 0x7b, 0x62, 0x0e, + 0xba, 0xd6, 0x07, 0x6b, 0xdf, 0xb3, 0xaa, 0xc6, 0x72, 0x1e, + 0x40, 0x2c, 0x98, 0xf4, 0xed, 0x81, 0x35, 0x59, 0x89, 0xe5, + 0x51, 0x3d, 0x24, 0x48, 0xfc, 0x90, 0xce, 0xa2, 0x16, 0x7a, + 0x63, 0x0f, 0xbb, 0xd7, 0x00, 0x6d, 0xda, 0xb7, 0xa9, 0xc4, + 0x73, 0x1e, 0x4f, 0x22, 0x95, 0xf8, 0xe6, 0x8b, 0x3c, 0x51, + 0x9e, 0xf3, 0x44, 0x29, 0x37, 0x5a, 0xed, 0x80, 0xd1, 0xbc, + 0x0b, 0x66, 0x78, 0x15, 0xa2, 0xcf, 0x21, 0x4c, 0xfb, 0x96, + 0x88, 0xe5, 0x52, 0x3f, 0x6e, 0x03, 0xb4, 0xd9, 0xc7, 0xaa, + 0x1d, 0x70, 0xbf, 0xd2, 0x65, 0x08, 0x16, 0x7b, 0xcc, 0xa1, + 0xf0, 0x9d, 0x2a, 0x47, 0x59, 0x34, 0x83, 0xee, 0x42, 0x2f, + 0x98, 0xf5, 0xeb, 0x86, 0x31, 0x5c, 0x0d, 0x60, 0xd7, 0xba, + 0xa4, 0xc9, 0x7e, 0x13, 0xdc, 0xb1, 0x06, 0x6b, 0x75, 0x18, + 0xaf, 0xc2, 0x93, 0xfe, 0x49, 0x24, 0x3a, 0x57, 0xe0, 0x8d, + 0x63, 0x0e, 0xb9, 0xd4, 0xca, 0xa7, 0x10, 0x7d, 0x2c, 0x41, + 0xf6, 0x9b, 0x85, 0xe8, 0x5f, 0x32, 0xfd, 0x90, 0x27, 0x4a, + 0x54, 0x39, 0x8e, 0xe3, 0xb2, 0xdf, 0x68, 0x05, 0x1b, 0x76, + 0xc1, 0xac, 0x84, 0xe9, 0x5e, 0x33, 0x2d, 0x40, 0xf7, 0x9a, + 0xcb, 0xa6, 0x11, 0x7c, 0x62, 0x0f, 0xb8, 0xd5, 0x1a, 0x77, + 0xc0, 0xad, 0xb3, 0xde, 0x69, 0x04, 0x55, 0x38, 0x8f, 0xe2, + 0xfc, 0x91, 0x26, 0x4b, 0xa5, 0xc8, 0x7f, 0x12, 0x0c, 0x61, + 0xd6, 0xbb, 0xea, 0x87, 0x30, 0x5d, 0x43, 0x2e, 0x99, 0xf4, + 0x3b, 0x56, 0xe1, 0x8c, 0x92, 0xff, 0x48, 0x25, 0x74, 0x19, + 0xae, 0xc3, 0xdd, 0xb0, 0x07, 0x6a, 0xc6, 0xab, 0x1c, 0x71, + 0x6f, 0x02, 0xb5, 0xd8, 0x89, 0xe4, 0x53, 0x3e, 0x20, 0x4d, + 0xfa, 0x97, 0x58, 0x35, 0x82, 0xef, 0xf1, 0x9c, 0x2b, 0x46, + 0x17, 0x7a, 0xcd, 0xa0, 0xbe, 0xd3, 0x64, 0x09, 0xe7, 0x8a, + 0x3d, 0x50, 0x4e, 0x23, 0x94, 0xf9, 0xa8, 0xc5, 0x72, 0x1f, + 0x01, 0x6c, 0xdb, 0xb6, 0x79, 0x14, 0xa3, 0xce, 0xd0, 0xbd, + 0x0a, 0x67, 0x36, 0x5b, 0xec, 0x81, 0x9f, 0xf2, 0x45, 0x28, + 0x00, 0x6e, 0xdc, 0xb2, 0xa5, 0xcb, 0x79, 0x17, 0x57, 0x39, + 0x8b, 0xe5, 0xf2, 0x9c, 0x2e, 0x40, 0xae, 0xc0, 0x72, 0x1c, + 0x0b, 0x65, 0xd7, 0xb9, 0xf9, 0x97, 0x25, 0x4b, 0x5c, 0x32, + 0x80, 0xee, 0x41, 0x2f, 0x9d, 0xf3, 0xe4, 0x8a, 0x38, 0x56, + 0x16, 0x78, 0xca, 0xa4, 0xb3, 0xdd, 0x6f, 0x01, 0xef, 0x81, + 0x33, 0x5d, 0x4a, 0x24, 0x96, 0xf8, 0xb8, 0xd6, 0x64, 0x0a, + 0x1d, 0x73, 0xc1, 0xaf, 0x82, 0xec, 0x5e, 0x30, 0x27, 0x49, + 0xfb, 0x95, 0xd5, 0xbb, 0x09, 0x67, 0x70, 0x1e, 0xac, 0xc2, + 0x2c, 0x42, 0xf0, 0x9e, 0x89, 0xe7, 0x55, 0x3b, 0x7b, 0x15, + 0xa7, 0xc9, 0xde, 0xb0, 0x02, 0x6c, 0xc3, 0xad, 0x1f, 0x71, + 0x66, 0x08, 0xba, 0xd4, 0x94, 0xfa, 0x48, 0x26, 0x31, 0x5f, + 0xed, 0x83, 0x6d, 0x03, 0xb1, 0xdf, 0xc8, 0xa6, 0x14, 0x7a, + 0x3a, 0x54, 0xe6, 0x88, 0x9f, 0xf1, 0x43, 0x2d, 0x19, 0x77, + 0xc5, 0xab, 0xbc, 0xd2, 0x60, 0x0e, 0x4e, 0x20, 0x92, 0xfc, + 0xeb, 0x85, 0x37, 0x59, 0xb7, 0xd9, 0x6b, 0x05, 0x12, 0x7c, + 0xce, 0xa0, 0xe0, 0x8e, 0x3c, 0x52, 0x45, 0x2b, 0x99, 0xf7, + 0x58, 0x36, 0x84, 0xea, 0xfd, 0x93, 0x21, 0x4f, 0x0f, 0x61, + 0xd3, 0xbd, 0xaa, 0xc4, 0x76, 0x18, 0xf6, 0x98, 0x2a, 0x44, + 0x53, 0x3d, 0x8f, 0xe1, 0xa1, 0xcf, 0x7d, 0x13, 0x04, 0x6a, + 0xd8, 0xb6, 0x9b, 0xf5, 0x47, 0x29, 0x3e, 0x50, 0xe2, 0x8c, + 0xcc, 0xa2, 0x10, 0x7e, 0x69, 0x07, 0xb5, 0xdb, 0x35, 0x5b, + 0xe9, 0x87, 0x90, 0xfe, 0x4c, 0x22, 0x62, 0x0c, 0xbe, 0xd0, + 0xc7, 0xa9, 0x1b, 0x75, 0xda, 0xb4, 0x06, 0x68, 0x7f, 0x11, + 0xa3, 0xcd, 0x8d, 0xe3, 0x51, 0x3f, 0x28, 0x46, 0xf4, 0x9a, + 0x74, 0x1a, 0xa8, 0xc6, 0xd1, 0xbf, 0x0d, 0x63, 0x23, 0x4d, + 0xff, 0x91, 0x86, 0xe8, 0x5a, 0x34, 0x00, 0x6f, 0xde, 0xb1, + 0xa1, 0xce, 0x7f, 0x10, 0x5f, 0x30, 0x81, 0xee, 0xfe, 0x91, + 0x20, 0x4f, 0xbe, 0xd1, 0x60, 0x0f, 0x1f, 0x70, 0xc1, 0xae, + 0xe1, 0x8e, 0x3f, 0x50, 0x40, 0x2f, 0x9e, 0xf1, 0x61, 0x0e, + 0xbf, 0xd0, 0xc0, 0xaf, 0x1e, 0x71, 0x3e, 0x51, 0xe0, 0x8f, + 0x9f, 0xf0, 0x41, 0x2e, 0xdf, 0xb0, 0x01, 0x6e, 0x7e, 0x11, + 0xa0, 0xcf, 0x80, 0xef, 0x5e, 0x31, 0x21, 0x4e, 0xff, 0x90, + 0xc2, 0xad, 0x1c, 0x73, 0x63, 0x0c, 0xbd, 0xd2, 0x9d, 0xf2, + 0x43, 0x2c, 0x3c, 0x53, 0xe2, 0x8d, 0x7c, 0x13, 0xa2, 0xcd, + 0xdd, 0xb2, 0x03, 0x6c, 0x23, 0x4c, 0xfd, 0x92, 0x82, 0xed, + 0x5c, 0x33, 0xa3, 0xcc, 0x7d, 0x12, 0x02, 0x6d, 0xdc, 0xb3, + 0xfc, 0x93, 0x22, 0x4d, 0x5d, 0x32, 0x83, 0xec, 0x1d, 0x72, + 0xc3, 0xac, 0xbc, 0xd3, 0x62, 0x0d, 0x42, 0x2d, 0x9c, 0xf3, + 0xe3, 0x8c, 0x3d, 0x52, 0x99, 0xf6, 0x47, 0x28, 0x38, 0x57, + 0xe6, 0x89, 0xc6, 0xa9, 0x18, 0x77, 0x67, 0x08, 0xb9, 0xd6, + 0x27, 0x48, 0xf9, 0x96, 0x86, 0xe9, 0x58, 0x37, 0x78, 0x17, + 0xa6, 0xc9, 0xd9, 0xb6, 0x07, 0x68, 0xf8, 0x97, 0x26, 0x49, + 0x59, 0x36, 0x87, 0xe8, 0xa7, 0xc8, 0x79, 0x16, 0x06, 0x69, + 0xd8, 0xb7, 0x46, 0x29, 0x98, 0xf7, 0xe7, 0x88, 0x39, 0x56, + 0x19, 0x76, 0xc7, 0xa8, 0xb8, 0xd7, 0x66, 0x09, 0x5b, 0x34, + 0x85, 0xea, 0xfa, 0x95, 0x24, 0x4b, 0x04, 0x6b, 0xda, 0xb5, + 0xa5, 0xca, 0x7b, 0x14, 0xe5, 0x8a, 0x3b, 0x54, 0x44, 0x2b, + 0x9a, 0xf5, 0xba, 0xd5, 0x64, 0x0b, 0x1b, 0x74, 0xc5, 0xaa, + 0x3a, 0x55, 0xe4, 0x8b, 0x9b, 0xf4, 0x45, 0x2a, 0x65, 0x0a, + 0xbb, 0xd4, 0xc4, 0xab, 0x1a, 0x75, 0x84, 0xeb, 0x5a, 0x35, + 0x25, 0x4a, 0xfb, 0x94, 0xdb, 0xb4, 0x05, 0x6a, 0x7a, 0x15, + 0xa4, 0xcb, 0x00, 0x70, 0xe0, 0x90, 0xdd, 0xad, 0x3d, 0x4d, + 0xa7, 0xd7, 0x47, 0x37, 0x7a, 0x0a, 0x9a, 0xea, 0x53, 0x23, + 0xb3, 0xc3, 0x8e, 0xfe, 0x6e, 0x1e, 0xf4, 0x84, 0x14, 0x64, + 0x29, 0x59, 0xc9, 0xb9, 0xa6, 0xd6, 0x46, 0x36, 0x7b, 0x0b, + 0x9b, 0xeb, 0x01, 0x71, 0xe1, 0x91, 0xdc, 0xac, 0x3c, 0x4c, + 0xf5, 0x85, 0x15, 0x65, 0x28, 0x58, 0xc8, 0xb8, 0x52, 0x22, + 0xb2, 0xc2, 0x8f, 0xff, 0x6f, 0x1f, 0x51, 0x21, 0xb1, 0xc1, + 0x8c, 0xfc, 0x6c, 0x1c, 0xf6, 0x86, 0x16, 0x66, 0x2b, 0x5b, + 0xcb, 0xbb, 0x02, 0x72, 0xe2, 0x92, 0xdf, 0xaf, 0x3f, 0x4f, + 0xa5, 0xd5, 0x45, 0x35, 0x78, 0x08, 0x98, 0xe8, 0xf7, 0x87, + 0x17, 0x67, 0x2a, 0x5a, 0xca, 0xba, 0x50, 0x20, 0xb0, 0xc0, + 0x8d, 0xfd, 0x6d, 0x1d, 0xa4, 0xd4, 0x44, 0x34, 0x79, 0x09, + 0x99, 0xe9, 0x03, 0x73, 0xe3, 0x93, 0xde, 0xae, 0x3e, 0x4e, + 0xa2, 0xd2, 0x42, 0x32, 0x7f, 0x0f, 0x9f, 0xef, 0x05, 0x75, + 0xe5, 0x95, 0xd8, 0xa8, 0x38, 0x48, 0xf1, 0x81, 0x11, 0x61, + 0x2c, 0x5c, 0xcc, 0xbc, 0x56, 0x26, 0xb6, 0xc6, 0x8b, 0xfb, + 0x6b, 0x1b, 0x04, 0x74, 0xe4, 0x94, 0xd9, 0xa9, 0x39, 0x49, + 0xa3, 0xd3, 0x43, 0x33, 0x7e, 0x0e, 0x9e, 0xee, 0x57, 0x27, + 0xb7, 0xc7, 0x8a, 0xfa, 0x6a, 0x1a, 0xf0, 0x80, 0x10, 0x60, + 0x2d, 0x5d, 0xcd, 0xbd, 0xf3, 0x83, 0x13, 0x63, 0x2e, 0x5e, + 0xce, 0xbe, 0x54, 0x24, 0xb4, 0xc4, 0x89, 0xf9, 0x69, 0x19, + 0xa0, 0xd0, 0x40, 0x30, 0x7d, 0x0d, 0x9d, 0xed, 0x07, 0x77, + 0xe7, 0x97, 0xda, 0xaa, 0x3a, 0x4a, 0x55, 0x25, 0xb5, 0xc5, + 0x88, 0xf8, 0x68, 0x18, 0xf2, 0x82, 0x12, 0x62, 0x2f, 0x5f, + 0xcf, 0xbf, 0x06, 0x76, 0xe6, 0x96, 0xdb, 0xab, 0x3b, 0x4b, + 0xa1, 0xd1, 0x41, 0x31, 0x7c, 0x0c, 0x9c, 0xec, 0x00, 0x71, + 0xe2, 0x93, 0xd9, 0xa8, 0x3b, 0x4a, 0xaf, 0xde, 0x4d, 0x3c, + 0x76, 0x07, 0x94, 0xe5, 0x43, 0x32, 0xa1, 0xd0, 0x9a, 0xeb, + 0x78, 0x09, 0xec, 0x9d, 0x0e, 0x7f, 0x35, 0x44, 0xd7, 0xa6, + 0x86, 0xf7, 0x64, 0x15, 0x5f, 0x2e, 0xbd, 0xcc, 0x29, 0x58, + 0xcb, 0xba, 0xf0, 0x81, 0x12, 0x63, 0xc5, 0xb4, 0x27, 0x56, + 0x1c, 0x6d, 0xfe, 0x8f, 0x6a, 0x1b, 0x88, 0xf9, 0xb3, 0xc2, + 0x51, 0x20, 0x11, 0x60, 0xf3, 0x82, 0xc8, 0xb9, 0x2a, 0x5b, + 0xbe, 0xcf, 0x5c, 0x2d, 0x67, 0x16, 0x85, 0xf4, 0x52, 0x23, + 0xb0, 0xc1, 0x8b, 0xfa, 0x69, 0x18, 0xfd, 0x8c, 0x1f, 0x6e, + 0x24, 0x55, 0xc6, 0xb7, 0x97, 0xe6, 0x75, 0x04, 0x4e, 0x3f, + 0xac, 0xdd, 0x38, 0x49, 0xda, 0xab, 0xe1, 0x90, 0x03, 0x72, + 0xd4, 0xa5, 0x36, 0x47, 0x0d, 0x7c, 0xef, 0x9e, 0x7b, 0x0a, + 0x99, 0xe8, 0xa2, 0xd3, 0x40, 0x31, 0x22, 0x53, 0xc0, 0xb1, + 0xfb, 0x8a, 0x19, 0x68, 0x8d, 0xfc, 0x6f, 0x1e, 0x54, 0x25, + 0xb6, 0xc7, 0x61, 0x10, 0x83, 0xf2, 0xb8, 0xc9, 0x5a, 0x2b, + 0xce, 0xbf, 0x2c, 0x5d, 0x17, 0x66, 0xf5, 0x84, 0xa4, 0xd5, + 0x46, 0x37, 0x7d, 0x0c, 0x9f, 0xee, 0x0b, 0x7a, 0xe9, 0x98, + 0xd2, 0xa3, 0x30, 0x41, 0xe7, 0x96, 0x05, 0x74, 0x3e, 0x4f, + 0xdc, 0xad, 0x48, 0x39, 0xaa, 0xdb, 0x91, 0xe0, 0x73, 0x02, + 0x33, 0x42, 0xd1, 0xa0, 0xea, 0x9b, 0x08, 0x79, 0x9c, 0xed, + 0x7e, 0x0f, 0x45, 0x34, 0xa7, 0xd6, 0x70, 0x01, 0x92, 0xe3, + 0xa9, 0xd8, 0x4b, 0x3a, 0xdf, 0xae, 0x3d, 0x4c, 0x06, 0x77, + 0xe4, 0x95, 0xb5, 0xc4, 0x57, 0x26, 0x6c, 0x1d, 0x8e, 0xff, + 0x1a, 0x6b, 0xf8, 0x89, 0xc3, 0xb2, 0x21, 0x50, 0xf6, 0x87, + 0x14, 0x65, 0x2f, 0x5e, 0xcd, 0xbc, 0x59, 0x28, 0xbb, 0xca, + 0x80, 0xf1, 0x62, 0x13, 0x00, 0x72, 0xe4, 0x96, 0xd5, 0xa7, + 0x31, 0x43, 0xb7, 0xc5, 0x53, 0x21, 0x62, 0x10, 0x86, 0xf4, + 0x73, 0x01, 0x97, 0xe5, 0xa6, 0xd4, 0x42, 0x30, 0xc4, 0xb6, + 0x20, 0x52, 0x11, 0x63, 0xf5, 0x87, 0xe6, 0x94, 0x02, 0x70, + 0x33, 0x41, 0xd7, 0xa5, 0x51, 0x23, 0xb5, 0xc7, 0x84, 0xf6, + 0x60, 0x12, 0x95, 0xe7, 0x71, 0x03, 0x40, 0x32, 0xa4, 0xd6, + 0x22, 0x50, 0xc6, 0xb4, 0xf7, 0x85, 0x13, 0x61, 0xd1, 0xa3, + 0x35, 0x47, 0x04, 0x76, 0xe0, 0x92, 0x66, 0x14, 0x82, 0xf0, + 0xb3, 0xc1, 0x57, 0x25, 0xa2, 0xd0, 0x46, 0x34, 0x77, 0x05, + 0x93, 0xe1, 0x15, 0x67, 0xf1, 0x83, 0xc0, 0xb2, 0x24, 0x56, + 0x37, 0x45, 0xd3, 0xa1, 0xe2, 0x90, 0x06, 0x74, 0x80, 0xf2, + 0x64, 0x16, 0x55, 0x27, 0xb1, 0xc3, 0x44, 0x36, 0xa0, 0xd2, + 0x91, 0xe3, 0x75, 0x07, 0xf3, 0x81, 0x17, 0x65, 0x26, 0x54, + 0xc2, 0xb0, 0xbf, 0xcd, 0x5b, 0x29, 0x6a, 0x18, 0x8e, 0xfc, + 0x08, 0x7a, 0xec, 0x9e, 0xdd, 0xaf, 0x39, 0x4b, 0xcc, 0xbe, + 0x28, 0x5a, 0x19, 0x6b, 0xfd, 0x8f, 0x7b, 0x09, 0x9f, 0xed, + 0xae, 0xdc, 0x4a, 0x38, 0x59, 0x2b, 0xbd, 0xcf, 0x8c, 0xfe, + 0x68, 0x1a, 0xee, 0x9c, 0x0a, 0x78, 0x3b, 0x49, 0xdf, 0xad, + 0x2a, 0x58, 0xce, 0xbc, 0xff, 0x8d, 0x1b, 0x69, 0x9d, 0xef, + 0x79, 0x0b, 0x48, 0x3a, 0xac, 0xde, 0x6e, 0x1c, 0x8a, 0xf8, + 0xbb, 0xc9, 0x5f, 0x2d, 0xd9, 0xab, 0x3d, 0x4f, 0x0c, 0x7e, + 0xe8, 0x9a, 0x1d, 0x6f, 0xf9, 0x8b, 0xc8, 0xba, 0x2c, 0x5e, + 0xaa, 0xd8, 0x4e, 0x3c, 0x7f, 0x0d, 0x9b, 0xe9, 0x88, 0xfa, + 0x6c, 0x1e, 0x5d, 0x2f, 0xb9, 0xcb, 0x3f, 0x4d, 0xdb, 0xa9, + 0xea, 0x98, 0x0e, 0x7c, 0xfb, 0x89, 0x1f, 0x6d, 0x2e, 0x5c, + 0xca, 0xb8, 0x4c, 0x3e, 0xa8, 0xda, 0x99, 0xeb, 0x7d, 0x0f, + 0x00, 0x73, 0xe6, 0x95, 0xd1, 0xa2, 0x37, 0x44, 0xbf, 0xcc, + 0x59, 0x2a, 0x6e, 0x1d, 0x88, 0xfb, 0x63, 0x10, 0x85, 0xf6, + 0xb2, 0xc1, 0x54, 0x27, 0xdc, 0xaf, 0x3a, 0x49, 0x0d, 0x7e, + 0xeb, 0x98, 0xc6, 0xb5, 0x20, 0x53, 0x17, 0x64, 0xf1, 0x82, + 0x79, 0x0a, 0x9f, 0xec, 0xa8, 0xdb, 0x4e, 0x3d, 0xa5, 0xd6, + 0x43, 0x30, 0x74, 0x07, 0x92, 0xe1, 0x1a, 0x69, 0xfc, 0x8f, + 0xcb, 0xb8, 0x2d, 0x5e, 0x91, 0xe2, 0x77, 0x04, 0x40, 0x33, + 0xa6, 0xd5, 0x2e, 0x5d, 0xc8, 0xbb, 0xff, 0x8c, 0x19, 0x6a, + 0xf2, 0x81, 0x14, 0x67, 0x23, 0x50, 0xc5, 0xb6, 0x4d, 0x3e, + 0xab, 0xd8, 0x9c, 0xef, 0x7a, 0x09, 0x57, 0x24, 0xb1, 0xc2, + 0x86, 0xf5, 0x60, 0x13, 0xe8, 0x9b, 0x0e, 0x7d, 0x39, 0x4a, + 0xdf, 0xac, 0x34, 0x47, 0xd2, 0xa1, 0xe5, 0x96, 0x03, 0x70, + 0x8b, 0xf8, 0x6d, 0x1e, 0x5a, 0x29, 0xbc, 0xcf, 0x3f, 0x4c, + 0xd9, 0xaa, 0xee, 0x9d, 0x08, 0x7b, 0x80, 0xf3, 0x66, 0x15, + 0x51, 0x22, 0xb7, 0xc4, 0x5c, 0x2f, 0xba, 0xc9, 0x8d, 0xfe, + 0x6b, 0x18, 0xe3, 0x90, 0x05, 0x76, 0x32, 0x41, 0xd4, 0xa7, + 0xf9, 0x8a, 0x1f, 0x6c, 0x28, 0x5b, 0xce, 0xbd, 0x46, 0x35, + 0xa0, 0xd3, 0x97, 0xe4, 0x71, 0x02, 0x9a, 0xe9, 0x7c, 0x0f, + 0x4b, 0x38, 0xad, 0xde, 0x25, 0x56, 0xc3, 0xb0, 0xf4, 0x87, + 0x12, 0x61, 0xae, 0xdd, 0x48, 0x3b, 0x7f, 0x0c, 0x99, 0xea, + 0x11, 0x62, 0xf7, 0x84, 0xc0, 0xb3, 0x26, 0x55, 0xcd, 0xbe, + 0x2b, 0x58, 0x1c, 0x6f, 0xfa, 0x89, 0x72, 0x01, 0x94, 0xe7, + 0xa3, 0xd0, 0x45, 0x36, 0x68, 0x1b, 0x8e, 0xfd, 0xb9, 0xca, + 0x5f, 0x2c, 0xd7, 0xa4, 0x31, 0x42, 0x06, 0x75, 0xe0, 0x93, + 0x0b, 0x78, 0xed, 0x9e, 0xda, 0xa9, 0x3c, 0x4f, 0xb4, 0xc7, + 0x52, 0x21, 0x65, 0x16, 0x83, 0xf0, 0x00, 0x74, 0xe8, 0x9c, + 0xcd, 0xb9, 0x25, 0x51, 0x87, 0xf3, 0x6f, 0x1b, 0x4a, 0x3e, + 0xa2, 0xd6, 0x13, 0x67, 0xfb, 0x8f, 0xde, 0xaa, 0x36, 0x42, + 0x94, 0xe0, 0x7c, 0x08, 0x59, 0x2d, 0xb1, 0xc5, 0x26, 0x52, + 0xce, 0xba, 0xeb, 0x9f, 0x03, 0x77, 0xa1, 0xd5, 0x49, 0x3d, + 0x6c, 0x18, 0x84, 0xf0, 0x35, 0x41, 0xdd, 0xa9, 0xf8, 0x8c, + 0x10, 0x64, 0xb2, 0xc6, 0x5a, 0x2e, 0x7f, 0x0b, 0x97, 0xe3, + 0x4c, 0x38, 0xa4, 0xd0, 0x81, 0xf5, 0x69, 0x1d, 0xcb, 0xbf, + 0x23, 0x57, 0x06, 0x72, 0xee, 0x9a, 0x5f, 0x2b, 0xb7, 0xc3, + 0x92, 0xe6, 0x7a, 0x0e, 0xd8, 0xac, 0x30, 0x44, 0x15, 0x61, + 0xfd, 0x89, 0x6a, 0x1e, 0x82, 0xf6, 0xa7, 0xd3, 0x4f, 0x3b, + 0xed, 0x99, 0x05, 0x71, 0x20, 0x54, 0xc8, 0xbc, 0x79, 0x0d, + 0x91, 0xe5, 0xb4, 0xc0, 0x5c, 0x28, 0xfe, 0x8a, 0x16, 0x62, + 0x33, 0x47, 0xdb, 0xaf, 0x98, 0xec, 0x70, 0x04, 0x55, 0x21, + 0xbd, 0xc9, 0x1f, 0x6b, 0xf7, 0x83, 0xd2, 0xa6, 0x3a, 0x4e, + 0x8b, 0xff, 0x63, 0x17, 0x46, 0x32, 0xae, 0xda, 0x0c, 0x78, + 0xe4, 0x90, 0xc1, 0xb5, 0x29, 0x5d, 0xbe, 0xca, 0x56, 0x22, + 0x73, 0x07, 0x9b, 0xef, 0x39, 0x4d, 0xd1, 0xa5, 0xf4, 0x80, + 0x1c, 0x68, 0xad, 0xd9, 0x45, 0x31, 0x60, 0x14, 0x88, 0xfc, + 0x2a, 0x5e, 0xc2, 0xb6, 0xe7, 0x93, 0x0f, 0x7b, 0xd4, 0xa0, + 0x3c, 0x48, 0x19, 0x6d, 0xf1, 0x85, 0x53, 0x27, 0xbb, 0xcf, + 0x9e, 0xea, 0x76, 0x02, 0xc7, 0xb3, 0x2f, 0x5b, 0x0a, 0x7e, + 0xe2, 0x96, 0x40, 0x34, 0xa8, 0xdc, 0x8d, 0xf9, 0x65, 0x11, + 0xf2, 0x86, 0x1a, 0x6e, 0x3f, 0x4b, 0xd7, 0xa3, 0x75, 0x01, + 0x9d, 0xe9, 0xb8, 0xcc, 0x50, 0x24, 0xe1, 0x95, 0x09, 0x7d, + 0x2c, 0x58, 0xc4, 0xb0, 0x66, 0x12, 0x8e, 0xfa, 0xab, 0xdf, + 0x43, 0x37, 0x00, 0x75, 0xea, 0x9f, 0xc9, 0xbc, 0x23, 0x56, + 0x8f, 0xfa, 0x65, 0x10, 0x46, 0x33, 0xac, 0xd9, 0x03, 0x76, + 0xe9, 0x9c, 0xca, 0xbf, 0x20, 0x55, 0x8c, 0xf9, 0x66, 0x13, + 0x45, 0x30, 0xaf, 0xda, 0x06, 0x73, 0xec, 0x99, 0xcf, 0xba, + 0x25, 0x50, 0x89, 0xfc, 0x63, 0x16, 0x40, 0x35, 0xaa, 0xdf, + 0x05, 0x70, 0xef, 0x9a, 0xcc, 0xb9, 0x26, 0x53, 0x8a, 0xff, + 0x60, 0x15, 0x43, 0x36, 0xa9, 0xdc, 0x0c, 0x79, 0xe6, 0x93, + 0xc5, 0xb0, 0x2f, 0x5a, 0x83, 0xf6, 0x69, 0x1c, 0x4a, 0x3f, + 0xa0, 0xd5, 0x0f, 0x7a, 0xe5, 0x90, 0xc6, 0xb3, 0x2c, 0x59, + 0x80, 0xf5, 0x6a, 0x1f, 0x49, 0x3c, 0xa3, 0xd6, 0x0a, 0x7f, + 0xe0, 0x95, 0xc3, 0xb6, 0x29, 0x5c, 0x85, 0xf0, 0x6f, 0x1a, + 0x4c, 0x39, 0xa6, 0xd3, 0x09, 0x7c, 0xe3, 0x96, 0xc0, 0xb5, + 0x2a, 0x5f, 0x86, 0xf3, 0x6c, 0x19, 0x4f, 0x3a, 0xa5, 0xd0, + 0x18, 0x6d, 0xf2, 0x87, 0xd1, 0xa4, 0x3b, 0x4e, 0x97, 0xe2, + 0x7d, 0x08, 0x5e, 0x2b, 0xb4, 0xc1, 0x1b, 0x6e, 0xf1, 0x84, + 0xd2, 0xa7, 0x38, 0x4d, 0x94, 0xe1, 0x7e, 0x0b, 0x5d, 0x28, + 0xb7, 0xc2, 0x1e, 0x6b, 0xf4, 0x81, 0xd7, 0xa2, 0x3d, 0x48, + 0x91, 0xe4, 0x7b, 0x0e, 0x58, 0x2d, 0xb2, 0xc7, 0x1d, 0x68, + 0xf7, 0x82, 0xd4, 0xa1, 0x3e, 0x4b, 0x92, 0xe7, 0x78, 0x0d, + 0x5b, 0x2e, 0xb1, 0xc4, 0x14, 0x61, 0xfe, 0x8b, 0xdd, 0xa8, + 0x37, 0x42, 0x9b, 0xee, 0x71, 0x04, 0x52, 0x27, 0xb8, 0xcd, + 0x17, 0x62, 0xfd, 0x88, 0xde, 0xab, 0x34, 0x41, 0x98, 0xed, + 0x72, 0x07, 0x51, 0x24, 0xbb, 0xce, 0x12, 0x67, 0xf8, 0x8d, + 0xdb, 0xae, 0x31, 0x44, 0x9d, 0xe8, 0x77, 0x02, 0x54, 0x21, + 0xbe, 0xcb, 0x11, 0x64, 0xfb, 0x8e, 0xd8, 0xad, 0x32, 0x47, + 0x9e, 0xeb, 0x74, 0x01, 0x57, 0x22, 0xbd, 0xc8, 0x00, 0x76, + 0xec, 0x9a, 0xc5, 0xb3, 0x29, 0x5f, 0x97, 0xe1, 0x7b, 0x0d, + 0x52, 0x24, 0xbe, 0xc8, 0x33, 0x45, 0xdf, 0xa9, 0xf6, 0x80, + 0x1a, 0x6c, 0xa4, 0xd2, 0x48, 0x3e, 0x61, 0x17, 0x8d, 0xfb, + 0x66, 0x10, 0x8a, 0xfc, 0xa3, 0xd5, 0x4f, 0x39, 0xf1, 0x87, + 0x1d, 0x6b, 0x34, 0x42, 0xd8, 0xae, 0x55, 0x23, 0xb9, 0xcf, + 0x90, 0xe6, 0x7c, 0x0a, 0xc2, 0xb4, 0x2e, 0x58, 0x07, 0x71, + 0xeb, 0x9d, 0xcc, 0xba, 0x20, 0x56, 0x09, 0x7f, 0xe5, 0x93, + 0x5b, 0x2d, 0xb7, 0xc1, 0x9e, 0xe8, 0x72, 0x04, 0xff, 0x89, + 0x13, 0x65, 0x3a, 0x4c, 0xd6, 0xa0, 0x68, 0x1e, 0x84, 0xf2, + 0xad, 0xdb, 0x41, 0x37, 0xaa, 0xdc, 0x46, 0x30, 0x6f, 0x19, + 0x83, 0xf5, 0x3d, 0x4b, 0xd1, 0xa7, 0xf8, 0x8e, 0x14, 0x62, + 0x99, 0xef, 0x75, 0x03, 0x5c, 0x2a, 0xb0, 0xc6, 0x0e, 0x78, + 0xe2, 0x94, 0xcb, 0xbd, 0x27, 0x51, 0x85, 0xf3, 0x69, 0x1f, + 0x40, 0x36, 0xac, 0xda, 0x12, 0x64, 0xfe, 0x88, 0xd7, 0xa1, + 0x3b, 0x4d, 0xb6, 0xc0, 0x5a, 0x2c, 0x73, 0x05, 0x9f, 0xe9, + 0x21, 0x57, 0xcd, 0xbb, 0xe4, 0x92, 0x08, 0x7e, 0xe3, 0x95, + 0x0f, 0x79, 0x26, 0x50, 0xca, 0xbc, 0x74, 0x02, 0x98, 0xee, + 0xb1, 0xc7, 0x5d, 0x2b, 0xd0, 0xa6, 0x3c, 0x4a, 0x15, 0x63, + 0xf9, 0x8f, 0x47, 0x31, 0xab, 0xdd, 0x82, 0xf4, 0x6e, 0x18, + 0x49, 0x3f, 0xa5, 0xd3, 0x8c, 0xfa, 0x60, 0x16, 0xde, 0xa8, + 0x32, 0x44, 0x1b, 0x6d, 0xf7, 0x81, 0x7a, 0x0c, 0x96, 0xe0, + 0xbf, 0xc9, 0x53, 0x25, 0xed, 0x9b, 0x01, 0x77, 0x28, 0x5e, + 0xc4, 0xb2, 0x2f, 0x59, 0xc3, 0xb5, 0xea, 0x9c, 0x06, 0x70, + 0xb8, 0xce, 0x54, 0x22, 0x7d, 0x0b, 0x91, 0xe7, 0x1c, 0x6a, + 0xf0, 0x86, 0xd9, 0xaf, 0x35, 0x43, 0x8b, 0xfd, 0x67, 0x11, + 0x4e, 0x38, 0xa2, 0xd4, 0x00, 0x77, 0xee, 0x99, 0xc1, 0xb6, + 0x2f, 0x58, 0x9f, 0xe8, 0x71, 0x06, 0x5e, 0x29, 0xb0, 0xc7, + 0x23, 0x54, 0xcd, 0xba, 0xe2, 0x95, 0x0c, 0x7b, 0xbc, 0xcb, + 0x52, 0x25, 0x7d, 0x0a, 0x93, 0xe4, 0x46, 0x31, 0xa8, 0xdf, + 0x87, 0xf0, 0x69, 0x1e, 0xd9, 0xae, 0x37, 0x40, 0x18, 0x6f, + 0xf6, 0x81, 0x65, 0x12, 0x8b, 0xfc, 0xa4, 0xd3, 0x4a, 0x3d, + 0xfa, 0x8d, 0x14, 0x63, 0x3b, 0x4c, 0xd5, 0xa2, 0x8c, 0xfb, + 0x62, 0x15, 0x4d, 0x3a, 0xa3, 0xd4, 0x13, 0x64, 0xfd, 0x8a, + 0xd2, 0xa5, 0x3c, 0x4b, 0xaf, 0xd8, 0x41, 0x36, 0x6e, 0x19, + 0x80, 0xf7, 0x30, 0x47, 0xde, 0xa9, 0xf1, 0x86, 0x1f, 0x68, + 0xca, 0xbd, 0x24, 0x53, 0x0b, 0x7c, 0xe5, 0x92, 0x55, 0x22, + 0xbb, 0xcc, 0x94, 0xe3, 0x7a, 0x0d, 0xe9, 0x9e, 0x07, 0x70, + 0x28, 0x5f, 0xc6, 0xb1, 0x76, 0x01, 0x98, 0xef, 0xb7, 0xc0, + 0x59, 0x2e, 0x05, 0x72, 0xeb, 0x9c, 0xc4, 0xb3, 0x2a, 0x5d, + 0x9a, 0xed, 0x74, 0x03, 0x5b, 0x2c, 0xb5, 0xc2, 0x26, 0x51, + 0xc8, 0xbf, 0xe7, 0x90, 0x09, 0x7e, 0xb9, 0xce, 0x57, 0x20, + 0x78, 0x0f, 0x96, 0xe1, 0x43, 0x34, 0xad, 0xda, 0x82, 0xf5, + 0x6c, 0x1b, 0xdc, 0xab, 0x32, 0x45, 0x1d, 0x6a, 0xf3, 0x84, + 0x60, 0x17, 0x8e, 0xf9, 0xa1, 0xd6, 0x4f, 0x38, 0xff, 0x88, + 0x11, 0x66, 0x3e, 0x49, 0xd0, 0xa7, 0x89, 0xfe, 0x67, 0x10, + 0x48, 0x3f, 0xa6, 0xd1, 0x16, 0x61, 0xf8, 0x8f, 0xd7, 0xa0, + 0x39, 0x4e, 0xaa, 0xdd, 0x44, 0x33, 0x6b, 0x1c, 0x85, 0xf2, + 0x35, 0x42, 0xdb, 0xac, 0xf4, 0x83, 0x1a, 0x6d, 0xcf, 0xb8, + 0x21, 0x56, 0x0e, 0x79, 0xe0, 0x97, 0x50, 0x27, 0xbe, 0xc9, + 0x91, 0xe6, 0x7f, 0x08, 0xec, 0x9b, 0x02, 0x75, 0x2d, 0x5a, + 0xc3, 0xb4, 0x73, 0x04, 0x9d, 0xea, 0xb2, 0xc5, 0x5c, 0x2b, + 0x00, 0x78, 0xf0, 0x88, 0xfd, 0x85, 0x0d, 0x75, 0xe7, 0x9f, + 0x17, 0x6f, 0x1a, 0x62, 0xea, 0x92, 0xd3, 0xab, 0x23, 0x5b, + 0x2e, 0x56, 0xde, 0xa6, 0x34, 0x4c, 0xc4, 0xbc, 0xc9, 0xb1, + 0x39, 0x41, 0xbb, 0xc3, 0x4b, 0x33, 0x46, 0x3e, 0xb6, 0xce, + 0x5c, 0x24, 0xac, 0xd4, 0xa1, 0xd9, 0x51, 0x29, 0x68, 0x10, + 0x98, 0xe0, 0x95, 0xed, 0x65, 0x1d, 0x8f, 0xf7, 0x7f, 0x07, + 0x72, 0x0a, 0x82, 0xfa, 0x6b, 0x13, 0x9b, 0xe3, 0x96, 0xee, + 0x66, 0x1e, 0x8c, 0xf4, 0x7c, 0x04, 0x71, 0x09, 0x81, 0xf9, + 0xb8, 0xc0, 0x48, 0x30, 0x45, 0x3d, 0xb5, 0xcd, 0x5f, 0x27, + 0xaf, 0xd7, 0xa2, 0xda, 0x52, 0x2a, 0xd0, 0xa8, 0x20, 0x58, + 0x2d, 0x55, 0xdd, 0xa5, 0x37, 0x4f, 0xc7, 0xbf, 0xca, 0xb2, + 0x3a, 0x42, 0x03, 0x7b, 0xf3, 0x8b, 0xfe, 0x86, 0x0e, 0x76, + 0xe4, 0x9c, 0x14, 0x6c, 0x19, 0x61, 0xe9, 0x91, 0xd6, 0xae, + 0x26, 0x5e, 0x2b, 0x53, 0xdb, 0xa3, 0x31, 0x49, 0xc1, 0xb9, + 0xcc, 0xb4, 0x3c, 0x44, 0x05, 0x7d, 0xf5, 0x8d, 0xf8, 0x80, + 0x08, 0x70, 0xe2, 0x9a, 0x12, 0x6a, 0x1f, 0x67, 0xef, 0x97, + 0x6d, 0x15, 0x9d, 0xe5, 0x90, 0xe8, 0x60, 0x18, 0x8a, 0xf2, + 0x7a, 0x02, 0x77, 0x0f, 0x87, 0xff, 0xbe, 0xc6, 0x4e, 0x36, + 0x43, 0x3b, 0xb3, 0xcb, 0x59, 0x21, 0xa9, 0xd1, 0xa4, 0xdc, + 0x54, 0x2c, 0xbd, 0xc5, 0x4d, 0x35, 0x40, 0x38, 0xb0, 0xc8, + 0x5a, 0x22, 0xaa, 0xd2, 0xa7, 0xdf, 0x57, 0x2f, 0x6e, 0x16, + 0x9e, 0xe6, 0x93, 0xeb, 0x63, 0x1b, 0x89, 0xf1, 0x79, 0x01, + 0x74, 0x0c, 0x84, 0xfc, 0x06, 0x7e, 0xf6, 0x8e, 0xfb, 0x83, + 0x0b, 0x73, 0xe1, 0x99, 0x11, 0x69, 0x1c, 0x64, 0xec, 0x94, + 0xd5, 0xad, 0x25, 0x5d, 0x28, 0x50, 0xd8, 0xa0, 0x32, 0x4a, + 0xc2, 0xba, 0xcf, 0xb7, 0x3f, 0x47, 0x00, 0x79, 0xf2, 0x8b, + 0xf9, 0x80, 0x0b, 0x72, 0xef, 0x96, 0x1d, 0x64, 0x16, 0x6f, + 0xe4, 0x9d, 0xc3, 0xba, 0x31, 0x48, 0x3a, 0x43, 0xc8, 0xb1, + 0x2c, 0x55, 0xde, 0xa7, 0xd5, 0xac, 0x27, 0x5e, 0x9b, 0xe2, + 0x69, 0x10, 0x62, 0x1b, 0x90, 0xe9, 0x74, 0x0d, 0x86, 0xff, + 0x8d, 0xf4, 0x7f, 0x06, 0x58, 0x21, 0xaa, 0xd3, 0xa1, 0xd8, + 0x53, 0x2a, 0xb7, 0xce, 0x45, 0x3c, 0x4e, 0x37, 0xbc, 0xc5, + 0x2b, 0x52, 0xd9, 0xa0, 0xd2, 0xab, 0x20, 0x59, 0xc4, 0xbd, + 0x36, 0x4f, 0x3d, 0x44, 0xcf, 0xb6, 0xe8, 0x91, 0x1a, 0x63, + 0x11, 0x68, 0xe3, 0x9a, 0x07, 0x7e, 0xf5, 0x8c, 0xfe, 0x87, + 0x0c, 0x75, 0xb0, 0xc9, 0x42, 0x3b, 0x49, 0x30, 0xbb, 0xc2, + 0x5f, 0x26, 0xad, 0xd4, 0xa6, 0xdf, 0x54, 0x2d, 0x73, 0x0a, + 0x81, 0xf8, 0x8a, 0xf3, 0x78, 0x01, 0x9c, 0xe5, 0x6e, 0x17, + 0x65, 0x1c, 0x97, 0xee, 0x56, 0x2f, 0xa4, 0xdd, 0xaf, 0xd6, + 0x5d, 0x24, 0xb9, 0xc0, 0x4b, 0x32, 0x40, 0x39, 0xb2, 0xcb, + 0x95, 0xec, 0x67, 0x1e, 0x6c, 0x15, 0x9e, 0xe7, 0x7a, 0x03, + 0x88, 0xf1, 0x83, 0xfa, 0x71, 0x08, 0xcd, 0xb4, 0x3f, 0x46, + 0x34, 0x4d, 0xc6, 0xbf, 0x22, 0x5b, 0xd0, 0xa9, 0xdb, 0xa2, + 0x29, 0x50, 0x0e, 0x77, 0xfc, 0x85, 0xf7, 0x8e, 0x05, 0x7c, + 0xe1, 0x98, 0x13, 0x6a, 0x18, 0x61, 0xea, 0x93, 0x7d, 0x04, + 0x8f, 0xf6, 0x84, 0xfd, 0x76, 0x0f, 0x92, 0xeb, 0x60, 0x19, + 0x6b, 0x12, 0x99, 0xe0, 0xbe, 0xc7, 0x4c, 0x35, 0x47, 0x3e, + 0xb5, 0xcc, 0x51, 0x28, 0xa3, 0xda, 0xa8, 0xd1, 0x5a, 0x23, + 0xe6, 0x9f, 0x14, 0x6d, 0x1f, 0x66, 0xed, 0x94, 0x09, 0x70, + 0xfb, 0x82, 0xf0, 0x89, 0x02, 0x7b, 0x25, 0x5c, 0xd7, 0xae, + 0xdc, 0xa5, 0x2e, 0x57, 0xca, 0xb3, 0x38, 0x41, 0x33, 0x4a, + 0xc1, 0xb8, 0x00, 0x7a, 0xf4, 0x8e, 0xf5, 0x8f, 0x01, 0x7b, + 0xf7, 0x8d, 0x03, 0x79, 0x02, 0x78, 0xf6, 0x8c, 0xf3, 0x89, + 0x07, 0x7d, 0x06, 0x7c, 0xf2, 0x88, 0x04, 0x7e, 0xf0, 0x8a, + 0xf1, 0x8b, 0x05, 0x7f, 0xfb, 0x81, 0x0f, 0x75, 0x0e, 0x74, + 0xfa, 0x80, 0x0c, 0x76, 0xf8, 0x82, 0xf9, 0x83, 0x0d, 0x77, + 0x08, 0x72, 0xfc, 0x86, 0xfd, 0x87, 0x09, 0x73, 0xff, 0x85, + 0x0b, 0x71, 0x0a, 0x70, 0xfe, 0x84, 0xeb, 0x91, 0x1f, 0x65, + 0x1e, 0x64, 0xea, 0x90, 0x1c, 0x66, 0xe8, 0x92, 0xe9, 0x93, + 0x1d, 0x67, 0x18, 0x62, 0xec, 0x96, 0xed, 0x97, 0x19, 0x63, + 0xef, 0x95, 0x1b, 0x61, 0x1a, 0x60, 0xee, 0x94, 0x10, 0x6a, + 0xe4, 0x9e, 0xe5, 0x9f, 0x11, 0x6b, 0xe7, 0x9d, 0x13, 0x69, + 0x12, 0x68, 0xe6, 0x9c, 0xe3, 0x99, 0x17, 0x6d, 0x16, 0x6c, + 0xe2, 0x98, 0x14, 0x6e, 0xe0, 0x9a, 0xe1, 0x9b, 0x15, 0x6f, + 0xcb, 0xb1, 0x3f, 0x45, 0x3e, 0x44, 0xca, 0xb0, 0x3c, 0x46, + 0xc8, 0xb2, 0xc9, 0xb3, 0x3d, 0x47, 0x38, 0x42, 0xcc, 0xb6, + 0xcd, 0xb7, 0x39, 0x43, 0xcf, 0xb5, 0x3b, 0x41, 0x3a, 0x40, + 0xce, 0xb4, 0x30, 0x4a, 0xc4, 0xbe, 0xc5, 0xbf, 0x31, 0x4b, + 0xc7, 0xbd, 0x33, 0x49, 0x32, 0x48, 0xc6, 0xbc, 0xc3, 0xb9, + 0x37, 0x4d, 0x36, 0x4c, 0xc2, 0xb8, 0x34, 0x4e, 0xc0, 0xba, + 0xc1, 0xbb, 0x35, 0x4f, 0x20, 0x5a, 0xd4, 0xae, 0xd5, 0xaf, + 0x21, 0x5b, 0xd7, 0xad, 0x23, 0x59, 0x22, 0x58, 0xd6, 0xac, + 0xd3, 0xa9, 0x27, 0x5d, 0x26, 0x5c, 0xd2, 0xa8, 0x24, 0x5e, + 0xd0, 0xaa, 0xd1, 0xab, 0x25, 0x5f, 0xdb, 0xa1, 0x2f, 0x55, + 0x2e, 0x54, 0xda, 0xa0, 0x2c, 0x56, 0xd8, 0xa2, 0xd9, 0xa3, + 0x2d, 0x57, 0x28, 0x52, 0xdc, 0xa6, 0xdd, 0xa7, 0x29, 0x53, + 0xdf, 0xa5, 0x2b, 0x51, 0x2a, 0x50, 0xde, 0xa4, 0x00, 0x7b, + 0xf6, 0x8d, 0xf1, 0x8a, 0x07, 0x7c, 0xff, 0x84, 0x09, 0x72, + 0x0e, 0x75, 0xf8, 0x83, 0xe3, 0x98, 0x15, 0x6e, 0x12, 0x69, + 0xe4, 0x9f, 0x1c, 0x67, 0xea, 0x91, 0xed, 0x96, 0x1b, 0x60, + 0xdb, 0xa0, 0x2d, 0x56, 0x2a, 0x51, 0xdc, 0xa7, 0x24, 0x5f, + 0xd2, 0xa9, 0xd5, 0xae, 0x23, 0x58, 0x38, 0x43, 0xce, 0xb5, + 0xc9, 0xb2, 0x3f, 0x44, 0xc7, 0xbc, 0x31, 0x4a, 0x36, 0x4d, + 0xc0, 0xbb, 0xab, 0xd0, 0x5d, 0x26, 0x5a, 0x21, 0xac, 0xd7, + 0x54, 0x2f, 0xa2, 0xd9, 0xa5, 0xde, 0x53, 0x28, 0x48, 0x33, + 0xbe, 0xc5, 0xb9, 0xc2, 0x4f, 0x34, 0xb7, 0xcc, 0x41, 0x3a, + 0x46, 0x3d, 0xb0, 0xcb, 0x70, 0x0b, 0x86, 0xfd, 0x81, 0xfa, + 0x77, 0x0c, 0x8f, 0xf4, 0x79, 0x02, 0x7e, 0x05, 0x88, 0xf3, + 0x93, 0xe8, 0x65, 0x1e, 0x62, 0x19, 0x94, 0xef, 0x6c, 0x17, + 0x9a, 0xe1, 0x9d, 0xe6, 0x6b, 0x10, 0x4b, 0x30, 0xbd, 0xc6, + 0xba, 0xc1, 0x4c, 0x37, 0xb4, 0xcf, 0x42, 0x39, 0x45, 0x3e, + 0xb3, 0xc8, 0xa8, 0xd3, 0x5e, 0x25, 0x59, 0x22, 0xaf, 0xd4, + 0x57, 0x2c, 0xa1, 0xda, 0xa6, 0xdd, 0x50, 0x2b, 0x90, 0xeb, + 0x66, 0x1d, 0x61, 0x1a, 0x97, 0xec, 0x6f, 0x14, 0x99, 0xe2, + 0x9e, 0xe5, 0x68, 0x13, 0x73, 0x08, 0x85, 0xfe, 0x82, 0xf9, + 0x74, 0x0f, 0x8c, 0xf7, 0x7a, 0x01, 0x7d, 0x06, 0x8b, 0xf0, + 0xe0, 0x9b, 0x16, 0x6d, 0x11, 0x6a, 0xe7, 0x9c, 0x1f, 0x64, + 0xe9, 0x92, 0xee, 0x95, 0x18, 0x63, 0x03, 0x78, 0xf5, 0x8e, + 0xf2, 0x89, 0x04, 0x7f, 0xfc, 0x87, 0x0a, 0x71, 0x0d, 0x76, + 0xfb, 0x80, 0x3b, 0x40, 0xcd, 0xb6, 0xca, 0xb1, 0x3c, 0x47, + 0xc4, 0xbf, 0x32, 0x49, 0x35, 0x4e, 0xc3, 0xb8, 0xd8, 0xa3, + 0x2e, 0x55, 0x29, 0x52, 0xdf, 0xa4, 0x27, 0x5c, 0xd1, 0xaa, + 0xd6, 0xad, 0x20, 0x5b, 0x00, 0x7c, 0xf8, 0x84, 0xed, 0x91, + 0x15, 0x69, 0xc7, 0xbb, 0x3f, 0x43, 0x2a, 0x56, 0xd2, 0xae, + 0x93, 0xef, 0x6b, 0x17, 0x7e, 0x02, 0x86, 0xfa, 0x54, 0x28, + 0xac, 0xd0, 0xb9, 0xc5, 0x41, 0x3d, 0x3b, 0x47, 0xc3, 0xbf, + 0xd6, 0xaa, 0x2e, 0x52, 0xfc, 0x80, 0x04, 0x78, 0x11, 0x6d, + 0xe9, 0x95, 0xa8, 0xd4, 0x50, 0x2c, 0x45, 0x39, 0xbd, 0xc1, + 0x6f, 0x13, 0x97, 0xeb, 0x82, 0xfe, 0x7a, 0x06, 0x76, 0x0a, + 0x8e, 0xf2, 0x9b, 0xe7, 0x63, 0x1f, 0xb1, 0xcd, 0x49, 0x35, + 0x5c, 0x20, 0xa4, 0xd8, 0xe5, 0x99, 0x1d, 0x61, 0x08, 0x74, + 0xf0, 0x8c, 0x22, 0x5e, 0xda, 0xa6, 0xcf, 0xb3, 0x37, 0x4b, + 0x4d, 0x31, 0xb5, 0xc9, 0xa0, 0xdc, 0x58, 0x24, 0x8a, 0xf6, + 0x72, 0x0e, 0x67, 0x1b, 0x9f, 0xe3, 0xde, 0xa2, 0x26, 0x5a, + 0x33, 0x4f, 0xcb, 0xb7, 0x19, 0x65, 0xe1, 0x9d, 0xf4, 0x88, + 0x0c, 0x70, 0xec, 0x90, 0x14, 0x68, 0x01, 0x7d, 0xf9, 0x85, + 0x2b, 0x57, 0xd3, 0xaf, 0xc6, 0xba, 0x3e, 0x42, 0x7f, 0x03, + 0x87, 0xfb, 0x92, 0xee, 0x6a, 0x16, 0xb8, 0xc4, 0x40, 0x3c, + 0x55, 0x29, 0xad, 0xd1, 0xd7, 0xab, 0x2f, 0x53, 0x3a, 0x46, + 0xc2, 0xbe, 0x10, 0x6c, 0xe8, 0x94, 0xfd, 0x81, 0x05, 0x79, + 0x44, 0x38, 0xbc, 0xc0, 0xa9, 0xd5, 0x51, 0x2d, 0x83, 0xff, + 0x7b, 0x07, 0x6e, 0x12, 0x96, 0xea, 0x9a, 0xe6, 0x62, 0x1e, + 0x77, 0x0b, 0x8f, 0xf3, 0x5d, 0x21, 0xa5, 0xd9, 0xb0, 0xcc, + 0x48, 0x34, 0x09, 0x75, 0xf1, 0x8d, 0xe4, 0x98, 0x1c, 0x60, + 0xce, 0xb2, 0x36, 0x4a, 0x23, 0x5f, 0xdb, 0xa7, 0xa1, 0xdd, + 0x59, 0x25, 0x4c, 0x30, 0xb4, 0xc8, 0x66, 0x1a, 0x9e, 0xe2, + 0x8b, 0xf7, 0x73, 0x0f, 0x32, 0x4e, 0xca, 0xb6, 0xdf, 0xa3, + 0x27, 0x5b, 0xf5, 0x89, 0x0d, 0x71, 0x18, 0x64, 0xe0, 0x9c, + 0x00, 0x7d, 0xfa, 0x87, 0xe9, 0x94, 0x13, 0x6e, 0xcf, 0xb2, + 0x35, 0x48, 0x26, 0x5b, 0xdc, 0xa1, 0x83, 0xfe, 0x79, 0x04, + 0x6a, 0x17, 0x90, 0xed, 0x4c, 0x31, 0xb6, 0xcb, 0xa5, 0xd8, + 0x5f, 0x22, 0x1b, 0x66, 0xe1, 0x9c, 0xf2, 0x8f, 0x08, 0x75, + 0xd4, 0xa9, 0x2e, 0x53, 0x3d, 0x40, 0xc7, 0xba, 0x98, 0xe5, + 0x62, 0x1f, 0x71, 0x0c, 0x8b, 0xf6, 0x57, 0x2a, 0xad, 0xd0, + 0xbe, 0xc3, 0x44, 0x39, 0x36, 0x4b, 0xcc, 0xb1, 0xdf, 0xa2, + 0x25, 0x58, 0xf9, 0x84, 0x03, 0x7e, 0x10, 0x6d, 0xea, 0x97, + 0xb5, 0xc8, 0x4f, 0x32, 0x5c, 0x21, 0xa6, 0xdb, 0x7a, 0x07, + 0x80, 0xfd, 0x93, 0xee, 0x69, 0x14, 0x2d, 0x50, 0xd7, 0xaa, + 0xc4, 0xb9, 0x3e, 0x43, 0xe2, 0x9f, 0x18, 0x65, 0x0b, 0x76, + 0xf1, 0x8c, 0xae, 0xd3, 0x54, 0x29, 0x47, 0x3a, 0xbd, 0xc0, + 0x61, 0x1c, 0x9b, 0xe6, 0x88, 0xf5, 0x72, 0x0f, 0x6c, 0x11, + 0x96, 0xeb, 0x85, 0xf8, 0x7f, 0x02, 0xa3, 0xde, 0x59, 0x24, + 0x4a, 0x37, 0xb0, 0xcd, 0xef, 0x92, 0x15, 0x68, 0x06, 0x7b, + 0xfc, 0x81, 0x20, 0x5d, 0xda, 0xa7, 0xc9, 0xb4, 0x33, 0x4e, + 0x77, 0x0a, 0x8d, 0xf0, 0x9e, 0xe3, 0x64, 0x19, 0xb8, 0xc5, + 0x42, 0x3f, 0x51, 0x2c, 0xab, 0xd6, 0xf4, 0x89, 0x0e, 0x73, + 0x1d, 0x60, 0xe7, 0x9a, 0x3b, 0x46, 0xc1, 0xbc, 0xd2, 0xaf, + 0x28, 0x55, 0x5a, 0x27, 0xa0, 0xdd, 0xb3, 0xce, 0x49, 0x34, + 0x95, 0xe8, 0x6f, 0x12, 0x7c, 0x01, 0x86, 0xfb, 0xd9, 0xa4, + 0x23, 0x5e, 0x30, 0x4d, 0xca, 0xb7, 0x16, 0x6b, 0xec, 0x91, + 0xff, 0x82, 0x05, 0x78, 0x41, 0x3c, 0xbb, 0xc6, 0xa8, 0xd5, + 0x52, 0x2f, 0x8e, 0xf3, 0x74, 0x09, 0x67, 0x1a, 0x9d, 0xe0, + 0xc2, 0xbf, 0x38, 0x45, 0x2b, 0x56, 0xd1, 0xac, 0x0d, 0x70, + 0xf7, 0x8a, 0xe4, 0x99, 0x1e, 0x63, 0x00, 0x7e, 0xfc, 0x82, + 0xe5, 0x9b, 0x19, 0x67, 0xd7, 0xa9, 0x2b, 0x55, 0x32, 0x4c, + 0xce, 0xb0, 0xb3, 0xcd, 0x4f, 0x31, 0x56, 0x28, 0xaa, 0xd4, + 0x64, 0x1a, 0x98, 0xe6, 0x81, 0xff, 0x7d, 0x03, 0x7b, 0x05, + 0x87, 0xf9, 0x9e, 0xe0, 0x62, 0x1c, 0xac, 0xd2, 0x50, 0x2e, + 0x49, 0x37, 0xb5, 0xcb, 0xc8, 0xb6, 0x34, 0x4a, 0x2d, 0x53, + 0xd1, 0xaf, 0x1f, 0x61, 0xe3, 0x9d, 0xfa, 0x84, 0x06, 0x78, + 0xf6, 0x88, 0x0a, 0x74, 0x13, 0x6d, 0xef, 0x91, 0x21, 0x5f, + 0xdd, 0xa3, 0xc4, 0xba, 0x38, 0x46, 0x45, 0x3b, 0xb9, 0xc7, + 0xa0, 0xde, 0x5c, 0x22, 0x92, 0xec, 0x6e, 0x10, 0x77, 0x09, + 0x8b, 0xf5, 0x8d, 0xf3, 0x71, 0x0f, 0x68, 0x16, 0x94, 0xea, + 0x5a, 0x24, 0xa6, 0xd8, 0xbf, 0xc1, 0x43, 0x3d, 0x3e, 0x40, + 0xc2, 0xbc, 0xdb, 0xa5, 0x27, 0x59, 0xe9, 0x97, 0x15, 0x6b, + 0x0c, 0x72, 0xf0, 0x8e, 0xf1, 0x8f, 0x0d, 0x73, 0x14, 0x6a, + 0xe8, 0x96, 0x26, 0x58, 0xda, 0xa4, 0xc3, 0xbd, 0x3f, 0x41, + 0x42, 0x3c, 0xbe, 0xc0, 0xa7, 0xd9, 0x5b, 0x25, 0x95, 0xeb, + 0x69, 0x17, 0x70, 0x0e, 0x8c, 0xf2, 0x8a, 0xf4, 0x76, 0x08, + 0x6f, 0x11, 0x93, 0xed, 0x5d, 0x23, 0xa1, 0xdf, 0xb8, 0xc6, + 0x44, 0x3a, 0x39, 0x47, 0xc5, 0xbb, 0xdc, 0xa2, 0x20, 0x5e, + 0xee, 0x90, 0x12, 0x6c, 0x0b, 0x75, 0xf7, 0x89, 0x07, 0x79, + 0xfb, 0x85, 0xe2, 0x9c, 0x1e, 0x60, 0xd0, 0xae, 0x2c, 0x52, + 0x35, 0x4b, 0xc9, 0xb7, 0xb4, 0xca, 0x48, 0x36, 0x51, 0x2f, + 0xad, 0xd3, 0x63, 0x1d, 0x9f, 0xe1, 0x86, 0xf8, 0x7a, 0x04, + 0x7c, 0x02, 0x80, 0xfe, 0x99, 0xe7, 0x65, 0x1b, 0xab, 0xd5, + 0x57, 0x29, 0x4e, 0x30, 0xb2, 0xcc, 0xcf, 0xb1, 0x33, 0x4d, + 0x2a, 0x54, 0xd6, 0xa8, 0x18, 0x66, 0xe4, 0x9a, 0xfd, 0x83, + 0x01, 0x7f, 0x00, 0x7f, 0xfe, 0x81, 0xe1, 0x9e, 0x1f, 0x60, + 0xdf, 0xa0, 0x21, 0x5e, 0x3e, 0x41, 0xc0, 0xbf, 0xa3, 0xdc, + 0x5d, 0x22, 0x42, 0x3d, 0xbc, 0xc3, 0x7c, 0x03, 0x82, 0xfd, + 0x9d, 0xe2, 0x63, 0x1c, 0x5b, 0x24, 0xa5, 0xda, 0xba, 0xc5, + 0x44, 0x3b, 0x84, 0xfb, 0x7a, 0x05, 0x65, 0x1a, 0x9b, 0xe4, + 0xf8, 0x87, 0x06, 0x79, 0x19, 0x66, 0xe7, 0x98, 0x27, 0x58, + 0xd9, 0xa6, 0xc6, 0xb9, 0x38, 0x47, 0xb6, 0xc9, 0x48, 0x37, + 0x57, 0x28, 0xa9, 0xd6, 0x69, 0x16, 0x97, 0xe8, 0x88, 0xf7, + 0x76, 0x09, 0x15, 0x6a, 0xeb, 0x94, 0xf4, 0x8b, 0x0a, 0x75, + 0xca, 0xb5, 0x34, 0x4b, 0x2b, 0x54, 0xd5, 0xaa, 0xed, 0x92, + 0x13, 0x6c, 0x0c, 0x73, 0xf2, 0x8d, 0x32, 0x4d, 0xcc, 0xb3, + 0xd3, 0xac, 0x2d, 0x52, 0x4e, 0x31, 0xb0, 0xcf, 0xaf, 0xd0, + 0x51, 0x2e, 0x91, 0xee, 0x6f, 0x10, 0x70, 0x0f, 0x8e, 0xf1, + 0x71, 0x0e, 0x8f, 0xf0, 0x90, 0xef, 0x6e, 0x11, 0xae, 0xd1, + 0x50, 0x2f, 0x4f, 0x30, 0xb1, 0xce, 0xd2, 0xad, 0x2c, 0x53, + 0x33, 0x4c, 0xcd, 0xb2, 0x0d, 0x72, 0xf3, 0x8c, 0xec, 0x93, + 0x12, 0x6d, 0x2a, 0x55, 0xd4, 0xab, 0xcb, 0xb4, 0x35, 0x4a, + 0xf5, 0x8a, 0x0b, 0x74, 0x14, 0x6b, 0xea, 0x95, 0x89, 0xf6, + 0x77, 0x08, 0x68, 0x17, 0x96, 0xe9, 0x56, 0x29, 0xa8, 0xd7, + 0xb7, 0xc8, 0x49, 0x36, 0xc7, 0xb8, 0x39, 0x46, 0x26, 0x59, + 0xd8, 0xa7, 0x18, 0x67, 0xe6, 0x99, 0xf9, 0x86, 0x07, 0x78, + 0x64, 0x1b, 0x9a, 0xe5, 0x85, 0xfa, 0x7b, 0x04, 0xbb, 0xc4, + 0x45, 0x3a, 0x5a, 0x25, 0xa4, 0xdb, 0x9c, 0xe3, 0x62, 0x1d, + 0x7d, 0x02, 0x83, 0xfc, 0x43, 0x3c, 0xbd, 0xc2, 0xa2, 0xdd, + 0x5c, 0x23, 0x3f, 0x40, 0xc1, 0xbe, 0xde, 0xa1, 0x20, 0x5f, + 0xe0, 0x9f, 0x1e, 0x61, 0x01, 0x7e, 0xff, 0x80, 0x00, 0x80, + 0x1d, 0x9d, 0x3a, 0xba, 0x27, 0xa7, 0x74, 0xf4, 0x69, 0xe9, + 0x4e, 0xce, 0x53, 0xd3, 0xe8, 0x68, 0xf5, 0x75, 0xd2, 0x52, + 0xcf, 0x4f, 0x9c, 0x1c, 0x81, 0x01, 0xa6, 0x26, 0xbb, 0x3b, + 0xcd, 0x4d, 0xd0, 0x50, 0xf7, 0x77, 0xea, 0x6a, 0xb9, 0x39, + 0xa4, 0x24, 0x83, 0x03, 0x9e, 0x1e, 0x25, 0xa5, 0x38, 0xb8, + 0x1f, 0x9f, 0x02, 0x82, 0x51, 0xd1, 0x4c, 0xcc, 0x6b, 0xeb, + 0x76, 0xf6, 0x87, 0x07, 0x9a, 0x1a, 0xbd, 0x3d, 0xa0, 0x20, + 0xf3, 0x73, 0xee, 0x6e, 0xc9, 0x49, 0xd4, 0x54, 0x6f, 0xef, + 0x72, 0xf2, 0x55, 0xd5, 0x48, 0xc8, 0x1b, 0x9b, 0x06, 0x86, + 0x21, 0xa1, 0x3c, 0xbc, 0x4a, 0xca, 0x57, 0xd7, 0x70, 0xf0, + 0x6d, 0xed, 0x3e, 0xbe, 0x23, 0xa3, 0x04, 0x84, 0x19, 0x99, + 0xa2, 0x22, 0xbf, 0x3f, 0x98, 0x18, 0x85, 0x05, 0xd6, 0x56, + 0xcb, 0x4b, 0xec, 0x6c, 0xf1, 0x71, 0x13, 0x93, 0x0e, 0x8e, + 0x29, 0xa9, 0x34, 0xb4, 0x67, 0xe7, 0x7a, 0xfa, 0x5d, 0xdd, + 0x40, 0xc0, 0xfb, 0x7b, 0xe6, 0x66, 0xc1, 0x41, 0xdc, 0x5c, + 0x8f, 0x0f, 0x92, 0x12, 0xb5, 0x35, 0xa8, 0x28, 0xde, 0x5e, + 0xc3, 0x43, 0xe4, 0x64, 0xf9, 0x79, 0xaa, 0x2a, 0xb7, 0x37, + 0x90, 0x10, 0x8d, 0x0d, 0x36, 0xb6, 0x2b, 0xab, 0x0c, 0x8c, + 0x11, 0x91, 0x42, 0xc2, 0x5f, 0xdf, 0x78, 0xf8, 0x65, 0xe5, + 0x94, 0x14, 0x89, 0x09, 0xae, 0x2e, 0xb3, 0x33, 0xe0, 0x60, + 0xfd, 0x7d, 0xda, 0x5a, 0xc7, 0x47, 0x7c, 0xfc, 0x61, 0xe1, + 0x46, 0xc6, 0x5b, 0xdb, 0x08, 0x88, 0x15, 0x95, 0x32, 0xb2, + 0x2f, 0xaf, 0x59, 0xd9, 0x44, 0xc4, 0x63, 0xe3, 0x7e, 0xfe, + 0x2d, 0xad, 0x30, 0xb0, 0x17, 0x97, 0x0a, 0x8a, 0xb1, 0x31, + 0xac, 0x2c, 0x8b, 0x0b, 0x96, 0x16, 0xc5, 0x45, 0xd8, 0x58, + 0xff, 0x7f, 0xe2, 0x62, 0x00, 0x81, 0x1f, 0x9e, 0x3e, 0xbf, + 0x21, 0xa0, 0x7c, 0xfd, 0x63, 0xe2, 0x42, 0xc3, 0x5d, 0xdc, + 0xf8, 0x79, 0xe7, 0x66, 0xc6, 0x47, 0xd9, 0x58, 0x84, 0x05, + 0x9b, 0x1a, 0xba, 0x3b, 0xa5, 0x24, 0xed, 0x6c, 0xf2, 0x73, + 0xd3, 0x52, 0xcc, 0x4d, 0x91, 0x10, 0x8e, 0x0f, 0xaf, 0x2e, + 0xb0, 0x31, 0x15, 0x94, 0x0a, 0x8b, 0x2b, 0xaa, 0x34, 0xb5, + 0x69, 0xe8, 0x76, 0xf7, 0x57, 0xd6, 0x48, 0xc9, 0xc7, 0x46, + 0xd8, 0x59, 0xf9, 0x78, 0xe6, 0x67, 0xbb, 0x3a, 0xa4, 0x25, + 0x85, 0x04, 0x9a, 0x1b, 0x3f, 0xbe, 0x20, 0xa1, 0x01, 0x80, + 0x1e, 0x9f, 0x43, 0xc2, 0x5c, 0xdd, 0x7d, 0xfc, 0x62, 0xe3, + 0x2a, 0xab, 0x35, 0xb4, 0x14, 0x95, 0x0b, 0x8a, 0x56, 0xd7, + 0x49, 0xc8, 0x68, 0xe9, 0x77, 0xf6, 0xd2, 0x53, 0xcd, 0x4c, + 0xec, 0x6d, 0xf3, 0x72, 0xae, 0x2f, 0xb1, 0x30, 0x90, 0x11, + 0x8f, 0x0e, 0x93, 0x12, 0x8c, 0x0d, 0xad, 0x2c, 0xb2, 0x33, + 0xef, 0x6e, 0xf0, 0x71, 0xd1, 0x50, 0xce, 0x4f, 0x6b, 0xea, + 0x74, 0xf5, 0x55, 0xd4, 0x4a, 0xcb, 0x17, 0x96, 0x08, 0x89, + 0x29, 0xa8, 0x36, 0xb7, 0x7e, 0xff, 0x61, 0xe0, 0x40, 0xc1, + 0x5f, 0xde, 0x02, 0x83, 0x1d, 0x9c, 0x3c, 0xbd, 0x23, 0xa2, + 0x86, 0x07, 0x99, 0x18, 0xb8, 0x39, 0xa7, 0x26, 0xfa, 0x7b, + 0xe5, 0x64, 0xc4, 0x45, 0xdb, 0x5a, 0x54, 0xd5, 0x4b, 0xca, + 0x6a, 0xeb, 0x75, 0xf4, 0x28, 0xa9, 0x37, 0xb6, 0x16, 0x97, + 0x09, 0x88, 0xac, 0x2d, 0xb3, 0x32, 0x92, 0x13, 0x8d, 0x0c, + 0xd0, 0x51, 0xcf, 0x4e, 0xee, 0x6f, 0xf1, 0x70, 0xb9, 0x38, + 0xa6, 0x27, 0x87, 0x06, 0x98, 0x19, 0xc5, 0x44, 0xda, 0x5b, + 0xfb, 0x7a, 0xe4, 0x65, 0x41, 0xc0, 0x5e, 0xdf, 0x7f, 0xfe, + 0x60, 0xe1, 0x3d, 0xbc, 0x22, 0xa3, 0x03, 0x82, 0x1c, 0x9d, + 0x00, 0x82, 0x19, 0x9b, 0x32, 0xb0, 0x2b, 0xa9, 0x64, 0xe6, + 0x7d, 0xff, 0x56, 0xd4, 0x4f, 0xcd, 0xc8, 0x4a, 0xd1, 0x53, + 0xfa, 0x78, 0xe3, 0x61, 0xac, 0x2e, 0xb5, 0x37, 0x9e, 0x1c, + 0x87, 0x05, 0x8d, 0x0f, 0x94, 0x16, 0xbf, 0x3d, 0xa6, 0x24, + 0xe9, 0x6b, 0xf0, 0x72, 0xdb, 0x59, 0xc2, 0x40, 0x45, 0xc7, + 0x5c, 0xde, 0x77, 0xf5, 0x6e, 0xec, 0x21, 0xa3, 0x38, 0xba, + 0x13, 0x91, 0x0a, 0x88, 0x07, 0x85, 0x1e, 0x9c, 0x35, 0xb7, + 0x2c, 0xae, 0x63, 0xe1, 0x7a, 0xf8, 0x51, 0xd3, 0x48, 0xca, + 0xcf, 0x4d, 0xd6, 0x54, 0xfd, 0x7f, 0xe4, 0x66, 0xab, 0x29, + 0xb2, 0x30, 0x99, 0x1b, 0x80, 0x02, 0x8a, 0x08, 0x93, 0x11, + 0xb8, 0x3a, 0xa1, 0x23, 0xee, 0x6c, 0xf7, 0x75, 0xdc, 0x5e, + 0xc5, 0x47, 0x42, 0xc0, 0x5b, 0xd9, 0x70, 0xf2, 0x69, 0xeb, + 0x26, 0xa4, 0x3f, 0xbd, 0x14, 0x96, 0x0d, 0x8f, 0x0e, 0x8c, + 0x17, 0x95, 0x3c, 0xbe, 0x25, 0xa7, 0x6a, 0xe8, 0x73, 0xf1, + 0x58, 0xda, 0x41, 0xc3, 0xc6, 0x44, 0xdf, 0x5d, 0xf4, 0x76, + 0xed, 0x6f, 0xa2, 0x20, 0xbb, 0x39, 0x90, 0x12, 0x89, 0x0b, + 0x83, 0x01, 0x9a, 0x18, 0xb1, 0x33, 0xa8, 0x2a, 0xe7, 0x65, + 0xfe, 0x7c, 0xd5, 0x57, 0xcc, 0x4e, 0x4b, 0xc9, 0x52, 0xd0, + 0x79, 0xfb, 0x60, 0xe2, 0x2f, 0xad, 0x36, 0xb4, 0x1d, 0x9f, + 0x04, 0x86, 0x09, 0x8b, 0x10, 0x92, 0x3b, 0xb9, 0x22, 0xa0, + 0x6d, 0xef, 0x74, 0xf6, 0x5f, 0xdd, 0x46, 0xc4, 0xc1, 0x43, + 0xd8, 0x5a, 0xf3, 0x71, 0xea, 0x68, 0xa5, 0x27, 0xbc, 0x3e, + 0x97, 0x15, 0x8e, 0x0c, 0x84, 0x06, 0x9d, 0x1f, 0xb6, 0x34, + 0xaf, 0x2d, 0xe0, 0x62, 0xf9, 0x7b, 0xd2, 0x50, 0xcb, 0x49, + 0x4c, 0xce, 0x55, 0xd7, 0x7e, 0xfc, 0x67, 0xe5, 0x28, 0xaa, + 0x31, 0xb3, 0x1a, 0x98, 0x03, 0x81, 0x00, 0x83, 0x1b, 0x98, + 0x36, 0xb5, 0x2d, 0xae, 0x6c, 0xef, 0x77, 0xf4, 0x5a, 0xd9, + 0x41, 0xc2, 0xd8, 0x5b, 0xc3, 0x40, 0xee, 0x6d, 0xf5, 0x76, + 0xb4, 0x37, 0xaf, 0x2c, 0x82, 0x01, 0x99, 0x1a, 0xad, 0x2e, + 0xb6, 0x35, 0x9b, 0x18, 0x80, 0x03, 0xc1, 0x42, 0xda, 0x59, + 0xf7, 0x74, 0xec, 0x6f, 0x75, 0xf6, 0x6e, 0xed, 0x43, 0xc0, + 0x58, 0xdb, 0x19, 0x9a, 0x02, 0x81, 0x2f, 0xac, 0x34, 0xb7, + 0x47, 0xc4, 0x5c, 0xdf, 0x71, 0xf2, 0x6a, 0xe9, 0x2b, 0xa8, + 0x30, 0xb3, 0x1d, 0x9e, 0x06, 0x85, 0x9f, 0x1c, 0x84, 0x07, + 0xa9, 0x2a, 0xb2, 0x31, 0xf3, 0x70, 0xe8, 0x6b, 0xc5, 0x46, + 0xde, 0x5d, 0xea, 0x69, 0xf1, 0x72, 0xdc, 0x5f, 0xc7, 0x44, + 0x86, 0x05, 0x9d, 0x1e, 0xb0, 0x33, 0xab, 0x28, 0x32, 0xb1, + 0x29, 0xaa, 0x04, 0x87, 0x1f, 0x9c, 0x5e, 0xdd, 0x45, 0xc6, + 0x68, 0xeb, 0x73, 0xf0, 0x8e, 0x0d, 0x95, 0x16, 0xb8, 0x3b, + 0xa3, 0x20, 0xe2, 0x61, 0xf9, 0x7a, 0xd4, 0x57, 0xcf, 0x4c, + 0x56, 0xd5, 0x4d, 0xce, 0x60, 0xe3, 0x7b, 0xf8, 0x3a, 0xb9, + 0x21, 0xa2, 0x0c, 0x8f, 0x17, 0x94, 0x23, 0xa0, 0x38, 0xbb, + 0x15, 0x96, 0x0e, 0x8d, 0x4f, 0xcc, 0x54, 0xd7, 0x79, 0xfa, + 0x62, 0xe1, 0xfb, 0x78, 0xe0, 0x63, 0xcd, 0x4e, 0xd6, 0x55, + 0x97, 0x14, 0x8c, 0x0f, 0xa1, 0x22, 0xba, 0x39, 0xc9, 0x4a, + 0xd2, 0x51, 0xff, 0x7c, 0xe4, 0x67, 0xa5, 0x26, 0xbe, 0x3d, + 0x93, 0x10, 0x88, 0x0b, 0x11, 0x92, 0x0a, 0x89, 0x27, 0xa4, + 0x3c, 0xbf, 0x7d, 0xfe, 0x66, 0xe5, 0x4b, 0xc8, 0x50, 0xd3, + 0x64, 0xe7, 0x7f, 0xfc, 0x52, 0xd1, 0x49, 0xca, 0x08, 0x8b, + 0x13, 0x90, 0x3e, 0xbd, 0x25, 0xa6, 0xbc, 0x3f, 0xa7, 0x24, + 0x8a, 0x09, 0x91, 0x12, 0xd0, 0x53, 0xcb, 0x48, 0xe6, 0x65, + 0xfd, 0x7e, 0x00, 0x84, 0x15, 0x91, 0x2a, 0xae, 0x3f, 0xbb, + 0x54, 0xd0, 0x41, 0xc5, 0x7e, 0xfa, 0x6b, 0xef, 0xa8, 0x2c, + 0xbd, 0x39, 0x82, 0x06, 0x97, 0x13, 0xfc, 0x78, 0xe9, 0x6d, + 0xd6, 0x52, 0xc3, 0x47, 0x4d, 0xc9, 0x58, 0xdc, 0x67, 0xe3, + 0x72, 0xf6, 0x19, 0x9d, 0x0c, 0x88, 0x33, 0xb7, 0x26, 0xa2, + 0xe5, 0x61, 0xf0, 0x74, 0xcf, 0x4b, 0xda, 0x5e, 0xb1, 0x35, + 0xa4, 0x20, 0x9b, 0x1f, 0x8e, 0x0a, 0x9a, 0x1e, 0x8f, 0x0b, + 0xb0, 0x34, 0xa5, 0x21, 0xce, 0x4a, 0xdb, 0x5f, 0xe4, 0x60, + 0xf1, 0x75, 0x32, 0xb6, 0x27, 0xa3, 0x18, 0x9c, 0x0d, 0x89, + 0x66, 0xe2, 0x73, 0xf7, 0x4c, 0xc8, 0x59, 0xdd, 0xd7, 0x53, + 0xc2, 0x46, 0xfd, 0x79, 0xe8, 0x6c, 0x83, 0x07, 0x96, 0x12, + 0xa9, 0x2d, 0xbc, 0x38, 0x7f, 0xfb, 0x6a, 0xee, 0x55, 0xd1, + 0x40, 0xc4, 0x2b, 0xaf, 0x3e, 0xba, 0x01, 0x85, 0x14, 0x90, + 0x29, 0xad, 0x3c, 0xb8, 0x03, 0x87, 0x16, 0x92, 0x7d, 0xf9, + 0x68, 0xec, 0x57, 0xd3, 0x42, 0xc6, 0x81, 0x05, 0x94, 0x10, + 0xab, 0x2f, 0xbe, 0x3a, 0xd5, 0x51, 0xc0, 0x44, 0xff, 0x7b, + 0xea, 0x6e, 0x64, 0xe0, 0x71, 0xf5, 0x4e, 0xca, 0x5b, 0xdf, + 0x30, 0xb4, 0x25, 0xa1, 0x1a, 0x9e, 0x0f, 0x8b, 0xcc, 0x48, + 0xd9, 0x5d, 0xe6, 0x62, 0xf3, 0x77, 0x98, 0x1c, 0x8d, 0x09, + 0xb2, 0x36, 0xa7, 0x23, 0xb3, 0x37, 0xa6, 0x22, 0x99, 0x1d, + 0x8c, 0x08, 0xe7, 0x63, 0xf2, 0x76, 0xcd, 0x49, 0xd8, 0x5c, + 0x1b, 0x9f, 0x0e, 0x8a, 0x31, 0xb5, 0x24, 0xa0, 0x4f, 0xcb, + 0x5a, 0xde, 0x65, 0xe1, 0x70, 0xf4, 0xfe, 0x7a, 0xeb, 0x6f, + 0xd4, 0x50, 0xc1, 0x45, 0xaa, 0x2e, 0xbf, 0x3b, 0x80, 0x04, + 0x95, 0x11, 0x56, 0xd2, 0x43, 0xc7, 0x7c, 0xf8, 0x69, 0xed, + 0x02, 0x86, 0x17, 0x93, 0x28, 0xac, 0x3d, 0xb9, 0x00, 0x85, + 0x17, 0x92, 0x2e, 0xab, 0x39, 0xbc, 0x5c, 0xd9, 0x4b, 0xce, + 0x72, 0xf7, 0x65, 0xe0, 0xb8, 0x3d, 0xaf, 0x2a, 0x96, 0x13, + 0x81, 0x04, 0xe4, 0x61, 0xf3, 0x76, 0xca, 0x4f, 0xdd, 0x58, + 0x6d, 0xe8, 0x7a, 0xff, 0x43, 0xc6, 0x54, 0xd1, 0x31, 0xb4, + 0x26, 0xa3, 0x1f, 0x9a, 0x08, 0x8d, 0xd5, 0x50, 0xc2, 0x47, + 0xfb, 0x7e, 0xec, 0x69, 0x89, 0x0c, 0x9e, 0x1b, 0xa7, 0x22, + 0xb0, 0x35, 0xda, 0x5f, 0xcd, 0x48, 0xf4, 0x71, 0xe3, 0x66, + 0x86, 0x03, 0x91, 0x14, 0xa8, 0x2d, 0xbf, 0x3a, 0x62, 0xe7, + 0x75, 0xf0, 0x4c, 0xc9, 0x5b, 0xde, 0x3e, 0xbb, 0x29, 0xac, + 0x10, 0x95, 0x07, 0x82, 0xb7, 0x32, 0xa0, 0x25, 0x99, 0x1c, + 0x8e, 0x0b, 0xeb, 0x6e, 0xfc, 0x79, 0xc5, 0x40, 0xd2, 0x57, + 0x0f, 0x8a, 0x18, 0x9d, 0x21, 0xa4, 0x36, 0xb3, 0x53, 0xd6, + 0x44, 0xc1, 0x7d, 0xf8, 0x6a, 0xef, 0xa9, 0x2c, 0xbe, 0x3b, + 0x87, 0x02, 0x90, 0x15, 0xf5, 0x70, 0xe2, 0x67, 0xdb, 0x5e, + 0xcc, 0x49, 0x11, 0x94, 0x06, 0x83, 0x3f, 0xba, 0x28, 0xad, + 0x4d, 0xc8, 0x5a, 0xdf, 0x63, 0xe6, 0x74, 0xf1, 0xc4, 0x41, + 0xd3, 0x56, 0xea, 0x6f, 0xfd, 0x78, 0x98, 0x1d, 0x8f, 0x0a, + 0xb6, 0x33, 0xa1, 0x24, 0x7c, 0xf9, 0x6b, 0xee, 0x52, 0xd7, + 0x45, 0xc0, 0x20, 0xa5, 0x37, 0xb2, 0x0e, 0x8b, 0x19, 0x9c, + 0x73, 0xf6, 0x64, 0xe1, 0x5d, 0xd8, 0x4a, 0xcf, 0x2f, 0xaa, + 0x38, 0xbd, 0x01, 0x84, 0x16, 0x93, 0xcb, 0x4e, 0xdc, 0x59, + 0xe5, 0x60, 0xf2, 0x77, 0x97, 0x12, 0x80, 0x05, 0xb9, 0x3c, + 0xae, 0x2b, 0x1e, 0x9b, 0x09, 0x8c, 0x30, 0xb5, 0x27, 0xa2, + 0x42, 0xc7, 0x55, 0xd0, 0x6c, 0xe9, 0x7b, 0xfe, 0xa6, 0x23, + 0xb1, 0x34, 0x88, 0x0d, 0x9f, 0x1a, 0xfa, 0x7f, 0xed, 0x68, + 0xd4, 0x51, 0xc3, 0x46, 0x00, 0x86, 0x11, 0x97, 0x22, 0xa4, + 0x33, 0xb5, 0x44, 0xc2, 0x55, 0xd3, 0x66, 0xe0, 0x77, 0xf1, + 0x88, 0x0e, 0x99, 0x1f, 0xaa, 0x2c, 0xbb, 0x3d, 0xcc, 0x4a, + 0xdd, 0x5b, 0xee, 0x68, 0xff, 0x79, 0x0d, 0x8b, 0x1c, 0x9a, + 0x2f, 0xa9, 0x3e, 0xb8, 0x49, 0xcf, 0x58, 0xde, 0x6b, 0xed, + 0x7a, 0xfc, 0x85, 0x03, 0x94, 0x12, 0xa7, 0x21, 0xb6, 0x30, + 0xc1, 0x47, 0xd0, 0x56, 0xe3, 0x65, 0xf2, 0x74, 0x1a, 0x9c, + 0x0b, 0x8d, 0x38, 0xbe, 0x29, 0xaf, 0x5e, 0xd8, 0x4f, 0xc9, + 0x7c, 0xfa, 0x6d, 0xeb, 0x92, 0x14, 0x83, 0x05, 0xb0, 0x36, + 0xa1, 0x27, 0xd6, 0x50, 0xc7, 0x41, 0xf4, 0x72, 0xe5, 0x63, + 0x17, 0x91, 0x06, 0x80, 0x35, 0xb3, 0x24, 0xa2, 0x53, 0xd5, + 0x42, 0xc4, 0x71, 0xf7, 0x60, 0xe6, 0x9f, 0x19, 0x8e, 0x08, + 0xbd, 0x3b, 0xac, 0x2a, 0xdb, 0x5d, 0xca, 0x4c, 0xf9, 0x7f, + 0xe8, 0x6e, 0x34, 0xb2, 0x25, 0xa3, 0x16, 0x90, 0x07, 0x81, + 0x70, 0xf6, 0x61, 0xe7, 0x52, 0xd4, 0x43, 0xc5, 0xbc, 0x3a, + 0xad, 0x2b, 0x9e, 0x18, 0x8f, 0x09, 0xf8, 0x7e, 0xe9, 0x6f, + 0xda, 0x5c, 0xcb, 0x4d, 0x39, 0xbf, 0x28, 0xae, 0x1b, 0x9d, + 0x0a, 0x8c, 0x7d, 0xfb, 0x6c, 0xea, 0x5f, 0xd9, 0x4e, 0xc8, + 0xb1, 0x37, 0xa0, 0x26, 0x93, 0x15, 0x82, 0x04, 0xf5, 0x73, + 0xe4, 0x62, 0xd7, 0x51, 0xc6, 0x40, 0x2e, 0xa8, 0x3f, 0xb9, + 0x0c, 0x8a, 0x1d, 0x9b, 0x6a, 0xec, 0x7b, 0xfd, 0x48, 0xce, + 0x59, 0xdf, 0xa6, 0x20, 0xb7, 0x31, 0x84, 0x02, 0x95, 0x13, + 0xe2, 0x64, 0xf3, 0x75, 0xc0, 0x46, 0xd1, 0x57, 0x23, 0xa5, + 0x32, 0xb4, 0x01, 0x87, 0x10, 0x96, 0x67, 0xe1, 0x76, 0xf0, + 0x45, 0xc3, 0x54, 0xd2, 0xab, 0x2d, 0xba, 0x3c, 0x89, 0x0f, + 0x98, 0x1e, 0xef, 0x69, 0xfe, 0x78, 0xcd, 0x4b, 0xdc, 0x5a, + 0x00, 0x87, 0x13, 0x94, 0x26, 0xa1, 0x35, 0xb2, 0x4c, 0xcb, + 0x5f, 0xd8, 0x6a, 0xed, 0x79, 0xfe, 0x98, 0x1f, 0x8b, 0x0c, + 0xbe, 0x39, 0xad, 0x2a, 0xd4, 0x53, 0xc7, 0x40, 0xf2, 0x75, + 0xe1, 0x66, 0x2d, 0xaa, 0x3e, 0xb9, 0x0b, 0x8c, 0x18, 0x9f, + 0x61, 0xe6, 0x72, 0xf5, 0x47, 0xc0, 0x54, 0xd3, 0xb5, 0x32, + 0xa6, 0x21, 0x93, 0x14, 0x80, 0x07, 0xf9, 0x7e, 0xea, 0x6d, + 0xdf, 0x58, 0xcc, 0x4b, 0x5a, 0xdd, 0x49, 0xce, 0x7c, 0xfb, + 0x6f, 0xe8, 0x16, 0x91, 0x05, 0x82, 0x30, 0xb7, 0x23, 0xa4, + 0xc2, 0x45, 0xd1, 0x56, 0xe4, 0x63, 0xf7, 0x70, 0x8e, 0x09, + 0x9d, 0x1a, 0xa8, 0x2f, 0xbb, 0x3c, 0x77, 0xf0, 0x64, 0xe3, + 0x51, 0xd6, 0x42, 0xc5, 0x3b, 0xbc, 0x28, 0xaf, 0x1d, 0x9a, + 0x0e, 0x89, 0xef, 0x68, 0xfc, 0x7b, 0xc9, 0x4e, 0xda, 0x5d, + 0xa3, 0x24, 0xb0, 0x37, 0x85, 0x02, 0x96, 0x11, 0xb4, 0x33, + 0xa7, 0x20, 0x92, 0x15, 0x81, 0x06, 0xf8, 0x7f, 0xeb, 0x6c, + 0xde, 0x59, 0xcd, 0x4a, 0x2c, 0xab, 0x3f, 0xb8, 0x0a, 0x8d, + 0x19, 0x9e, 0x60, 0xe7, 0x73, 0xf4, 0x46, 0xc1, 0x55, 0xd2, + 0x99, 0x1e, 0x8a, 0x0d, 0xbf, 0x38, 0xac, 0x2b, 0xd5, 0x52, + 0xc6, 0x41, 0xf3, 0x74, 0xe0, 0x67, 0x01, 0x86, 0x12, 0x95, + 0x27, 0xa0, 0x34, 0xb3, 0x4d, 0xca, 0x5e, 0xd9, 0x6b, 0xec, + 0x78, 0xff, 0xee, 0x69, 0xfd, 0x7a, 0xc8, 0x4f, 0xdb, 0x5c, + 0xa2, 0x25, 0xb1, 0x36, 0x84, 0x03, 0x97, 0x10, 0x76, 0xf1, + 0x65, 0xe2, 0x50, 0xd7, 0x43, 0xc4, 0x3a, 0xbd, 0x29, 0xae, + 0x1c, 0x9b, 0x0f, 0x88, 0xc3, 0x44, 0xd0, 0x57, 0xe5, 0x62, + 0xf6, 0x71, 0x8f, 0x08, 0x9c, 0x1b, 0xa9, 0x2e, 0xba, 0x3d, + 0x5b, 0xdc, 0x48, 0xcf, 0x7d, 0xfa, 0x6e, 0xe9, 0x17, 0x90, + 0x04, 0x83, 0x31, 0xb6, 0x22, 0xa5, 0x00, 0x88, 0x0d, 0x85, + 0x1a, 0x92, 0x17, 0x9f, 0x34, 0xbc, 0x39, 0xb1, 0x2e, 0xa6, + 0x23, 0xab, 0x68, 0xe0, 0x65, 0xed, 0x72, 0xfa, 0x7f, 0xf7, + 0x5c, 0xd4, 0x51, 0xd9, 0x46, 0xce, 0x4b, 0xc3, 0xd0, 0x58, + 0xdd, 0x55, 0xca, 0x42, 0xc7, 0x4f, 0xe4, 0x6c, 0xe9, 0x61, + 0xfe, 0x76, 0xf3, 0x7b, 0xb8, 0x30, 0xb5, 0x3d, 0xa2, 0x2a, + 0xaf, 0x27, 0x8c, 0x04, 0x81, 0x09, 0x96, 0x1e, 0x9b, 0x13, + 0xbd, 0x35, 0xb0, 0x38, 0xa7, 0x2f, 0xaa, 0x22, 0x89, 0x01, + 0x84, 0x0c, 0x93, 0x1b, 0x9e, 0x16, 0xd5, 0x5d, 0xd8, 0x50, + 0xcf, 0x47, 0xc2, 0x4a, 0xe1, 0x69, 0xec, 0x64, 0xfb, 0x73, + 0xf6, 0x7e, 0x6d, 0xe5, 0x60, 0xe8, 0x77, 0xff, 0x7a, 0xf2, + 0x59, 0xd1, 0x54, 0xdc, 0x43, 0xcb, 0x4e, 0xc6, 0x05, 0x8d, + 0x08, 0x80, 0x1f, 0x97, 0x12, 0x9a, 0x31, 0xb9, 0x3c, 0xb4, + 0x2b, 0xa3, 0x26, 0xae, 0x67, 0xef, 0x6a, 0xe2, 0x7d, 0xf5, + 0x70, 0xf8, 0x53, 0xdb, 0x5e, 0xd6, 0x49, 0xc1, 0x44, 0xcc, + 0x0f, 0x87, 0x02, 0x8a, 0x15, 0x9d, 0x18, 0x90, 0x3b, 0xb3, + 0x36, 0xbe, 0x21, 0xa9, 0x2c, 0xa4, 0xb7, 0x3f, 0xba, 0x32, + 0xad, 0x25, 0xa0, 0x28, 0x83, 0x0b, 0x8e, 0x06, 0x99, 0x11, + 0x94, 0x1c, 0xdf, 0x57, 0xd2, 0x5a, 0xc5, 0x4d, 0xc8, 0x40, + 0xeb, 0x63, 0xe6, 0x6e, 0xf1, 0x79, 0xfc, 0x74, 0xda, 0x52, + 0xd7, 0x5f, 0xc0, 0x48, 0xcd, 0x45, 0xee, 0x66, 0xe3, 0x6b, + 0xf4, 0x7c, 0xf9, 0x71, 0xb2, 0x3a, 0xbf, 0x37, 0xa8, 0x20, + 0xa5, 0x2d, 0x86, 0x0e, 0x8b, 0x03, 0x9c, 0x14, 0x91, 0x19, + 0x0a, 0x82, 0x07, 0x8f, 0x10, 0x98, 0x1d, 0x95, 0x3e, 0xb6, + 0x33, 0xbb, 0x24, 0xac, 0x29, 0xa1, 0x62, 0xea, 0x6f, 0xe7, + 0x78, 0xf0, 0x75, 0xfd, 0x56, 0xde, 0x5b, 0xd3, 0x4c, 0xc4, + 0x41, 0xc9, 0x00, 0x89, 0x0f, 0x86, 0x1e, 0x97, 0x11, 0x98, + 0x3c, 0xb5, 0x33, 0xba, 0x22, 0xab, 0x2d, 0xa4, 0x78, 0xf1, + 0x77, 0xfe, 0x66, 0xef, 0x69, 0xe0, 0x44, 0xcd, 0x4b, 0xc2, + 0x5a, 0xd3, 0x55, 0xdc, 0xf0, 0x79, 0xff, 0x76, 0xee, 0x67, + 0xe1, 0x68, 0xcc, 0x45, 0xc3, 0x4a, 0xd2, 0x5b, 0xdd, 0x54, + 0x88, 0x01, 0x87, 0x0e, 0x96, 0x1f, 0x99, 0x10, 0xb4, 0x3d, + 0xbb, 0x32, 0xaa, 0x23, 0xa5, 0x2c, 0xfd, 0x74, 0xf2, 0x7b, + 0xe3, 0x6a, 0xec, 0x65, 0xc1, 0x48, 0xce, 0x47, 0xdf, 0x56, + 0xd0, 0x59, 0x85, 0x0c, 0x8a, 0x03, 0x9b, 0x12, 0x94, 0x1d, + 0xb9, 0x30, 0xb6, 0x3f, 0xa7, 0x2e, 0xa8, 0x21, 0x0d, 0x84, + 0x02, 0x8b, 0x13, 0x9a, 0x1c, 0x95, 0x31, 0xb8, 0x3e, 0xb7, + 0x2f, 0xa6, 0x20, 0xa9, 0x75, 0xfc, 0x7a, 0xf3, 0x6b, 0xe2, + 0x64, 0xed, 0x49, 0xc0, 0x46, 0xcf, 0x57, 0xde, 0x58, 0xd1, + 0xe7, 0x6e, 0xe8, 0x61, 0xf9, 0x70, 0xf6, 0x7f, 0xdb, 0x52, + 0xd4, 0x5d, 0xc5, 0x4c, 0xca, 0x43, 0x9f, 0x16, 0x90, 0x19, + 0x81, 0x08, 0x8e, 0x07, 0xa3, 0x2a, 0xac, 0x25, 0xbd, 0x34, + 0xb2, 0x3b, 0x17, 0x9e, 0x18, 0x91, 0x09, 0x80, 0x06, 0x8f, + 0x2b, 0xa2, 0x24, 0xad, 0x35, 0xbc, 0x3a, 0xb3, 0x6f, 0xe6, + 0x60, 0xe9, 0x71, 0xf8, 0x7e, 0xf7, 0x53, 0xda, 0x5c, 0xd5, + 0x4d, 0xc4, 0x42, 0xcb, 0x1a, 0x93, 0x15, 0x9c, 0x04, 0x8d, + 0x0b, 0x82, 0x26, 0xaf, 0x29, 0xa0, 0x38, 0xb1, 0x37, 0xbe, + 0x62, 0xeb, 0x6d, 0xe4, 0x7c, 0xf5, 0x73, 0xfa, 0x5e, 0xd7, + 0x51, 0xd8, 0x40, 0xc9, 0x4f, 0xc6, 0xea, 0x63, 0xe5, 0x6c, + 0xf4, 0x7d, 0xfb, 0x72, 0xd6, 0x5f, 0xd9, 0x50, 0xc8, 0x41, + 0xc7, 0x4e, 0x92, 0x1b, 0x9d, 0x14, 0x8c, 0x05, 0x83, 0x0a, + 0xae, 0x27, 0xa1, 0x28, 0xb0, 0x39, 0xbf, 0x36, 0x00, 0x8a, + 0x09, 0x83, 0x12, 0x98, 0x1b, 0x91, 0x24, 0xae, 0x2d, 0xa7, + 0x36, 0xbc, 0x3f, 0xb5, 0x48, 0xc2, 0x41, 0xcb, 0x5a, 0xd0, + 0x53, 0xd9, 0x6c, 0xe6, 0x65, 0xef, 0x7e, 0xf4, 0x77, 0xfd, + 0x90, 0x1a, 0x99, 0x13, 0x82, 0x08, 0x8b, 0x01, 0xb4, 0x3e, + 0xbd, 0x37, 0xa6, 0x2c, 0xaf, 0x25, 0xd8, 0x52, 0xd1, 0x5b, + 0xca, 0x40, 0xc3, 0x49, 0xfc, 0x76, 0xf5, 0x7f, 0xee, 0x64, + 0xe7, 0x6d, 0x3d, 0xb7, 0x34, 0xbe, 0x2f, 0xa5, 0x26, 0xac, + 0x19, 0x93, 0x10, 0x9a, 0x0b, 0x81, 0x02, 0x88, 0x75, 0xff, + 0x7c, 0xf6, 0x67, 0xed, 0x6e, 0xe4, 0x51, 0xdb, 0x58, 0xd2, + 0x43, 0xc9, 0x4a, 0xc0, 0xad, 0x27, 0xa4, 0x2e, 0xbf, 0x35, + 0xb6, 0x3c, 0x89, 0x03, 0x80, 0x0a, 0x9b, 0x11, 0x92, 0x18, + 0xe5, 0x6f, 0xec, 0x66, 0xf7, 0x7d, 0xfe, 0x74, 0xc1, 0x4b, + 0xc8, 0x42, 0xd3, 0x59, 0xda, 0x50, 0x7a, 0xf0, 0x73, 0xf9, + 0x68, 0xe2, 0x61, 0xeb, 0x5e, 0xd4, 0x57, 0xdd, 0x4c, 0xc6, + 0x45, 0xcf, 0x32, 0xb8, 0x3b, 0xb1, 0x20, 0xaa, 0x29, 0xa3, + 0x16, 0x9c, 0x1f, 0x95, 0x04, 0x8e, 0x0d, 0x87, 0xea, 0x60, + 0xe3, 0x69, 0xf8, 0x72, 0xf1, 0x7b, 0xce, 0x44, 0xc7, 0x4d, + 0xdc, 0x56, 0xd5, 0x5f, 0xa2, 0x28, 0xab, 0x21, 0xb0, 0x3a, + 0xb9, 0x33, 0x86, 0x0c, 0x8f, 0x05, 0x94, 0x1e, 0x9d, 0x17, + 0x47, 0xcd, 0x4e, 0xc4, 0x55, 0xdf, 0x5c, 0xd6, 0x63, 0xe9, + 0x6a, 0xe0, 0x71, 0xfb, 0x78, 0xf2, 0x0f, 0x85, 0x06, 0x8c, + 0x1d, 0x97, 0x14, 0x9e, 0x2b, 0xa1, 0x22, 0xa8, 0x39, 0xb3, + 0x30, 0xba, 0xd7, 0x5d, 0xde, 0x54, 0xc5, 0x4f, 0xcc, 0x46, + 0xf3, 0x79, 0xfa, 0x70, 0xe1, 0x6b, 0xe8, 0x62, 0x9f, 0x15, + 0x96, 0x1c, 0x8d, 0x07, 0x84, 0x0e, 0xbb, 0x31, 0xb2, 0x38, + 0xa9, 0x23, 0xa0, 0x2a, 0x00, 0x8b, 0x0b, 0x80, 0x16, 0x9d, + 0x1d, 0x96, 0x2c, 0xa7, 0x27, 0xac, 0x3a, 0xb1, 0x31, 0xba, + 0x58, 0xd3, 0x53, 0xd8, 0x4e, 0xc5, 0x45, 0xce, 0x74, 0xff, + 0x7f, 0xf4, 0x62, 0xe9, 0x69, 0xe2, 0xb0, 0x3b, 0xbb, 0x30, + 0xa6, 0x2d, 0xad, 0x26, 0x9c, 0x17, 0x97, 0x1c, 0x8a, 0x01, + 0x81, 0x0a, 0xe8, 0x63, 0xe3, 0x68, 0xfe, 0x75, 0xf5, 0x7e, + 0xc4, 0x4f, 0xcf, 0x44, 0xd2, 0x59, 0xd9, 0x52, 0x7d, 0xf6, + 0x76, 0xfd, 0x6b, 0xe0, 0x60, 0xeb, 0x51, 0xda, 0x5a, 0xd1, + 0x47, 0xcc, 0x4c, 0xc7, 0x25, 0xae, 0x2e, 0xa5, 0x33, 0xb8, + 0x38, 0xb3, 0x09, 0x82, 0x02, 0x89, 0x1f, 0x94, 0x14, 0x9f, + 0xcd, 0x46, 0xc6, 0x4d, 0xdb, 0x50, 0xd0, 0x5b, 0xe1, 0x6a, + 0xea, 0x61, 0xf7, 0x7c, 0xfc, 0x77, 0x95, 0x1e, 0x9e, 0x15, + 0x83, 0x08, 0x88, 0x03, 0xb9, 0x32, 0xb2, 0x39, 0xaf, 0x24, + 0xa4, 0x2f, 0xfa, 0x71, 0xf1, 0x7a, 0xec, 0x67, 0xe7, 0x6c, + 0xd6, 0x5d, 0xdd, 0x56, 0xc0, 0x4b, 0xcb, 0x40, 0xa2, 0x29, + 0xa9, 0x22, 0xb4, 0x3f, 0xbf, 0x34, 0x8e, 0x05, 0x85, 0x0e, + 0x98, 0x13, 0x93, 0x18, 0x4a, 0xc1, 0x41, 0xca, 0x5c, 0xd7, + 0x57, 0xdc, 0x66, 0xed, 0x6d, 0xe6, 0x70, 0xfb, 0x7b, 0xf0, + 0x12, 0x99, 0x19, 0x92, 0x04, 0x8f, 0x0f, 0x84, 0x3e, 0xb5, + 0x35, 0xbe, 0x28, 0xa3, 0x23, 0xa8, 0x87, 0x0c, 0x8c, 0x07, + 0x91, 0x1a, 0x9a, 0x11, 0xab, 0x20, 0xa0, 0x2b, 0xbd, 0x36, + 0xb6, 0x3d, 0xdf, 0x54, 0xd4, 0x5f, 0xc9, 0x42, 0xc2, 0x49, + 0xf3, 0x78, 0xf8, 0x73, 0xe5, 0x6e, 0xee, 0x65, 0x37, 0xbc, + 0x3c, 0xb7, 0x21, 0xaa, 0x2a, 0xa1, 0x1b, 0x90, 0x10, 0x9b, + 0x0d, 0x86, 0x06, 0x8d, 0x6f, 0xe4, 0x64, 0xef, 0x79, 0xf2, + 0x72, 0xf9, 0x43, 0xc8, 0x48, 0xc3, 0x55, 0xde, 0x5e, 0xd5, + 0x00, 0x8c, 0x05, 0x89, 0x0a, 0x86, 0x0f, 0x83, 0x14, 0x98, + 0x11, 0x9d, 0x1e, 0x92, 0x1b, 0x97, 0x28, 0xa4, 0x2d, 0xa1, + 0x22, 0xae, 0x27, 0xab, 0x3c, 0xb0, 0x39, 0xb5, 0x36, 0xba, + 0x33, 0xbf, 0x50, 0xdc, 0x55, 0xd9, 0x5a, 0xd6, 0x5f, 0xd3, + 0x44, 0xc8, 0x41, 0xcd, 0x4e, 0xc2, 0x4b, 0xc7, 0x78, 0xf4, + 0x7d, 0xf1, 0x72, 0xfe, 0x77, 0xfb, 0x6c, 0xe0, 0x69, 0xe5, + 0x66, 0xea, 0x63, 0xef, 0xa0, 0x2c, 0xa5, 0x29, 0xaa, 0x26, + 0xaf, 0x23, 0xb4, 0x38, 0xb1, 0x3d, 0xbe, 0x32, 0xbb, 0x37, + 0x88, 0x04, 0x8d, 0x01, 0x82, 0x0e, 0x87, 0x0b, 0x9c, 0x10, + 0x99, 0x15, 0x96, 0x1a, 0x93, 0x1f, 0xf0, 0x7c, 0xf5, 0x79, + 0xfa, 0x76, 0xff, 0x73, 0xe4, 0x68, 0xe1, 0x6d, 0xee, 0x62, + 0xeb, 0x67, 0xd8, 0x54, 0xdd, 0x51, 0xd2, 0x5e, 0xd7, 0x5b, + 0xcc, 0x40, 0xc9, 0x45, 0xc6, 0x4a, 0xc3, 0x4f, 0x5d, 0xd1, + 0x58, 0xd4, 0x57, 0xdb, 0x52, 0xde, 0x49, 0xc5, 0x4c, 0xc0, + 0x43, 0xcf, 0x46, 0xca, 0x75, 0xf9, 0x70, 0xfc, 0x7f, 0xf3, + 0x7a, 0xf6, 0x61, 0xed, 0x64, 0xe8, 0x6b, 0xe7, 0x6e, 0xe2, + 0x0d, 0x81, 0x08, 0x84, 0x07, 0x8b, 0x02, 0x8e, 0x19, 0x95, + 0x1c, 0x90, 0x13, 0x9f, 0x16, 0x9a, 0x25, 0xa9, 0x20, 0xac, + 0x2f, 0xa3, 0x2a, 0xa6, 0x31, 0xbd, 0x34, 0xb8, 0x3b, 0xb7, + 0x3e, 0xb2, 0xfd, 0x71, 0xf8, 0x74, 0xf7, 0x7b, 0xf2, 0x7e, + 0xe9, 0x65, 0xec, 0x60, 0xe3, 0x6f, 0xe6, 0x6a, 0xd5, 0x59, + 0xd0, 0x5c, 0xdf, 0x53, 0xda, 0x56, 0xc1, 0x4d, 0xc4, 0x48, + 0xcb, 0x47, 0xce, 0x42, 0xad, 0x21, 0xa8, 0x24, 0xa7, 0x2b, + 0xa2, 0x2e, 0xb9, 0x35, 0xbc, 0x30, 0xb3, 0x3f, 0xb6, 0x3a, + 0x85, 0x09, 0x80, 0x0c, 0x8f, 0x03, 0x8a, 0x06, 0x91, 0x1d, + 0x94, 0x18, 0x9b, 0x17, 0x9e, 0x12, 0x00, 0x8d, 0x07, 0x8a, + 0x0e, 0x83, 0x09, 0x84, 0x1c, 0x91, 0x1b, 0x96, 0x12, 0x9f, + 0x15, 0x98, 0x38, 0xb5, 0x3f, 0xb2, 0x36, 0xbb, 0x31, 0xbc, + 0x24, 0xa9, 0x23, 0xae, 0x2a, 0xa7, 0x2d, 0xa0, 0x70, 0xfd, + 0x77, 0xfa, 0x7e, 0xf3, 0x79, 0xf4, 0x6c, 0xe1, 0x6b, 0xe6, + 0x62, 0xef, 0x65, 0xe8, 0x48, 0xc5, 0x4f, 0xc2, 0x46, 0xcb, + 0x41, 0xcc, 0x54, 0xd9, 0x53, 0xde, 0x5a, 0xd7, 0x5d, 0xd0, + 0xe0, 0x6d, 0xe7, 0x6a, 0xee, 0x63, 0xe9, 0x64, 0xfc, 0x71, + 0xfb, 0x76, 0xf2, 0x7f, 0xf5, 0x78, 0xd8, 0x55, 0xdf, 0x52, + 0xd6, 0x5b, 0xd1, 0x5c, 0xc4, 0x49, 0xc3, 0x4e, 0xca, 0x47, + 0xcd, 0x40, 0x90, 0x1d, 0x97, 0x1a, 0x9e, 0x13, 0x99, 0x14, + 0x8c, 0x01, 0x8b, 0x06, 0x82, 0x0f, 0x85, 0x08, 0xa8, 0x25, + 0xaf, 0x22, 0xa6, 0x2b, 0xa1, 0x2c, 0xb4, 0x39, 0xb3, 0x3e, + 0xba, 0x37, 0xbd, 0x30, 0xdd, 0x50, 0xda, 0x57, 0xd3, 0x5e, + 0xd4, 0x59, 0xc1, 0x4c, 0xc6, 0x4b, 0xcf, 0x42, 0xc8, 0x45, + 0xe5, 0x68, 0xe2, 0x6f, 0xeb, 0x66, 0xec, 0x61, 0xf9, 0x74, + 0xfe, 0x73, 0xf7, 0x7a, 0xf0, 0x7d, 0xad, 0x20, 0xaa, 0x27, + 0xa3, 0x2e, 0xa4, 0x29, 0xb1, 0x3c, 0xb6, 0x3b, 0xbf, 0x32, + 0xb8, 0x35, 0x95, 0x18, 0x92, 0x1f, 0x9b, 0x16, 0x9c, 0x11, + 0x89, 0x04, 0x8e, 0x03, 0x87, 0x0a, 0x80, 0x0d, 0x3d, 0xb0, + 0x3a, 0xb7, 0x33, 0xbe, 0x34, 0xb9, 0x21, 0xac, 0x26, 0xab, + 0x2f, 0xa2, 0x28, 0xa5, 0x05, 0x88, 0x02, 0x8f, 0x0b, 0x86, + 0x0c, 0x81, 0x19, 0x94, 0x1e, 0x93, 0x17, 0x9a, 0x10, 0x9d, + 0x4d, 0xc0, 0x4a, 0xc7, 0x43, 0xce, 0x44, 0xc9, 0x51, 0xdc, + 0x56, 0xdb, 0x5f, 0xd2, 0x58, 0xd5, 0x75, 0xf8, 0x72, 0xff, + 0x7b, 0xf6, 0x7c, 0xf1, 0x69, 0xe4, 0x6e, 0xe3, 0x67, 0xea, + 0x60, 0xed, 0x00, 0x8e, 0x01, 0x8f, 0x02, 0x8c, 0x03, 0x8d, + 0x04, 0x8a, 0x05, 0x8b, 0x06, 0x88, 0x07, 0x89, 0x08, 0x86, + 0x09, 0x87, 0x0a, 0x84, 0x0b, 0x85, 0x0c, 0x82, 0x0d, 0x83, + 0x0e, 0x80, 0x0f, 0x81, 0x10, 0x9e, 0x11, 0x9f, 0x12, 0x9c, + 0x13, 0x9d, 0x14, 0x9a, 0x15, 0x9b, 0x16, 0x98, 0x17, 0x99, + 0x18, 0x96, 0x19, 0x97, 0x1a, 0x94, 0x1b, 0x95, 0x1c, 0x92, + 0x1d, 0x93, 0x1e, 0x90, 0x1f, 0x91, 0x20, 0xae, 0x21, 0xaf, + 0x22, 0xac, 0x23, 0xad, 0x24, 0xaa, 0x25, 0xab, 0x26, 0xa8, + 0x27, 0xa9, 0x28, 0xa6, 0x29, 0xa7, 0x2a, 0xa4, 0x2b, 0xa5, + 0x2c, 0xa2, 0x2d, 0xa3, 0x2e, 0xa0, 0x2f, 0xa1, 0x30, 0xbe, + 0x31, 0xbf, 0x32, 0xbc, 0x33, 0xbd, 0x34, 0xba, 0x35, 0xbb, + 0x36, 0xb8, 0x37, 0xb9, 0x38, 0xb6, 0x39, 0xb7, 0x3a, 0xb4, + 0x3b, 0xb5, 0x3c, 0xb2, 0x3d, 0xb3, 0x3e, 0xb0, 0x3f, 0xb1, + 0x40, 0xce, 0x41, 0xcf, 0x42, 0xcc, 0x43, 0xcd, 0x44, 0xca, + 0x45, 0xcb, 0x46, 0xc8, 0x47, 0xc9, 0x48, 0xc6, 0x49, 0xc7, + 0x4a, 0xc4, 0x4b, 0xc5, 0x4c, 0xc2, 0x4d, 0xc3, 0x4e, 0xc0, + 0x4f, 0xc1, 0x50, 0xde, 0x51, 0xdf, 0x52, 0xdc, 0x53, 0xdd, + 0x54, 0xda, 0x55, 0xdb, 0x56, 0xd8, 0x57, 0xd9, 0x58, 0xd6, + 0x59, 0xd7, 0x5a, 0xd4, 0x5b, 0xd5, 0x5c, 0xd2, 0x5d, 0xd3, + 0x5e, 0xd0, 0x5f, 0xd1, 0x60, 0xee, 0x61, 0xef, 0x62, 0xec, + 0x63, 0xed, 0x64, 0xea, 0x65, 0xeb, 0x66, 0xe8, 0x67, 0xe9, + 0x68, 0xe6, 0x69, 0xe7, 0x6a, 0xe4, 0x6b, 0xe5, 0x6c, 0xe2, + 0x6d, 0xe3, 0x6e, 0xe0, 0x6f, 0xe1, 0x70, 0xfe, 0x71, 0xff, + 0x72, 0xfc, 0x73, 0xfd, 0x74, 0xfa, 0x75, 0xfb, 0x76, 0xf8, + 0x77, 0xf9, 0x78, 0xf6, 0x79, 0xf7, 0x7a, 0xf4, 0x7b, 0xf5, + 0x7c, 0xf2, 0x7d, 0xf3, 0x7e, 0xf0, 0x7f, 0xf1, 0x00, 0x8f, + 0x03, 0x8c, 0x06, 0x89, 0x05, 0x8a, 0x0c, 0x83, 0x0f, 0x80, + 0x0a, 0x85, 0x09, 0x86, 0x18, 0x97, 0x1b, 0x94, 0x1e, 0x91, + 0x1d, 0x92, 0x14, 0x9b, 0x17, 0x98, 0x12, 0x9d, 0x11, 0x9e, + 0x30, 0xbf, 0x33, 0xbc, 0x36, 0xb9, 0x35, 0xba, 0x3c, 0xb3, + 0x3f, 0xb0, 0x3a, 0xb5, 0x39, 0xb6, 0x28, 0xa7, 0x2b, 0xa4, + 0x2e, 0xa1, 0x2d, 0xa2, 0x24, 0xab, 0x27, 0xa8, 0x22, 0xad, + 0x21, 0xae, 0x60, 0xef, 0x63, 0xec, 0x66, 0xe9, 0x65, 0xea, + 0x6c, 0xe3, 0x6f, 0xe0, 0x6a, 0xe5, 0x69, 0xe6, 0x78, 0xf7, + 0x7b, 0xf4, 0x7e, 0xf1, 0x7d, 0xf2, 0x74, 0xfb, 0x77, 0xf8, + 0x72, 0xfd, 0x71, 0xfe, 0x50, 0xdf, 0x53, 0xdc, 0x56, 0xd9, + 0x55, 0xda, 0x5c, 0xd3, 0x5f, 0xd0, 0x5a, 0xd5, 0x59, 0xd6, + 0x48, 0xc7, 0x4b, 0xc4, 0x4e, 0xc1, 0x4d, 0xc2, 0x44, 0xcb, + 0x47, 0xc8, 0x42, 0xcd, 0x41, 0xce, 0xc0, 0x4f, 0xc3, 0x4c, + 0xc6, 0x49, 0xc5, 0x4a, 0xcc, 0x43, 0xcf, 0x40, 0xca, 0x45, + 0xc9, 0x46, 0xd8, 0x57, 0xdb, 0x54, 0xde, 0x51, 0xdd, 0x52, + 0xd4, 0x5b, 0xd7, 0x58, 0xd2, 0x5d, 0xd1, 0x5e, 0xf0, 0x7f, + 0xf3, 0x7c, 0xf6, 0x79, 0xf5, 0x7a, 0xfc, 0x73, 0xff, 0x70, + 0xfa, 0x75, 0xf9, 0x76, 0xe8, 0x67, 0xeb, 0x64, 0xee, 0x61, + 0xed, 0x62, 0xe4, 0x6b, 0xe7, 0x68, 0xe2, 0x6d, 0xe1, 0x6e, + 0xa0, 0x2f, 0xa3, 0x2c, 0xa6, 0x29, 0xa5, 0x2a, 0xac, 0x23, + 0xaf, 0x20, 0xaa, 0x25, 0xa9, 0x26, 0xb8, 0x37, 0xbb, 0x34, + 0xbe, 0x31, 0xbd, 0x32, 0xb4, 0x3b, 0xb7, 0x38, 0xb2, 0x3d, + 0xb1, 0x3e, 0x90, 0x1f, 0x93, 0x1c, 0x96, 0x19, 0x95, 0x1a, + 0x9c, 0x13, 0x9f, 0x10, 0x9a, 0x15, 0x99, 0x16, 0x88, 0x07, + 0x8b, 0x04, 0x8e, 0x01, 0x8d, 0x02, 0x84, 0x0b, 0x87, 0x08, + 0x82, 0x0d, 0x81, 0x0e, 0x00, 0x90, 0x3d, 0xad, 0x7a, 0xea, + 0x47, 0xd7, 0xf4, 0x64, 0xc9, 0x59, 0x8e, 0x1e, 0xb3, 0x23, + 0xf5, 0x65, 0xc8, 0x58, 0x8f, 0x1f, 0xb2, 0x22, 0x01, 0x91, + 0x3c, 0xac, 0x7b, 0xeb, 0x46, 0xd6, 0xf7, 0x67, 0xca, 0x5a, + 0x8d, 0x1d, 0xb0, 0x20, 0x03, 0x93, 0x3e, 0xae, 0x79, 0xe9, + 0x44, 0xd4, 0x02, 0x92, 0x3f, 0xaf, 0x78, 0xe8, 0x45, 0xd5, + 0xf6, 0x66, 0xcb, 0x5b, 0x8c, 0x1c, 0xb1, 0x21, 0xf3, 0x63, + 0xce, 0x5e, 0x89, 0x19, 0xb4, 0x24, 0x07, 0x97, 0x3a, 0xaa, + 0x7d, 0xed, 0x40, 0xd0, 0x06, 0x96, 0x3b, 0xab, 0x7c, 0xec, + 0x41, 0xd1, 0xf2, 0x62, 0xcf, 0x5f, 0x88, 0x18, 0xb5, 0x25, + 0x04, 0x94, 0x39, 0xa9, 0x7e, 0xee, 0x43, 0xd3, 0xf0, 0x60, + 0xcd, 0x5d, 0x8a, 0x1a, 0xb7, 0x27, 0xf1, 0x61, 0xcc, 0x5c, + 0x8b, 0x1b, 0xb6, 0x26, 0x05, 0x95, 0x38, 0xa8, 0x7f, 0xef, + 0x42, 0xd2, 0xfb, 0x6b, 0xc6, 0x56, 0x81, 0x11, 0xbc, 0x2c, + 0x0f, 0x9f, 0x32, 0xa2, 0x75, 0xe5, 0x48, 0xd8, 0x0e, 0x9e, + 0x33, 0xa3, 0x74, 0xe4, 0x49, 0xd9, 0xfa, 0x6a, 0xc7, 0x57, + 0x80, 0x10, 0xbd, 0x2d, 0x0c, 0x9c, 0x31, 0xa1, 0x76, 0xe6, + 0x4b, 0xdb, 0xf8, 0x68, 0xc5, 0x55, 0x82, 0x12, 0xbf, 0x2f, + 0xf9, 0x69, 0xc4, 0x54, 0x83, 0x13, 0xbe, 0x2e, 0x0d, 0x9d, + 0x30, 0xa0, 0x77, 0xe7, 0x4a, 0xda, 0x08, 0x98, 0x35, 0xa5, + 0x72, 0xe2, 0x4f, 0xdf, 0xfc, 0x6c, 0xc1, 0x51, 0x86, 0x16, + 0xbb, 0x2b, 0xfd, 0x6d, 0xc0, 0x50, 0x87, 0x17, 0xba, 0x2a, + 0x09, 0x99, 0x34, 0xa4, 0x73, 0xe3, 0x4e, 0xde, 0xff, 0x6f, + 0xc2, 0x52, 0x85, 0x15, 0xb8, 0x28, 0x0b, 0x9b, 0x36, 0xa6, + 0x71, 0xe1, 0x4c, 0xdc, 0x0a, 0x9a, 0x37, 0xa7, 0x70, 0xe0, + 0x4d, 0xdd, 0xfe, 0x6e, 0xc3, 0x53, 0x84, 0x14, 0xb9, 0x29, + 0x00, 0x91, 0x3f, 0xae, 0x7e, 0xef, 0x41, 0xd0, 0xfc, 0x6d, + 0xc3, 0x52, 0x82, 0x13, 0xbd, 0x2c, 0xe5, 0x74, 0xda, 0x4b, + 0x9b, 0x0a, 0xa4, 0x35, 0x19, 0x88, 0x26, 0xb7, 0x67, 0xf6, + 0x58, 0xc9, 0xd7, 0x46, 0xe8, 0x79, 0xa9, 0x38, 0x96, 0x07, + 0x2b, 0xba, 0x14, 0x85, 0x55, 0xc4, 0x6a, 0xfb, 0x32, 0xa3, + 0x0d, 0x9c, 0x4c, 0xdd, 0x73, 0xe2, 0xce, 0x5f, 0xf1, 0x60, + 0xb0, 0x21, 0x8f, 0x1e, 0xb3, 0x22, 0x8c, 0x1d, 0xcd, 0x5c, + 0xf2, 0x63, 0x4f, 0xde, 0x70, 0xe1, 0x31, 0xa0, 0x0e, 0x9f, + 0x56, 0xc7, 0x69, 0xf8, 0x28, 0xb9, 0x17, 0x86, 0xaa, 0x3b, + 0x95, 0x04, 0xd4, 0x45, 0xeb, 0x7a, 0x64, 0xf5, 0x5b, 0xca, + 0x1a, 0x8b, 0x25, 0xb4, 0x98, 0x09, 0xa7, 0x36, 0xe6, 0x77, + 0xd9, 0x48, 0x81, 0x10, 0xbe, 0x2f, 0xff, 0x6e, 0xc0, 0x51, + 0x7d, 0xec, 0x42, 0xd3, 0x03, 0x92, 0x3c, 0xad, 0x7b, 0xea, + 0x44, 0xd5, 0x05, 0x94, 0x3a, 0xab, 0x87, 0x16, 0xb8, 0x29, + 0xf9, 0x68, 0xc6, 0x57, 0x9e, 0x0f, 0xa1, 0x30, 0xe0, 0x71, + 0xdf, 0x4e, 0x62, 0xf3, 0x5d, 0xcc, 0x1c, 0x8d, 0x23, 0xb2, + 0xac, 0x3d, 0x93, 0x02, 0xd2, 0x43, 0xed, 0x7c, 0x50, 0xc1, + 0x6f, 0xfe, 0x2e, 0xbf, 0x11, 0x80, 0x49, 0xd8, 0x76, 0xe7, + 0x37, 0xa6, 0x08, 0x99, 0xb5, 0x24, 0x8a, 0x1b, 0xcb, 0x5a, + 0xf4, 0x65, 0xc8, 0x59, 0xf7, 0x66, 0xb6, 0x27, 0x89, 0x18, + 0x34, 0xa5, 0x0b, 0x9a, 0x4a, 0xdb, 0x75, 0xe4, 0x2d, 0xbc, + 0x12, 0x83, 0x53, 0xc2, 0x6c, 0xfd, 0xd1, 0x40, 0xee, 0x7f, + 0xaf, 0x3e, 0x90, 0x01, 0x1f, 0x8e, 0x20, 0xb1, 0x61, 0xf0, + 0x5e, 0xcf, 0xe3, 0x72, 0xdc, 0x4d, 0x9d, 0x0c, 0xa2, 0x33, + 0xfa, 0x6b, 0xc5, 0x54, 0x84, 0x15, 0xbb, 0x2a, 0x06, 0x97, + 0x39, 0xa8, 0x78, 0xe9, 0x47, 0xd6, 0x00, 0x92, 0x39, 0xab, + 0x72, 0xe0, 0x4b, 0xd9, 0xe4, 0x76, 0xdd, 0x4f, 0x96, 0x04, + 0xaf, 0x3d, 0xd5, 0x47, 0xec, 0x7e, 0xa7, 0x35, 0x9e, 0x0c, + 0x31, 0xa3, 0x08, 0x9a, 0x43, 0xd1, 0x7a, 0xe8, 0xb7, 0x25, + 0x8e, 0x1c, 0xc5, 0x57, 0xfc, 0x6e, 0x53, 0xc1, 0x6a, 0xf8, + 0x21, 0xb3, 0x18, 0x8a, 0x62, 0xf0, 0x5b, 0xc9, 0x10, 0x82, + 0x29, 0xbb, 0x86, 0x14, 0xbf, 0x2d, 0xf4, 0x66, 0xcd, 0x5f, + 0x73, 0xe1, 0x4a, 0xd8, 0x01, 0x93, 0x38, 0xaa, 0x97, 0x05, + 0xae, 0x3c, 0xe5, 0x77, 0xdc, 0x4e, 0xa6, 0x34, 0x9f, 0x0d, + 0xd4, 0x46, 0xed, 0x7f, 0x42, 0xd0, 0x7b, 0xe9, 0x30, 0xa2, + 0x09, 0x9b, 0xc4, 0x56, 0xfd, 0x6f, 0xb6, 0x24, 0x8f, 0x1d, + 0x20, 0xb2, 0x19, 0x8b, 0x52, 0xc0, 0x6b, 0xf9, 0x11, 0x83, + 0x28, 0xba, 0x63, 0xf1, 0x5a, 0xc8, 0xf5, 0x67, 0xcc, 0x5e, + 0x87, 0x15, 0xbe, 0x2c, 0xe6, 0x74, 0xdf, 0x4d, 0x94, 0x06, + 0xad, 0x3f, 0x02, 0x90, 0x3b, 0xa9, 0x70, 0xe2, 0x49, 0xdb, + 0x33, 0xa1, 0x0a, 0x98, 0x41, 0xd3, 0x78, 0xea, 0xd7, 0x45, + 0xee, 0x7c, 0xa5, 0x37, 0x9c, 0x0e, 0x51, 0xc3, 0x68, 0xfa, + 0x23, 0xb1, 0x1a, 0x88, 0xb5, 0x27, 0x8c, 0x1e, 0xc7, 0x55, + 0xfe, 0x6c, 0x84, 0x16, 0xbd, 0x2f, 0xf6, 0x64, 0xcf, 0x5d, + 0x60, 0xf2, 0x59, 0xcb, 0x12, 0x80, 0x2b, 0xb9, 0x95, 0x07, + 0xac, 0x3e, 0xe7, 0x75, 0xde, 0x4c, 0x71, 0xe3, 0x48, 0xda, + 0x03, 0x91, 0x3a, 0xa8, 0x40, 0xd2, 0x79, 0xeb, 0x32, 0xa0, + 0x0b, 0x99, 0xa4, 0x36, 0x9d, 0x0f, 0xd6, 0x44, 0xef, 0x7d, + 0x22, 0xb0, 0x1b, 0x89, 0x50, 0xc2, 0x69, 0xfb, 0xc6, 0x54, + 0xff, 0x6d, 0xb4, 0x26, 0x8d, 0x1f, 0xf7, 0x65, 0xce, 0x5c, + 0x85, 0x17, 0xbc, 0x2e, 0x13, 0x81, 0x2a, 0xb8, 0x61, 0xf3, + 0x58, 0xca, 0x00, 0x93, 0x3b, 0xa8, 0x76, 0xe5, 0x4d, 0xde, + 0xec, 0x7f, 0xd7, 0x44, 0x9a, 0x09, 0xa1, 0x32, 0xc5, 0x56, + 0xfe, 0x6d, 0xb3, 0x20, 0x88, 0x1b, 0x29, 0xba, 0x12, 0x81, + 0x5f, 0xcc, 0x64, 0xf7, 0x97, 0x04, 0xac, 0x3f, 0xe1, 0x72, + 0xda, 0x49, 0x7b, 0xe8, 0x40, 0xd3, 0x0d, 0x9e, 0x36, 0xa5, + 0x52, 0xc1, 0x69, 0xfa, 0x24, 0xb7, 0x1f, 0x8c, 0xbe, 0x2d, + 0x85, 0x16, 0xc8, 0x5b, 0xf3, 0x60, 0x33, 0xa0, 0x08, 0x9b, + 0x45, 0xd6, 0x7e, 0xed, 0xdf, 0x4c, 0xe4, 0x77, 0xa9, 0x3a, + 0x92, 0x01, 0xf6, 0x65, 0xcd, 0x5e, 0x80, 0x13, 0xbb, 0x28, + 0x1a, 0x89, 0x21, 0xb2, 0x6c, 0xff, 0x57, 0xc4, 0xa4, 0x37, + 0x9f, 0x0c, 0xd2, 0x41, 0xe9, 0x7a, 0x48, 0xdb, 0x73, 0xe0, + 0x3e, 0xad, 0x05, 0x96, 0x61, 0xf2, 0x5a, 0xc9, 0x17, 0x84, + 0x2c, 0xbf, 0x8d, 0x1e, 0xb6, 0x25, 0xfb, 0x68, 0xc0, 0x53, + 0x66, 0xf5, 0x5d, 0xce, 0x10, 0x83, 0x2b, 0xb8, 0x8a, 0x19, + 0xb1, 0x22, 0xfc, 0x6f, 0xc7, 0x54, 0xa3, 0x30, 0x98, 0x0b, + 0xd5, 0x46, 0xee, 0x7d, 0x4f, 0xdc, 0x74, 0xe7, 0x39, 0xaa, + 0x02, 0x91, 0xf1, 0x62, 0xca, 0x59, 0x87, 0x14, 0xbc, 0x2f, + 0x1d, 0x8e, 0x26, 0xb5, 0x6b, 0xf8, 0x50, 0xc3, 0x34, 0xa7, + 0x0f, 0x9c, 0x42, 0xd1, 0x79, 0xea, 0xd8, 0x4b, 0xe3, 0x70, + 0xae, 0x3d, 0x95, 0x06, 0x55, 0xc6, 0x6e, 0xfd, 0x23, 0xb0, + 0x18, 0x8b, 0xb9, 0x2a, 0x82, 0x11, 0xcf, 0x5c, 0xf4, 0x67, + 0x90, 0x03, 0xab, 0x38, 0xe6, 0x75, 0xdd, 0x4e, 0x7c, 0xef, + 0x47, 0xd4, 0x0a, 0x99, 0x31, 0xa2, 0xc2, 0x51, 0xf9, 0x6a, + 0xb4, 0x27, 0x8f, 0x1c, 0x2e, 0xbd, 0x15, 0x86, 0x58, 0xcb, + 0x63, 0xf0, 0x07, 0x94, 0x3c, 0xaf, 0x71, 0xe2, 0x4a, 0xd9, + 0xeb, 0x78, 0xd0, 0x43, 0x9d, 0x0e, 0xa6, 0x35, 0x00, 0x94, + 0x35, 0xa1, 0x6a, 0xfe, 0x5f, 0xcb, 0xd4, 0x40, 0xe1, 0x75, + 0xbe, 0x2a, 0x8b, 0x1f, 0xb5, 0x21, 0x80, 0x14, 0xdf, 0x4b, + 0xea, 0x7e, 0x61, 0xf5, 0x54, 0xc0, 0x0b, 0x9f, 0x3e, 0xaa, + 0x77, 0xe3, 0x42, 0xd6, 0x1d, 0x89, 0x28, 0xbc, 0xa3, 0x37, + 0x96, 0x02, 0xc9, 0x5d, 0xfc, 0x68, 0xc2, 0x56, 0xf7, 0x63, + 0xa8, 0x3c, 0x9d, 0x09, 0x16, 0x82, 0x23, 0xb7, 0x7c, 0xe8, + 0x49, 0xdd, 0xee, 0x7a, 0xdb, 0x4f, 0x84, 0x10, 0xb1, 0x25, + 0x3a, 0xae, 0x0f, 0x9b, 0x50, 0xc4, 0x65, 0xf1, 0x5b, 0xcf, + 0x6e, 0xfa, 0x31, 0xa5, 0x04, 0x90, 0x8f, 0x1b, 0xba, 0x2e, + 0xe5, 0x71, 0xd0, 0x44, 0x99, 0x0d, 0xac, 0x38, 0xf3, 0x67, + 0xc6, 0x52, 0x4d, 0xd9, 0x78, 0xec, 0x27, 0xb3, 0x12, 0x86, + 0x2c, 0xb8, 0x19, 0x8d, 0x46, 0xd2, 0x73, 0xe7, 0xf8, 0x6c, + 0xcd, 0x59, 0x92, 0x06, 0xa7, 0x33, 0xc1, 0x55, 0xf4, 0x60, + 0xab, 0x3f, 0x9e, 0x0a, 0x15, 0x81, 0x20, 0xb4, 0x7f, 0xeb, + 0x4a, 0xde, 0x74, 0xe0, 0x41, 0xd5, 0x1e, 0x8a, 0x2b, 0xbf, + 0xa0, 0x34, 0x95, 0x01, 0xca, 0x5e, 0xff, 0x6b, 0xb6, 0x22, + 0x83, 0x17, 0xdc, 0x48, 0xe9, 0x7d, 0x62, 0xf6, 0x57, 0xc3, + 0x08, 0x9c, 0x3d, 0xa9, 0x03, 0x97, 0x36, 0xa2, 0x69, 0xfd, + 0x5c, 0xc8, 0xd7, 0x43, 0xe2, 0x76, 0xbd, 0x29, 0x88, 0x1c, + 0x2f, 0xbb, 0x1a, 0x8e, 0x45, 0xd1, 0x70, 0xe4, 0xfb, 0x6f, + 0xce, 0x5a, 0x91, 0x05, 0xa4, 0x30, 0x9a, 0x0e, 0xaf, 0x3b, + 0xf0, 0x64, 0xc5, 0x51, 0x4e, 0xda, 0x7b, 0xef, 0x24, 0xb0, + 0x11, 0x85, 0x58, 0xcc, 0x6d, 0xf9, 0x32, 0xa6, 0x07, 0x93, + 0x8c, 0x18, 0xb9, 0x2d, 0xe6, 0x72, 0xd3, 0x47, 0xed, 0x79, + 0xd8, 0x4c, 0x87, 0x13, 0xb2, 0x26, 0x39, 0xad, 0x0c, 0x98, + 0x53, 0xc7, 0x66, 0xf2, 0x00, 0x95, 0x37, 0xa2, 0x6e, 0xfb, + 0x59, 0xcc, 0xdc, 0x49, 0xeb, 0x7e, 0xb2, 0x27, 0x85, 0x10, + 0xa5, 0x30, 0x92, 0x07, 0xcb, 0x5e, 0xfc, 0x69, 0x79, 0xec, + 0x4e, 0xdb, 0x17, 0x82, 0x20, 0xb5, 0x57, 0xc2, 0x60, 0xf5, + 0x39, 0xac, 0x0e, 0x9b, 0x8b, 0x1e, 0xbc, 0x29, 0xe5, 0x70, + 0xd2, 0x47, 0xf2, 0x67, 0xc5, 0x50, 0x9c, 0x09, 0xab, 0x3e, + 0x2e, 0xbb, 0x19, 0x8c, 0x40, 0xd5, 0x77, 0xe2, 0xae, 0x3b, + 0x99, 0x0c, 0xc0, 0x55, 0xf7, 0x62, 0x72, 0xe7, 0x45, 0xd0, + 0x1c, 0x89, 0x2b, 0xbe, 0x0b, 0x9e, 0x3c, 0xa9, 0x65, 0xf0, + 0x52, 0xc7, 0xd7, 0x42, 0xe0, 0x75, 0xb9, 0x2c, 0x8e, 0x1b, + 0xf9, 0x6c, 0xce, 0x5b, 0x97, 0x02, 0xa0, 0x35, 0x25, 0xb0, + 0x12, 0x87, 0x4b, 0xde, 0x7c, 0xe9, 0x5c, 0xc9, 0x6b, 0xfe, + 0x32, 0xa7, 0x05, 0x90, 0x80, 0x15, 0xb7, 0x22, 0xee, 0x7b, + 0xd9, 0x4c, 0x41, 0xd4, 0x76, 0xe3, 0x2f, 0xba, 0x18, 0x8d, + 0x9d, 0x08, 0xaa, 0x3f, 0xf3, 0x66, 0xc4, 0x51, 0xe4, 0x71, + 0xd3, 0x46, 0x8a, 0x1f, 0xbd, 0x28, 0x38, 0xad, 0x0f, 0x9a, + 0x56, 0xc3, 0x61, 0xf4, 0x16, 0x83, 0x21, 0xb4, 0x78, 0xed, + 0x4f, 0xda, 0xca, 0x5f, 0xfd, 0x68, 0xa4, 0x31, 0x93, 0x06, + 0xb3, 0x26, 0x84, 0x11, 0xdd, 0x48, 0xea, 0x7f, 0x6f, 0xfa, + 0x58, 0xcd, 0x01, 0x94, 0x36, 0xa3, 0xef, 0x7a, 0xd8, 0x4d, + 0x81, 0x14, 0xb6, 0x23, 0x33, 0xa6, 0x04, 0x91, 0x5d, 0xc8, + 0x6a, 0xff, 0x4a, 0xdf, 0x7d, 0xe8, 0x24, 0xb1, 0x13, 0x86, + 0x96, 0x03, 0xa1, 0x34, 0xf8, 0x6d, 0xcf, 0x5a, 0xb8, 0x2d, + 0x8f, 0x1a, 0xd6, 0x43, 0xe1, 0x74, 0x64, 0xf1, 0x53, 0xc6, + 0x0a, 0x9f, 0x3d, 0xa8, 0x1d, 0x88, 0x2a, 0xbf, 0x73, 0xe6, + 0x44, 0xd1, 0xc1, 0x54, 0xf6, 0x63, 0xaf, 0x3a, 0x98, 0x0d, + 0x00, 0x96, 0x31, 0xa7, 0x62, 0xf4, 0x53, 0xc5, 0xc4, 0x52, + 0xf5, 0x63, 0xa6, 0x30, 0x97, 0x01, 0x95, 0x03, 0xa4, 0x32, + 0xf7, 0x61, 0xc6, 0x50, 0x51, 0xc7, 0x60, 0xf6, 0x33, 0xa5, + 0x02, 0x94, 0x37, 0xa1, 0x06, 0x90, 0x55, 0xc3, 0x64, 0xf2, + 0xf3, 0x65, 0xc2, 0x54, 0x91, 0x07, 0xa0, 0x36, 0xa2, 0x34, + 0x93, 0x05, 0xc0, 0x56, 0xf1, 0x67, 0x66, 0xf0, 0x57, 0xc1, + 0x04, 0x92, 0x35, 0xa3, 0x6e, 0xf8, 0x5f, 0xc9, 0x0c, 0x9a, + 0x3d, 0xab, 0xaa, 0x3c, 0x9b, 0x0d, 0xc8, 0x5e, 0xf9, 0x6f, + 0xfb, 0x6d, 0xca, 0x5c, 0x99, 0x0f, 0xa8, 0x3e, 0x3f, 0xa9, + 0x0e, 0x98, 0x5d, 0xcb, 0x6c, 0xfa, 0x59, 0xcf, 0x68, 0xfe, + 0x3b, 0xad, 0x0a, 0x9c, 0x9d, 0x0b, 0xac, 0x3a, 0xff, 0x69, + 0xce, 0x58, 0xcc, 0x5a, 0xfd, 0x6b, 0xae, 0x38, 0x9f, 0x09, + 0x08, 0x9e, 0x39, 0xaf, 0x6a, 0xfc, 0x5b, 0xcd, 0xdc, 0x4a, + 0xed, 0x7b, 0xbe, 0x28, 0x8f, 0x19, 0x18, 0x8e, 0x29, 0xbf, + 0x7a, 0xec, 0x4b, 0xdd, 0x49, 0xdf, 0x78, 0xee, 0x2b, 0xbd, + 0x1a, 0x8c, 0x8d, 0x1b, 0xbc, 0x2a, 0xef, 0x79, 0xde, 0x48, + 0xeb, 0x7d, 0xda, 0x4c, 0x89, 0x1f, 0xb8, 0x2e, 0x2f, 0xb9, + 0x1e, 0x88, 0x4d, 0xdb, 0x7c, 0xea, 0x7e, 0xe8, 0x4f, 0xd9, + 0x1c, 0x8a, 0x2d, 0xbb, 0xba, 0x2c, 0x8b, 0x1d, 0xd8, 0x4e, + 0xe9, 0x7f, 0xb2, 0x24, 0x83, 0x15, 0xd0, 0x46, 0xe1, 0x77, + 0x76, 0xe0, 0x47, 0xd1, 0x14, 0x82, 0x25, 0xb3, 0x27, 0xb1, + 0x16, 0x80, 0x45, 0xd3, 0x74, 0xe2, 0xe3, 0x75, 0xd2, 0x44, + 0x81, 0x17, 0xb0, 0x26, 0x85, 0x13, 0xb4, 0x22, 0xe7, 0x71, + 0xd6, 0x40, 0x41, 0xd7, 0x70, 0xe6, 0x23, 0xb5, 0x12, 0x84, + 0x10, 0x86, 0x21, 0xb7, 0x72, 0xe4, 0x43, 0xd5, 0xd4, 0x42, + 0xe5, 0x73, 0xb6, 0x20, 0x87, 0x11, 0x00, 0x97, 0x33, 0xa4, + 0x66, 0xf1, 0x55, 0xc2, 0xcc, 0x5b, 0xff, 0x68, 0xaa, 0x3d, + 0x99, 0x0e, 0x85, 0x12, 0xb6, 0x21, 0xe3, 0x74, 0xd0, 0x47, + 0x49, 0xde, 0x7a, 0xed, 0x2f, 0xb8, 0x1c, 0x8b, 0x17, 0x80, + 0x24, 0xb3, 0x71, 0xe6, 0x42, 0xd5, 0xdb, 0x4c, 0xe8, 0x7f, + 0xbd, 0x2a, 0x8e, 0x19, 0x92, 0x05, 0xa1, 0x36, 0xf4, 0x63, + 0xc7, 0x50, 0x5e, 0xc9, 0x6d, 0xfa, 0x38, 0xaf, 0x0b, 0x9c, + 0x2e, 0xb9, 0x1d, 0x8a, 0x48, 0xdf, 0x7b, 0xec, 0xe2, 0x75, + 0xd1, 0x46, 0x84, 0x13, 0xb7, 0x20, 0xab, 0x3c, 0x98, 0x0f, + 0xcd, 0x5a, 0xfe, 0x69, 0x67, 0xf0, 0x54, 0xc3, 0x01, 0x96, + 0x32, 0xa5, 0x39, 0xae, 0x0a, 0x9d, 0x5f, 0xc8, 0x6c, 0xfb, + 0xf5, 0x62, 0xc6, 0x51, 0x93, 0x04, 0xa0, 0x37, 0xbc, 0x2b, + 0x8f, 0x18, 0xda, 0x4d, 0xe9, 0x7e, 0x70, 0xe7, 0x43, 0xd4, + 0x16, 0x81, 0x25, 0xb2, 0x5c, 0xcb, 0x6f, 0xf8, 0x3a, 0xad, + 0x09, 0x9e, 0x90, 0x07, 0xa3, 0x34, 0xf6, 0x61, 0xc5, 0x52, + 0xd9, 0x4e, 0xea, 0x7d, 0xbf, 0x28, 0x8c, 0x1b, 0x15, 0x82, + 0x26, 0xb1, 0x73, 0xe4, 0x40, 0xd7, 0x4b, 0xdc, 0x78, 0xef, + 0x2d, 0xba, 0x1e, 0x89, 0x87, 0x10, 0xb4, 0x23, 0xe1, 0x76, + 0xd2, 0x45, 0xce, 0x59, 0xfd, 0x6a, 0xa8, 0x3f, 0x9b, 0x0c, + 0x02, 0x95, 0x31, 0xa6, 0x64, 0xf3, 0x57, 0xc0, 0x72, 0xe5, + 0x41, 0xd6, 0x14, 0x83, 0x27, 0xb0, 0xbe, 0x29, 0x8d, 0x1a, + 0xd8, 0x4f, 0xeb, 0x7c, 0xf7, 0x60, 0xc4, 0x53, 0x91, 0x06, + 0xa2, 0x35, 0x3b, 0xac, 0x08, 0x9f, 0x5d, 0xca, 0x6e, 0xf9, + 0x65, 0xf2, 0x56, 0xc1, 0x03, 0x94, 0x30, 0xa7, 0xa9, 0x3e, + 0x9a, 0x0d, 0xcf, 0x58, 0xfc, 0x6b, 0xe0, 0x77, 0xd3, 0x44, + 0x86, 0x11, 0xb5, 0x22, 0x2c, 0xbb, 0x1f, 0x88, 0x4a, 0xdd, + 0x79, 0xee, 0x00, 0x98, 0x2d, 0xb5, 0x5a, 0xc2, 0x77, 0xef, + 0xb4, 0x2c, 0x99, 0x01, 0xee, 0x76, 0xc3, 0x5b, 0x75, 0xed, + 0x58, 0xc0, 0x2f, 0xb7, 0x02, 0x9a, 0xc1, 0x59, 0xec, 0x74, + 0x9b, 0x03, 0xb6, 0x2e, 0xea, 0x72, 0xc7, 0x5f, 0xb0, 0x28, + 0x9d, 0x05, 0x5e, 0xc6, 0x73, 0xeb, 0x04, 0x9c, 0x29, 0xb1, + 0x9f, 0x07, 0xb2, 0x2a, 0xc5, 0x5d, 0xe8, 0x70, 0x2b, 0xb3, + 0x06, 0x9e, 0x71, 0xe9, 0x5c, 0xc4, 0xc9, 0x51, 0xe4, 0x7c, + 0x93, 0x0b, 0xbe, 0x26, 0x7d, 0xe5, 0x50, 0xc8, 0x27, 0xbf, + 0x0a, 0x92, 0xbc, 0x24, 0x91, 0x09, 0xe6, 0x7e, 0xcb, 0x53, + 0x08, 0x90, 0x25, 0xbd, 0x52, 0xca, 0x7f, 0xe7, 0x23, 0xbb, + 0x0e, 0x96, 0x79, 0xe1, 0x54, 0xcc, 0x97, 0x0f, 0xba, 0x22, + 0xcd, 0x55, 0xe0, 0x78, 0x56, 0xce, 0x7b, 0xe3, 0x0c, 0x94, + 0x21, 0xb9, 0xe2, 0x7a, 0xcf, 0x57, 0xb8, 0x20, 0x95, 0x0d, + 0x8f, 0x17, 0xa2, 0x3a, 0xd5, 0x4d, 0xf8, 0x60, 0x3b, 0xa3, + 0x16, 0x8e, 0x61, 0xf9, 0x4c, 0xd4, 0xfa, 0x62, 0xd7, 0x4f, + 0xa0, 0x38, 0x8d, 0x15, 0x4e, 0xd6, 0x63, 0xfb, 0x14, 0x8c, + 0x39, 0xa1, 0x65, 0xfd, 0x48, 0xd0, 0x3f, 0xa7, 0x12, 0x8a, + 0xd1, 0x49, 0xfc, 0x64, 0x8b, 0x13, 0xa6, 0x3e, 0x10, 0x88, + 0x3d, 0xa5, 0x4a, 0xd2, 0x67, 0xff, 0xa4, 0x3c, 0x89, 0x11, + 0xfe, 0x66, 0xd3, 0x4b, 0x46, 0xde, 0x6b, 0xf3, 0x1c, 0x84, + 0x31, 0xa9, 0xf2, 0x6a, 0xdf, 0x47, 0xa8, 0x30, 0x85, 0x1d, + 0x33, 0xab, 0x1e, 0x86, 0x69, 0xf1, 0x44, 0xdc, 0x87, 0x1f, + 0xaa, 0x32, 0xdd, 0x45, 0xf0, 0x68, 0xac, 0x34, 0x81, 0x19, + 0xf6, 0x6e, 0xdb, 0x43, 0x18, 0x80, 0x35, 0xad, 0x42, 0xda, + 0x6f, 0xf7, 0xd9, 0x41, 0xf4, 0x6c, 0x83, 0x1b, 0xae, 0x36, + 0x6d, 0xf5, 0x40, 0xd8, 0x37, 0xaf, 0x1a, 0x82, 0x00, 0x99, + 0x2f, 0xb6, 0x5e, 0xc7, 0x71, 0xe8, 0xbc, 0x25, 0x93, 0x0a, + 0xe2, 0x7b, 0xcd, 0x54, 0x65, 0xfc, 0x4a, 0xd3, 0x3b, 0xa2, + 0x14, 0x8d, 0xd9, 0x40, 0xf6, 0x6f, 0x87, 0x1e, 0xa8, 0x31, + 0xca, 0x53, 0xe5, 0x7c, 0x94, 0x0d, 0xbb, 0x22, 0x76, 0xef, + 0x59, 0xc0, 0x28, 0xb1, 0x07, 0x9e, 0xaf, 0x36, 0x80, 0x19, + 0xf1, 0x68, 0xde, 0x47, 0x13, 0x8a, 0x3c, 0xa5, 0x4d, 0xd4, + 0x62, 0xfb, 0x89, 0x10, 0xa6, 0x3f, 0xd7, 0x4e, 0xf8, 0x61, + 0x35, 0xac, 0x1a, 0x83, 0x6b, 0xf2, 0x44, 0xdd, 0xec, 0x75, + 0xc3, 0x5a, 0xb2, 0x2b, 0x9d, 0x04, 0x50, 0xc9, 0x7f, 0xe6, + 0x0e, 0x97, 0x21, 0xb8, 0x43, 0xda, 0x6c, 0xf5, 0x1d, 0x84, + 0x32, 0xab, 0xff, 0x66, 0xd0, 0x49, 0xa1, 0x38, 0x8e, 0x17, + 0x26, 0xbf, 0x09, 0x90, 0x78, 0xe1, 0x57, 0xce, 0x9a, 0x03, + 0xb5, 0x2c, 0xc4, 0x5d, 0xeb, 0x72, 0x0f, 0x96, 0x20, 0xb9, + 0x51, 0xc8, 0x7e, 0xe7, 0xb3, 0x2a, 0x9c, 0x05, 0xed, 0x74, + 0xc2, 0x5b, 0x6a, 0xf3, 0x45, 0xdc, 0x34, 0xad, 0x1b, 0x82, + 0xd6, 0x4f, 0xf9, 0x60, 0x88, 0x11, 0xa7, 0x3e, 0xc5, 0x5c, + 0xea, 0x73, 0x9b, 0x02, 0xb4, 0x2d, 0x79, 0xe0, 0x56, 0xcf, + 0x27, 0xbe, 0x08, 0x91, 0xa0, 0x39, 0x8f, 0x16, 0xfe, 0x67, + 0xd1, 0x48, 0x1c, 0x85, 0x33, 0xaa, 0x42, 0xdb, 0x6d, 0xf4, + 0x86, 0x1f, 0xa9, 0x30, 0xd8, 0x41, 0xf7, 0x6e, 0x3a, 0xa3, + 0x15, 0x8c, 0x64, 0xfd, 0x4b, 0xd2, 0xe3, 0x7a, 0xcc, 0x55, + 0xbd, 0x24, 0x92, 0x0b, 0x5f, 0xc6, 0x70, 0xe9, 0x01, 0x98, + 0x2e, 0xb7, 0x4c, 0xd5, 0x63, 0xfa, 0x12, 0x8b, 0x3d, 0xa4, + 0xf0, 0x69, 0xdf, 0x46, 0xae, 0x37, 0x81, 0x18, 0x29, 0xb0, + 0x06, 0x9f, 0x77, 0xee, 0x58, 0xc1, 0x95, 0x0c, 0xba, 0x23, + 0xcb, 0x52, 0xe4, 0x7d, 0x00, 0x9a, 0x29, 0xb3, 0x52, 0xc8, + 0x7b, 0xe1, 0xa4, 0x3e, 0x8d, 0x17, 0xf6, 0x6c, 0xdf, 0x45, + 0x55, 0xcf, 0x7c, 0xe6, 0x07, 0x9d, 0x2e, 0xb4, 0xf1, 0x6b, + 0xd8, 0x42, 0xa3, 0x39, 0x8a, 0x10, 0xaa, 0x30, 0x83, 0x19, + 0xf8, 0x62, 0xd1, 0x4b, 0x0e, 0x94, 0x27, 0xbd, 0x5c, 0xc6, + 0x75, 0xef, 0xff, 0x65, 0xd6, 0x4c, 0xad, 0x37, 0x84, 0x1e, + 0x5b, 0xc1, 0x72, 0xe8, 0x09, 0x93, 0x20, 0xba, 0x49, 0xd3, + 0x60, 0xfa, 0x1b, 0x81, 0x32, 0xa8, 0xed, 0x77, 0xc4, 0x5e, + 0xbf, 0x25, 0x96, 0x0c, 0x1c, 0x86, 0x35, 0xaf, 0x4e, 0xd4, + 0x67, 0xfd, 0xb8, 0x22, 0x91, 0x0b, 0xea, 0x70, 0xc3, 0x59, + 0xe3, 0x79, 0xca, 0x50, 0xb1, 0x2b, 0x98, 0x02, 0x47, 0xdd, + 0x6e, 0xf4, 0x15, 0x8f, 0x3c, 0xa6, 0xb6, 0x2c, 0x9f, 0x05, + 0xe4, 0x7e, 0xcd, 0x57, 0x12, 0x88, 0x3b, 0xa1, 0x40, 0xda, + 0x69, 0xf3, 0x92, 0x08, 0xbb, 0x21, 0xc0, 0x5a, 0xe9, 0x73, + 0x36, 0xac, 0x1f, 0x85, 0x64, 0xfe, 0x4d, 0xd7, 0xc7, 0x5d, + 0xee, 0x74, 0x95, 0x0f, 0xbc, 0x26, 0x63, 0xf9, 0x4a, 0xd0, + 0x31, 0xab, 0x18, 0x82, 0x38, 0xa2, 0x11, 0x8b, 0x6a, 0xf0, + 0x43, 0xd9, 0x9c, 0x06, 0xb5, 0x2f, 0xce, 0x54, 0xe7, 0x7d, + 0x6d, 0xf7, 0x44, 0xde, 0x3f, 0xa5, 0x16, 0x8c, 0xc9, 0x53, + 0xe0, 0x7a, 0x9b, 0x01, 0xb2, 0x28, 0xdb, 0x41, 0xf2, 0x68, + 0x89, 0x13, 0xa0, 0x3a, 0x7f, 0xe5, 0x56, 0xcc, 0x2d, 0xb7, + 0x04, 0x9e, 0x8e, 0x14, 0xa7, 0x3d, 0xdc, 0x46, 0xf5, 0x6f, + 0x2a, 0xb0, 0x03, 0x99, 0x78, 0xe2, 0x51, 0xcb, 0x71, 0xeb, + 0x58, 0xc2, 0x23, 0xb9, 0x0a, 0x90, 0xd5, 0x4f, 0xfc, 0x66, + 0x87, 0x1d, 0xae, 0x34, 0x24, 0xbe, 0x0d, 0x97, 0x76, 0xec, + 0x5f, 0xc5, 0x80, 0x1a, 0xa9, 0x33, 0xd2, 0x48, 0xfb, 0x61, + 0x00, 0x9b, 0x2b, 0xb0, 0x56, 0xcd, 0x7d, 0xe6, 0xac, 0x37, + 0x87, 0x1c, 0xfa, 0x61, 0xd1, 0x4a, 0x45, 0xde, 0x6e, 0xf5, + 0x13, 0x88, 0x38, 0xa3, 0xe9, 0x72, 0xc2, 0x59, 0xbf, 0x24, + 0x94, 0x0f, 0x8a, 0x11, 0xa1, 0x3a, 0xdc, 0x47, 0xf7, 0x6c, + 0x26, 0xbd, 0x0d, 0x96, 0x70, 0xeb, 0x5b, 0xc0, 0xcf, 0x54, + 0xe4, 0x7f, 0x99, 0x02, 0xb2, 0x29, 0x63, 0xf8, 0x48, 0xd3, + 0x35, 0xae, 0x1e, 0x85, 0x09, 0x92, 0x22, 0xb9, 0x5f, 0xc4, + 0x74, 0xef, 0xa5, 0x3e, 0x8e, 0x15, 0xf3, 0x68, 0xd8, 0x43, + 0x4c, 0xd7, 0x67, 0xfc, 0x1a, 0x81, 0x31, 0xaa, 0xe0, 0x7b, + 0xcb, 0x50, 0xb6, 0x2d, 0x9d, 0x06, 0x83, 0x18, 0xa8, 0x33, + 0xd5, 0x4e, 0xfe, 0x65, 0x2f, 0xb4, 0x04, 0x9f, 0x79, 0xe2, + 0x52, 0xc9, 0xc6, 0x5d, 0xed, 0x76, 0x90, 0x0b, 0xbb, 0x20, + 0x6a, 0xf1, 0x41, 0xda, 0x3c, 0xa7, 0x17, 0x8c, 0x12, 0x89, + 0x39, 0xa2, 0x44, 0xdf, 0x6f, 0xf4, 0xbe, 0x25, 0x95, 0x0e, + 0xe8, 0x73, 0xc3, 0x58, 0x57, 0xcc, 0x7c, 0xe7, 0x01, 0x9a, + 0x2a, 0xb1, 0xfb, 0x60, 0xd0, 0x4b, 0xad, 0x36, 0x86, 0x1d, + 0x98, 0x03, 0xb3, 0x28, 0xce, 0x55, 0xe5, 0x7e, 0x34, 0xaf, + 0x1f, 0x84, 0x62, 0xf9, 0x49, 0xd2, 0xdd, 0x46, 0xf6, 0x6d, + 0x8b, 0x10, 0xa0, 0x3b, 0x71, 0xea, 0x5a, 0xc1, 0x27, 0xbc, + 0x0c, 0x97, 0x1b, 0x80, 0x30, 0xab, 0x4d, 0xd6, 0x66, 0xfd, + 0xb7, 0x2c, 0x9c, 0x07, 0xe1, 0x7a, 0xca, 0x51, 0x5e, 0xc5, + 0x75, 0xee, 0x08, 0x93, 0x23, 0xb8, 0xf2, 0x69, 0xd9, 0x42, + 0xa4, 0x3f, 0x8f, 0x14, 0x91, 0x0a, 0xba, 0x21, 0xc7, 0x5c, + 0xec, 0x77, 0x3d, 0xa6, 0x16, 0x8d, 0x6b, 0xf0, 0x40, 0xdb, + 0xd4, 0x4f, 0xff, 0x64, 0x82, 0x19, 0xa9, 0x32, 0x78, 0xe3, + 0x53, 0xc8, 0x2e, 0xb5, 0x05, 0x9e, 0x00, 0x9c, 0x25, 0xb9, + 0x4a, 0xd6, 0x6f, 0xf3, 0x94, 0x08, 0xb1, 0x2d, 0xde, 0x42, + 0xfb, 0x67, 0x35, 0xa9, 0x10, 0x8c, 0x7f, 0xe3, 0x5a, 0xc6, + 0xa1, 0x3d, 0x84, 0x18, 0xeb, 0x77, 0xce, 0x52, 0x6a, 0xf6, + 0x4f, 0xd3, 0x20, 0xbc, 0x05, 0x99, 0xfe, 0x62, 0xdb, 0x47, + 0xb4, 0x28, 0x91, 0x0d, 0x5f, 0xc3, 0x7a, 0xe6, 0x15, 0x89, + 0x30, 0xac, 0xcb, 0x57, 0xee, 0x72, 0x81, 0x1d, 0xa4, 0x38, + 0xd4, 0x48, 0xf1, 0x6d, 0x9e, 0x02, 0xbb, 0x27, 0x40, 0xdc, + 0x65, 0xf9, 0x0a, 0x96, 0x2f, 0xb3, 0xe1, 0x7d, 0xc4, 0x58, + 0xab, 0x37, 0x8e, 0x12, 0x75, 0xe9, 0x50, 0xcc, 0x3f, 0xa3, + 0x1a, 0x86, 0xbe, 0x22, 0x9b, 0x07, 0xf4, 0x68, 0xd1, 0x4d, + 0x2a, 0xb6, 0x0f, 0x93, 0x60, 0xfc, 0x45, 0xd9, 0x8b, 0x17, + 0xae, 0x32, 0xc1, 0x5d, 0xe4, 0x78, 0x1f, 0x83, 0x3a, 0xa6, + 0x55, 0xc9, 0x70, 0xec, 0xb5, 0x29, 0x90, 0x0c, 0xff, 0x63, + 0xda, 0x46, 0x21, 0xbd, 0x04, 0x98, 0x6b, 0xf7, 0x4e, 0xd2, + 0x80, 0x1c, 0xa5, 0x39, 0xca, 0x56, 0xef, 0x73, 0x14, 0x88, + 0x31, 0xad, 0x5e, 0xc2, 0x7b, 0xe7, 0xdf, 0x43, 0xfa, 0x66, + 0x95, 0x09, 0xb0, 0x2c, 0x4b, 0xd7, 0x6e, 0xf2, 0x01, 0x9d, + 0x24, 0xb8, 0xea, 0x76, 0xcf, 0x53, 0xa0, 0x3c, 0x85, 0x19, + 0x7e, 0xe2, 0x5b, 0xc7, 0x34, 0xa8, 0x11, 0x8d, 0x61, 0xfd, + 0x44, 0xd8, 0x2b, 0xb7, 0x0e, 0x92, 0xf5, 0x69, 0xd0, 0x4c, + 0xbf, 0x23, 0x9a, 0x06, 0x54, 0xc8, 0x71, 0xed, 0x1e, 0x82, + 0x3b, 0xa7, 0xc0, 0x5c, 0xe5, 0x79, 0x8a, 0x16, 0xaf, 0x33, + 0x0b, 0x97, 0x2e, 0xb2, 0x41, 0xdd, 0x64, 0xf8, 0x9f, 0x03, + 0xba, 0x26, 0xd5, 0x49, 0xf0, 0x6c, 0x3e, 0xa2, 0x1b, 0x87, + 0x74, 0xe8, 0x51, 0xcd, 0xaa, 0x36, 0x8f, 0x13, 0xe0, 0x7c, + 0xc5, 0x59, 0x00, 0x9d, 0x27, 0xba, 0x4e, 0xd3, 0x69, 0xf4, + 0x9c, 0x01, 0xbb, 0x26, 0xd2, 0x4f, 0xf5, 0x68, 0x25, 0xb8, + 0x02, 0x9f, 0x6b, 0xf6, 0x4c, 0xd1, 0xb9, 0x24, 0x9e, 0x03, + 0xf7, 0x6a, 0xd0, 0x4d, 0x4a, 0xd7, 0x6d, 0xf0, 0x04, 0x99, + 0x23, 0xbe, 0xd6, 0x4b, 0xf1, 0x6c, 0x98, 0x05, 0xbf, 0x22, + 0x6f, 0xf2, 0x48, 0xd5, 0x21, 0xbc, 0x06, 0x9b, 0xf3, 0x6e, + 0xd4, 0x49, 0xbd, 0x20, 0x9a, 0x07, 0x94, 0x09, 0xb3, 0x2e, + 0xda, 0x47, 0xfd, 0x60, 0x08, 0x95, 0x2f, 0xb2, 0x46, 0xdb, + 0x61, 0xfc, 0xb1, 0x2c, 0x96, 0x0b, 0xff, 0x62, 0xd8, 0x45, + 0x2d, 0xb0, 0x0a, 0x97, 0x63, 0xfe, 0x44, 0xd9, 0xde, 0x43, + 0xf9, 0x64, 0x90, 0x0d, 0xb7, 0x2a, 0x42, 0xdf, 0x65, 0xf8, + 0x0c, 0x91, 0x2b, 0xb6, 0xfb, 0x66, 0xdc, 0x41, 0xb5, 0x28, + 0x92, 0x0f, 0x67, 0xfa, 0x40, 0xdd, 0x29, 0xb4, 0x0e, 0x93, + 0x35, 0xa8, 0x12, 0x8f, 0x7b, 0xe6, 0x5c, 0xc1, 0xa9, 0x34, + 0x8e, 0x13, 0xe7, 0x7a, 0xc0, 0x5d, 0x10, 0x8d, 0x37, 0xaa, + 0x5e, 0xc3, 0x79, 0xe4, 0x8c, 0x11, 0xab, 0x36, 0xc2, 0x5f, + 0xe5, 0x78, 0x7f, 0xe2, 0x58, 0xc5, 0x31, 0xac, 0x16, 0x8b, + 0xe3, 0x7e, 0xc4, 0x59, 0xad, 0x30, 0x8a, 0x17, 0x5a, 0xc7, + 0x7d, 0xe0, 0x14, 0x89, 0x33, 0xae, 0xc6, 0x5b, 0xe1, 0x7c, + 0x88, 0x15, 0xaf, 0x32, 0xa1, 0x3c, 0x86, 0x1b, 0xef, 0x72, + 0xc8, 0x55, 0x3d, 0xa0, 0x1a, 0x87, 0x73, 0xee, 0x54, 0xc9, + 0x84, 0x19, 0xa3, 0x3e, 0xca, 0x57, 0xed, 0x70, 0x18, 0x85, + 0x3f, 0xa2, 0x56, 0xcb, 0x71, 0xec, 0xeb, 0x76, 0xcc, 0x51, + 0xa5, 0x38, 0x82, 0x1f, 0x77, 0xea, 0x50, 0xcd, 0x39, 0xa4, + 0x1e, 0x83, 0xce, 0x53, 0xe9, 0x74, 0x80, 0x1d, 0xa7, 0x3a, + 0x52, 0xcf, 0x75, 0xe8, 0x1c, 0x81, 0x3b, 0xa6, 0x00, 0x9e, + 0x21, 0xbf, 0x42, 0xdc, 0x63, 0xfd, 0x84, 0x1a, 0xa5, 0x3b, + 0xc6, 0x58, 0xe7, 0x79, 0x15, 0x8b, 0x34, 0xaa, 0x57, 0xc9, + 0x76, 0xe8, 0x91, 0x0f, 0xb0, 0x2e, 0xd3, 0x4d, 0xf2, 0x6c, + 0x2a, 0xb4, 0x0b, 0x95, 0x68, 0xf6, 0x49, 0xd7, 0xae, 0x30, + 0x8f, 0x11, 0xec, 0x72, 0xcd, 0x53, 0x3f, 0xa1, 0x1e, 0x80, + 0x7d, 0xe3, 0x5c, 0xc2, 0xbb, 0x25, 0x9a, 0x04, 0xf9, 0x67, + 0xd8, 0x46, 0x54, 0xca, 0x75, 0xeb, 0x16, 0x88, 0x37, 0xa9, + 0xd0, 0x4e, 0xf1, 0x6f, 0x92, 0x0c, 0xb3, 0x2d, 0x41, 0xdf, + 0x60, 0xfe, 0x03, 0x9d, 0x22, 0xbc, 0xc5, 0x5b, 0xe4, 0x7a, + 0x87, 0x19, 0xa6, 0x38, 0x7e, 0xe0, 0x5f, 0xc1, 0x3c, 0xa2, + 0x1d, 0x83, 0xfa, 0x64, 0xdb, 0x45, 0xb8, 0x26, 0x99, 0x07, + 0x6b, 0xf5, 0x4a, 0xd4, 0x29, 0xb7, 0x08, 0x96, 0xef, 0x71, + 0xce, 0x50, 0xad, 0x33, 0x8c, 0x12, 0xa8, 0x36, 0x89, 0x17, + 0xea, 0x74, 0xcb, 0x55, 0x2c, 0xb2, 0x0d, 0x93, 0x6e, 0xf0, + 0x4f, 0xd1, 0xbd, 0x23, 0x9c, 0x02, 0xff, 0x61, 0xde, 0x40, + 0x39, 0xa7, 0x18, 0x86, 0x7b, 0xe5, 0x5a, 0xc4, 0x82, 0x1c, + 0xa3, 0x3d, 0xc0, 0x5e, 0xe1, 0x7f, 0x06, 0x98, 0x27, 0xb9, + 0x44, 0xda, 0x65, 0xfb, 0x97, 0x09, 0xb6, 0x28, 0xd5, 0x4b, + 0xf4, 0x6a, 0x13, 0x8d, 0x32, 0xac, 0x51, 0xcf, 0x70, 0xee, + 0xfc, 0x62, 0xdd, 0x43, 0xbe, 0x20, 0x9f, 0x01, 0x78, 0xe6, + 0x59, 0xc7, 0x3a, 0xa4, 0x1b, 0x85, 0xe9, 0x77, 0xc8, 0x56, + 0xab, 0x35, 0x8a, 0x14, 0x6d, 0xf3, 0x4c, 0xd2, 0x2f, 0xb1, + 0x0e, 0x90, 0xd6, 0x48, 0xf7, 0x69, 0x94, 0x0a, 0xb5, 0x2b, + 0x52, 0xcc, 0x73, 0xed, 0x10, 0x8e, 0x31, 0xaf, 0xc3, 0x5d, + 0xe2, 0x7c, 0x81, 0x1f, 0xa0, 0x3e, 0x47, 0xd9, 0x66, 0xf8, + 0x05, 0x9b, 0x24, 0xba, 0x00, 0x9f, 0x23, 0xbc, 0x46, 0xd9, + 0x65, 0xfa, 0x8c, 0x13, 0xaf, 0x30, 0xca, 0x55, 0xe9, 0x76, + 0x05, 0x9a, 0x26, 0xb9, 0x43, 0xdc, 0x60, 0xff, 0x89, 0x16, + 0xaa, 0x35, 0xcf, 0x50, 0xec, 0x73, 0x0a, 0x95, 0x29, 0xb6, + 0x4c, 0xd3, 0x6f, 0xf0, 0x86, 0x19, 0xa5, 0x3a, 0xc0, 0x5f, + 0xe3, 0x7c, 0x0f, 0x90, 0x2c, 0xb3, 0x49, 0xd6, 0x6a, 0xf5, + 0x83, 0x1c, 0xa0, 0x3f, 0xc5, 0x5a, 0xe6, 0x79, 0x14, 0x8b, + 0x37, 0xa8, 0x52, 0xcd, 0x71, 0xee, 0x98, 0x07, 0xbb, 0x24, + 0xde, 0x41, 0xfd, 0x62, 0x11, 0x8e, 0x32, 0xad, 0x57, 0xc8, + 0x74, 0xeb, 0x9d, 0x02, 0xbe, 0x21, 0xdb, 0x44, 0xf8, 0x67, + 0x1e, 0x81, 0x3d, 0xa2, 0x58, 0xc7, 0x7b, 0xe4, 0x92, 0x0d, + 0xb1, 0x2e, 0xd4, 0x4b, 0xf7, 0x68, 0x1b, 0x84, 0x38, 0xa7, + 0x5d, 0xc2, 0x7e, 0xe1, 0x97, 0x08, 0xb4, 0x2b, 0xd1, 0x4e, + 0xf2, 0x6d, 0x28, 0xb7, 0x0b, 0x94, 0x6e, 0xf1, 0x4d, 0xd2, + 0xa4, 0x3b, 0x87, 0x18, 0xe2, 0x7d, 0xc1, 0x5e, 0x2d, 0xb2, + 0x0e, 0x91, 0x6b, 0xf4, 0x48, 0xd7, 0xa1, 0x3e, 0x82, 0x1d, + 0xe7, 0x78, 0xc4, 0x5b, 0x22, 0xbd, 0x01, 0x9e, 0x64, 0xfb, + 0x47, 0xd8, 0xae, 0x31, 0x8d, 0x12, 0xe8, 0x77, 0xcb, 0x54, + 0x27, 0xb8, 0x04, 0x9b, 0x61, 0xfe, 0x42, 0xdd, 0xab, 0x34, + 0x88, 0x17, 0xed, 0x72, 0xce, 0x51, 0x3c, 0xa3, 0x1f, 0x80, + 0x7a, 0xe5, 0x59, 0xc6, 0xb0, 0x2f, 0x93, 0x0c, 0xf6, 0x69, + 0xd5, 0x4a, 0x39, 0xa6, 0x1a, 0x85, 0x7f, 0xe0, 0x5c, 0xc3, + 0xb5, 0x2a, 0x96, 0x09, 0xf3, 0x6c, 0xd0, 0x4f, 0x36, 0xa9, + 0x15, 0x8a, 0x70, 0xef, 0x53, 0xcc, 0xba, 0x25, 0x99, 0x06, + 0xfc, 0x63, 0xdf, 0x40, 0x33, 0xac, 0x10, 0x8f, 0x75, 0xea, + 0x56, 0xc9, 0xbf, 0x20, 0x9c, 0x03, 0xf9, 0x66, 0xda, 0x45, + 0x00, 0xa0, 0x5d, 0xfd, 0xba, 0x1a, 0xe7, 0x47, 0x69, 0xc9, + 0x34, 0x94, 0xd3, 0x73, 0x8e, 0x2e, 0xd2, 0x72, 0x8f, 0x2f, + 0x68, 0xc8, 0x35, 0x95, 0xbb, 0x1b, 0xe6, 0x46, 0x01, 0xa1, + 0x5c, 0xfc, 0xb9, 0x19, 0xe4, 0x44, 0x03, 0xa3, 0x5e, 0xfe, + 0xd0, 0x70, 0x8d, 0x2d, 0x6a, 0xca, 0x37, 0x97, 0x6b, 0xcb, + 0x36, 0x96, 0xd1, 0x71, 0x8c, 0x2c, 0x02, 0xa2, 0x5f, 0xff, + 0xb8, 0x18, 0xe5, 0x45, 0x6f, 0xcf, 0x32, 0x92, 0xd5, 0x75, + 0x88, 0x28, 0x06, 0xa6, 0x5b, 0xfb, 0xbc, 0x1c, 0xe1, 0x41, + 0xbd, 0x1d, 0xe0, 0x40, 0x07, 0xa7, 0x5a, 0xfa, 0xd4, 0x74, + 0x89, 0x29, 0x6e, 0xce, 0x33, 0x93, 0xd6, 0x76, 0x8b, 0x2b, + 0x6c, 0xcc, 0x31, 0x91, 0xbf, 0x1f, 0xe2, 0x42, 0x05, 0xa5, + 0x58, 0xf8, 0x04, 0xa4, 0x59, 0xf9, 0xbe, 0x1e, 0xe3, 0x43, + 0x6d, 0xcd, 0x30, 0x90, 0xd7, 0x77, 0x8a, 0x2a, 0xde, 0x7e, + 0x83, 0x23, 0x64, 0xc4, 0x39, 0x99, 0xb7, 0x17, 0xea, 0x4a, + 0x0d, 0xad, 0x50, 0xf0, 0x0c, 0xac, 0x51, 0xf1, 0xb6, 0x16, + 0xeb, 0x4b, 0x65, 0xc5, 0x38, 0x98, 0xdf, 0x7f, 0x82, 0x22, + 0x67, 0xc7, 0x3a, 0x9a, 0xdd, 0x7d, 0x80, 0x20, 0x0e, 0xae, + 0x53, 0xf3, 0xb4, 0x14, 0xe9, 0x49, 0xb5, 0x15, 0xe8, 0x48, + 0x0f, 0xaf, 0x52, 0xf2, 0xdc, 0x7c, 0x81, 0x21, 0x66, 0xc6, + 0x3b, 0x9b, 0xb1, 0x11, 0xec, 0x4c, 0x0b, 0xab, 0x56, 0xf6, + 0xd8, 0x78, 0x85, 0x25, 0x62, 0xc2, 0x3f, 0x9f, 0x63, 0xc3, + 0x3e, 0x9e, 0xd9, 0x79, 0x84, 0x24, 0x0a, 0xaa, 0x57, 0xf7, + 0xb0, 0x10, 0xed, 0x4d, 0x08, 0xa8, 0x55, 0xf5, 0xb2, 0x12, + 0xef, 0x4f, 0x61, 0xc1, 0x3c, 0x9c, 0xdb, 0x7b, 0x86, 0x26, + 0xda, 0x7a, 0x87, 0x27, 0x60, 0xc0, 0x3d, 0x9d, 0xb3, 0x13, + 0xee, 0x4e, 0x09, 0xa9, 0x54, 0xf4, 0x00, 0xa1, 0x5f, 0xfe, + 0xbe, 0x1f, 0xe1, 0x40, 0x61, 0xc0, 0x3e, 0x9f, 0xdf, 0x7e, + 0x80, 0x21, 0xc2, 0x63, 0x9d, 0x3c, 0x7c, 0xdd, 0x23, 0x82, + 0xa3, 0x02, 0xfc, 0x5d, 0x1d, 0xbc, 0x42, 0xe3, 0x99, 0x38, + 0xc6, 0x67, 0x27, 0x86, 0x78, 0xd9, 0xf8, 0x59, 0xa7, 0x06, + 0x46, 0xe7, 0x19, 0xb8, 0x5b, 0xfa, 0x04, 0xa5, 0xe5, 0x44, + 0xba, 0x1b, 0x3a, 0x9b, 0x65, 0xc4, 0x84, 0x25, 0xdb, 0x7a, + 0x2f, 0x8e, 0x70, 0xd1, 0x91, 0x30, 0xce, 0x6f, 0x4e, 0xef, + 0x11, 0xb0, 0xf0, 0x51, 0xaf, 0x0e, 0xed, 0x4c, 0xb2, 0x13, + 0x53, 0xf2, 0x0c, 0xad, 0x8c, 0x2d, 0xd3, 0x72, 0x32, 0x93, + 0x6d, 0xcc, 0xb6, 0x17, 0xe9, 0x48, 0x08, 0xa9, 0x57, 0xf6, + 0xd7, 0x76, 0x88, 0x29, 0x69, 0xc8, 0x36, 0x97, 0x74, 0xd5, + 0x2b, 0x8a, 0xca, 0x6b, 0x95, 0x34, 0x15, 0xb4, 0x4a, 0xeb, + 0xab, 0x0a, 0xf4, 0x55, 0x5e, 0xff, 0x01, 0xa0, 0xe0, 0x41, + 0xbf, 0x1e, 0x3f, 0x9e, 0x60, 0xc1, 0x81, 0x20, 0xde, 0x7f, + 0x9c, 0x3d, 0xc3, 0x62, 0x22, 0x83, 0x7d, 0xdc, 0xfd, 0x5c, + 0xa2, 0x03, 0x43, 0xe2, 0x1c, 0xbd, 0xc7, 0x66, 0x98, 0x39, + 0x79, 0xd8, 0x26, 0x87, 0xa6, 0x07, 0xf9, 0x58, 0x18, 0xb9, + 0x47, 0xe6, 0x05, 0xa4, 0x5a, 0xfb, 0xbb, 0x1a, 0xe4, 0x45, + 0x64, 0xc5, 0x3b, 0x9a, 0xda, 0x7b, 0x85, 0x24, 0x71, 0xd0, + 0x2e, 0x8f, 0xcf, 0x6e, 0x90, 0x31, 0x10, 0xb1, 0x4f, 0xee, + 0xae, 0x0f, 0xf1, 0x50, 0xb3, 0x12, 0xec, 0x4d, 0x0d, 0xac, + 0x52, 0xf3, 0xd2, 0x73, 0x8d, 0x2c, 0x6c, 0xcd, 0x33, 0x92, + 0xe8, 0x49, 0xb7, 0x16, 0x56, 0xf7, 0x09, 0xa8, 0x89, 0x28, + 0xd6, 0x77, 0x37, 0x96, 0x68, 0xc9, 0x2a, 0x8b, 0x75, 0xd4, + 0x94, 0x35, 0xcb, 0x6a, 0x4b, 0xea, 0x14, 0xb5, 0xf5, 0x54, + 0xaa, 0x0b, 0x00, 0xa2, 0x59, 0xfb, 0xb2, 0x10, 0xeb, 0x49, + 0x79, 0xdb, 0x20, 0x82, 0xcb, 0x69, 0x92, 0x30, 0xf2, 0x50, + 0xab, 0x09, 0x40, 0xe2, 0x19, 0xbb, 0x8b, 0x29, 0xd2, 0x70, + 0x39, 0x9b, 0x60, 0xc2, 0xf9, 0x5b, 0xa0, 0x02, 0x4b, 0xe9, + 0x12, 0xb0, 0x80, 0x22, 0xd9, 0x7b, 0x32, 0x90, 0x6b, 0xc9, + 0x0b, 0xa9, 0x52, 0xf0, 0xb9, 0x1b, 0xe0, 0x42, 0x72, 0xd0, + 0x2b, 0x89, 0xc0, 0x62, 0x99, 0x3b, 0xef, 0x4d, 0xb6, 0x14, + 0x5d, 0xff, 0x04, 0xa6, 0x96, 0x34, 0xcf, 0x6d, 0x24, 0x86, + 0x7d, 0xdf, 0x1d, 0xbf, 0x44, 0xe6, 0xaf, 0x0d, 0xf6, 0x54, + 0x64, 0xc6, 0x3d, 0x9f, 0xd6, 0x74, 0x8f, 0x2d, 0x16, 0xb4, + 0x4f, 0xed, 0xa4, 0x06, 0xfd, 0x5f, 0x6f, 0xcd, 0x36, 0x94, + 0xdd, 0x7f, 0x84, 0x26, 0xe4, 0x46, 0xbd, 0x1f, 0x56, 0xf4, + 0x0f, 0xad, 0x9d, 0x3f, 0xc4, 0x66, 0x2f, 0x8d, 0x76, 0xd4, + 0xc3, 0x61, 0x9a, 0x38, 0x71, 0xd3, 0x28, 0x8a, 0xba, 0x18, + 0xe3, 0x41, 0x08, 0xaa, 0x51, 0xf3, 0x31, 0x93, 0x68, 0xca, + 0x83, 0x21, 0xda, 0x78, 0x48, 0xea, 0x11, 0xb3, 0xfa, 0x58, + 0xa3, 0x01, 0x3a, 0x98, 0x63, 0xc1, 0x88, 0x2a, 0xd1, 0x73, + 0x43, 0xe1, 0x1a, 0xb8, 0xf1, 0x53, 0xa8, 0x0a, 0xc8, 0x6a, + 0x91, 0x33, 0x7a, 0xd8, 0x23, 0x81, 0xb1, 0x13, 0xe8, 0x4a, + 0x03, 0xa1, 0x5a, 0xf8, 0x2c, 0x8e, 0x75, 0xd7, 0x9e, 0x3c, + 0xc7, 0x65, 0x55, 0xf7, 0x0c, 0xae, 0xe7, 0x45, 0xbe, 0x1c, + 0xde, 0x7c, 0x87, 0x25, 0x6c, 0xce, 0x35, 0x97, 0xa7, 0x05, + 0xfe, 0x5c, 0x15, 0xb7, 0x4c, 0xee, 0xd5, 0x77, 0x8c, 0x2e, + 0x67, 0xc5, 0x3e, 0x9c, 0xac, 0x0e, 0xf5, 0x57, 0x1e, 0xbc, + 0x47, 0xe5, 0x27, 0x85, 0x7e, 0xdc, 0x95, 0x37, 0xcc, 0x6e, + 0x5e, 0xfc, 0x07, 0xa5, 0xec, 0x4e, 0xb5, 0x17, 0x00, 0xa3, + 0x5b, 0xf8, 0xb6, 0x15, 0xed, 0x4e, 0x71, 0xd2, 0x2a, 0x89, + 0xc7, 0x64, 0x9c, 0x3f, 0xe2, 0x41, 0xb9, 0x1a, 0x54, 0xf7, + 0x0f, 0xac, 0x93, 0x30, 0xc8, 0x6b, 0x25, 0x86, 0x7e, 0xdd, + 0xd9, 0x7a, 0x82, 0x21, 0x6f, 0xcc, 0x34, 0x97, 0xa8, 0x0b, + 0xf3, 0x50, 0x1e, 0xbd, 0x45, 0xe6, 0x3b, 0x98, 0x60, 0xc3, + 0x8d, 0x2e, 0xd6, 0x75, 0x4a, 0xe9, 0x11, 0xb2, 0xfc, 0x5f, + 0xa7, 0x04, 0xaf, 0x0c, 0xf4, 0x57, 0x19, 0xba, 0x42, 0xe1, + 0xde, 0x7d, 0x85, 0x26, 0x68, 0xcb, 0x33, 0x90, 0x4d, 0xee, + 0x16, 0xb5, 0xfb, 0x58, 0xa0, 0x03, 0x3c, 0x9f, 0x67, 0xc4, + 0x8a, 0x29, 0xd1, 0x72, 0x76, 0xd5, 0x2d, 0x8e, 0xc0, 0x63, + 0x9b, 0x38, 0x07, 0xa4, 0x5c, 0xff, 0xb1, 0x12, 0xea, 0x49, + 0x94, 0x37, 0xcf, 0x6c, 0x22, 0x81, 0x79, 0xda, 0xe5, 0x46, + 0xbe, 0x1d, 0x53, 0xf0, 0x08, 0xab, 0x43, 0xe0, 0x18, 0xbb, + 0xf5, 0x56, 0xae, 0x0d, 0x32, 0x91, 0x69, 0xca, 0x84, 0x27, + 0xdf, 0x7c, 0xa1, 0x02, 0xfa, 0x59, 0x17, 0xb4, 0x4c, 0xef, + 0xd0, 0x73, 0x8b, 0x28, 0x66, 0xc5, 0x3d, 0x9e, 0x9a, 0x39, + 0xc1, 0x62, 0x2c, 0x8f, 0x77, 0xd4, 0xeb, 0x48, 0xb0, 0x13, + 0x5d, 0xfe, 0x06, 0xa5, 0x78, 0xdb, 0x23, 0x80, 0xce, 0x6d, + 0x95, 0x36, 0x09, 0xaa, 0x52, 0xf1, 0xbf, 0x1c, 0xe4, 0x47, + 0xec, 0x4f, 0xb7, 0x14, 0x5a, 0xf9, 0x01, 0xa2, 0x9d, 0x3e, + 0xc6, 0x65, 0x2b, 0x88, 0x70, 0xd3, 0x0e, 0xad, 0x55, 0xf6, + 0xb8, 0x1b, 0xe3, 0x40, 0x7f, 0xdc, 0x24, 0x87, 0xc9, 0x6a, + 0x92, 0x31, 0x35, 0x96, 0x6e, 0xcd, 0x83, 0x20, 0xd8, 0x7b, + 0x44, 0xe7, 0x1f, 0xbc, 0xf2, 0x51, 0xa9, 0x0a, 0xd7, 0x74, + 0x8c, 0x2f, 0x61, 0xc2, 0x3a, 0x99, 0xa6, 0x05, 0xfd, 0x5e, + 0x10, 0xb3, 0x4b, 0xe8, 0x00, 0xa4, 0x55, 0xf1, 0xaa, 0x0e, + 0xff, 0x5b, 0x49, 0xed, 0x1c, 0xb8, 0xe3, 0x47, 0xb6, 0x12, + 0x92, 0x36, 0xc7, 0x63, 0x38, 0x9c, 0x6d, 0xc9, 0xdb, 0x7f, + 0x8e, 0x2a, 0x71, 0xd5, 0x24, 0x80, 0x39, 0x9d, 0x6c, 0xc8, + 0x93, 0x37, 0xc6, 0x62, 0x70, 0xd4, 0x25, 0x81, 0xda, 0x7e, + 0x8f, 0x2b, 0xab, 0x0f, 0xfe, 0x5a, 0x01, 0xa5, 0x54, 0xf0, + 0xe2, 0x46, 0xb7, 0x13, 0x48, 0xec, 0x1d, 0xb9, 0x72, 0xd6, + 0x27, 0x83, 0xd8, 0x7c, 0x8d, 0x29, 0x3b, 0x9f, 0x6e, 0xca, + 0x91, 0x35, 0xc4, 0x60, 0xe0, 0x44, 0xb5, 0x11, 0x4a, 0xee, + 0x1f, 0xbb, 0xa9, 0x0d, 0xfc, 0x58, 0x03, 0xa7, 0x56, 0xf2, + 0x4b, 0xef, 0x1e, 0xba, 0xe1, 0x45, 0xb4, 0x10, 0x02, 0xa6, + 0x57, 0xf3, 0xa8, 0x0c, 0xfd, 0x59, 0xd9, 0x7d, 0x8c, 0x28, + 0x73, 0xd7, 0x26, 0x82, 0x90, 0x34, 0xc5, 0x61, 0x3a, 0x9e, + 0x6f, 0xcb, 0xe4, 0x40, 0xb1, 0x15, 0x4e, 0xea, 0x1b, 0xbf, + 0xad, 0x09, 0xf8, 0x5c, 0x07, 0xa3, 0x52, 0xf6, 0x76, 0xd2, + 0x23, 0x87, 0xdc, 0x78, 0x89, 0x2d, 0x3f, 0x9b, 0x6a, 0xce, + 0x95, 0x31, 0xc0, 0x64, 0xdd, 0x79, 0x88, 0x2c, 0x77, 0xd3, + 0x22, 0x86, 0x94, 0x30, 0xc1, 0x65, 0x3e, 0x9a, 0x6b, 0xcf, + 0x4f, 0xeb, 0x1a, 0xbe, 0xe5, 0x41, 0xb0, 0x14, 0x06, 0xa2, + 0x53, 0xf7, 0xac, 0x08, 0xf9, 0x5d, 0x96, 0x32, 0xc3, 0x67, + 0x3c, 0x98, 0x69, 0xcd, 0xdf, 0x7b, 0x8a, 0x2e, 0x75, 0xd1, + 0x20, 0x84, 0x04, 0xa0, 0x51, 0xf5, 0xae, 0x0a, 0xfb, 0x5f, + 0x4d, 0xe9, 0x18, 0xbc, 0xe7, 0x43, 0xb2, 0x16, 0xaf, 0x0b, + 0xfa, 0x5e, 0x05, 0xa1, 0x50, 0xf4, 0xe6, 0x42, 0xb3, 0x17, + 0x4c, 0xe8, 0x19, 0xbd, 0x3d, 0x99, 0x68, 0xcc, 0x97, 0x33, + 0xc2, 0x66, 0x74, 0xd0, 0x21, 0x85, 0xde, 0x7a, 0x8b, 0x2f, + 0x00, 0xa5, 0x57, 0xf2, 0xae, 0x0b, 0xf9, 0x5c, 0x41, 0xe4, + 0x16, 0xb3, 0xef, 0x4a, 0xb8, 0x1d, 0x82, 0x27, 0xd5, 0x70, + 0x2c, 0x89, 0x7b, 0xde, 0xc3, 0x66, 0x94, 0x31, 0x6d, 0xc8, + 0x3a, 0x9f, 0x19, 0xbc, 0x4e, 0xeb, 0xb7, 0x12, 0xe0, 0x45, + 0x58, 0xfd, 0x0f, 0xaa, 0xf6, 0x53, 0xa1, 0x04, 0x9b, 0x3e, + 0xcc, 0x69, 0x35, 0x90, 0x62, 0xc7, 0xda, 0x7f, 0x8d, 0x28, + 0x74, 0xd1, 0x23, 0x86, 0x32, 0x97, 0x65, 0xc0, 0x9c, 0x39, + 0xcb, 0x6e, 0x73, 0xd6, 0x24, 0x81, 0xdd, 0x78, 0x8a, 0x2f, + 0xb0, 0x15, 0xe7, 0x42, 0x1e, 0xbb, 0x49, 0xec, 0xf1, 0x54, + 0xa6, 0x03, 0x5f, 0xfa, 0x08, 0xad, 0x2b, 0x8e, 0x7c, 0xd9, + 0x85, 0x20, 0xd2, 0x77, 0x6a, 0xcf, 0x3d, 0x98, 0xc4, 0x61, + 0x93, 0x36, 0xa9, 0x0c, 0xfe, 0x5b, 0x07, 0xa2, 0x50, 0xf5, + 0xe8, 0x4d, 0xbf, 0x1a, 0x46, 0xe3, 0x11, 0xb4, 0x64, 0xc1, + 0x33, 0x96, 0xca, 0x6f, 0x9d, 0x38, 0x25, 0x80, 0x72, 0xd7, + 0x8b, 0x2e, 0xdc, 0x79, 0xe6, 0x43, 0xb1, 0x14, 0x48, 0xed, + 0x1f, 0xba, 0xa7, 0x02, 0xf0, 0x55, 0x09, 0xac, 0x5e, 0xfb, + 0x7d, 0xd8, 0x2a, 0x8f, 0xd3, 0x76, 0x84, 0x21, 0x3c, 0x99, + 0x6b, 0xce, 0x92, 0x37, 0xc5, 0x60, 0xff, 0x5a, 0xa8, 0x0d, + 0x51, 0xf4, 0x06, 0xa3, 0xbe, 0x1b, 0xe9, 0x4c, 0x10, 0xb5, + 0x47, 0xe2, 0x56, 0xf3, 0x01, 0xa4, 0xf8, 0x5d, 0xaf, 0x0a, + 0x17, 0xb2, 0x40, 0xe5, 0xb9, 0x1c, 0xee, 0x4b, 0xd4, 0x71, + 0x83, 0x26, 0x7a, 0xdf, 0x2d, 0x88, 0x95, 0x30, 0xc2, 0x67, + 0x3b, 0x9e, 0x6c, 0xc9, 0x4f, 0xea, 0x18, 0xbd, 0xe1, 0x44, + 0xb6, 0x13, 0x0e, 0xab, 0x59, 0xfc, 0xa0, 0x05, 0xf7, 0x52, + 0xcd, 0x68, 0x9a, 0x3f, 0x63, 0xc6, 0x34, 0x91, 0x8c, 0x29, + 0xdb, 0x7e, 0x22, 0x87, 0x75, 0xd0, 0x00, 0xa6, 0x51, 0xf7, + 0xa2, 0x04, 0xf3, 0x55, 0x59, 0xff, 0x08, 0xae, 0xfb, 0x5d, + 0xaa, 0x0c, 0xb2, 0x14, 0xe3, 0x45, 0x10, 0xb6, 0x41, 0xe7, + 0xeb, 0x4d, 0xba, 0x1c, 0x49, 0xef, 0x18, 0xbe, 0x79, 0xdf, + 0x28, 0x8e, 0xdb, 0x7d, 0x8a, 0x2c, 0x20, 0x86, 0x71, 0xd7, + 0x82, 0x24, 0xd3, 0x75, 0xcb, 0x6d, 0x9a, 0x3c, 0x69, 0xcf, + 0x38, 0x9e, 0x92, 0x34, 0xc3, 0x65, 0x30, 0x96, 0x61, 0xc7, + 0xf2, 0x54, 0xa3, 0x05, 0x50, 0xf6, 0x01, 0xa7, 0xab, 0x0d, + 0xfa, 0x5c, 0x09, 0xaf, 0x58, 0xfe, 0x40, 0xe6, 0x11, 0xb7, + 0xe2, 0x44, 0xb3, 0x15, 0x19, 0xbf, 0x48, 0xee, 0xbb, 0x1d, + 0xea, 0x4c, 0x8b, 0x2d, 0xda, 0x7c, 0x29, 0x8f, 0x78, 0xde, + 0xd2, 0x74, 0x83, 0x25, 0x70, 0xd6, 0x21, 0x87, 0x39, 0x9f, + 0x68, 0xce, 0x9b, 0x3d, 0xca, 0x6c, 0x60, 0xc6, 0x31, 0x97, + 0xc2, 0x64, 0x93, 0x35, 0xf9, 0x5f, 0xa8, 0x0e, 0x5b, 0xfd, + 0x0a, 0xac, 0xa0, 0x06, 0xf1, 0x57, 0x02, 0xa4, 0x53, 0xf5, + 0x4b, 0xed, 0x1a, 0xbc, 0xe9, 0x4f, 0xb8, 0x1e, 0x12, 0xb4, + 0x43, 0xe5, 0xb0, 0x16, 0xe1, 0x47, 0x80, 0x26, 0xd1, 0x77, + 0x22, 0x84, 0x73, 0xd5, 0xd9, 0x7f, 0x88, 0x2e, 0x7b, 0xdd, + 0x2a, 0x8c, 0x32, 0x94, 0x63, 0xc5, 0x90, 0x36, 0xc1, 0x67, + 0x6b, 0xcd, 0x3a, 0x9c, 0xc9, 0x6f, 0x98, 0x3e, 0x0b, 0xad, + 0x5a, 0xfc, 0xa9, 0x0f, 0xf8, 0x5e, 0x52, 0xf4, 0x03, 0xa5, + 0xf0, 0x56, 0xa1, 0x07, 0xb9, 0x1f, 0xe8, 0x4e, 0x1b, 0xbd, + 0x4a, 0xec, 0xe0, 0x46, 0xb1, 0x17, 0x42, 0xe4, 0x13, 0xb5, + 0x72, 0xd4, 0x23, 0x85, 0xd0, 0x76, 0x81, 0x27, 0x2b, 0x8d, + 0x7a, 0xdc, 0x89, 0x2f, 0xd8, 0x7e, 0xc0, 0x66, 0x91, 0x37, + 0x62, 0xc4, 0x33, 0x95, 0x99, 0x3f, 0xc8, 0x6e, 0x3b, 0x9d, + 0x6a, 0xcc, 0x00, 0xa7, 0x53, 0xf4, 0xa6, 0x01, 0xf5, 0x52, + 0x51, 0xf6, 0x02, 0xa5, 0xf7, 0x50, 0xa4, 0x03, 0xa2, 0x05, + 0xf1, 0x56, 0x04, 0xa3, 0x57, 0xf0, 0xf3, 0x54, 0xa0, 0x07, + 0x55, 0xf2, 0x06, 0xa1, 0x59, 0xfe, 0x0a, 0xad, 0xff, 0x58, + 0xac, 0x0b, 0x08, 0xaf, 0x5b, 0xfc, 0xae, 0x09, 0xfd, 0x5a, + 0xfb, 0x5c, 0xa8, 0x0f, 0x5d, 0xfa, 0x0e, 0xa9, 0xaa, 0x0d, + 0xf9, 0x5e, 0x0c, 0xab, 0x5f, 0xf8, 0xb2, 0x15, 0xe1, 0x46, + 0x14, 0xb3, 0x47, 0xe0, 0xe3, 0x44, 0xb0, 0x17, 0x45, 0xe2, + 0x16, 0xb1, 0x10, 0xb7, 0x43, 0xe4, 0xb6, 0x11, 0xe5, 0x42, + 0x41, 0xe6, 0x12, 0xb5, 0xe7, 0x40, 0xb4, 0x13, 0xeb, 0x4c, + 0xb8, 0x1f, 0x4d, 0xea, 0x1e, 0xb9, 0xba, 0x1d, 0xe9, 0x4e, + 0x1c, 0xbb, 0x4f, 0xe8, 0x49, 0xee, 0x1a, 0xbd, 0xef, 0x48, + 0xbc, 0x1b, 0x18, 0xbf, 0x4b, 0xec, 0xbe, 0x19, 0xed, 0x4a, + 0x79, 0xde, 0x2a, 0x8d, 0xdf, 0x78, 0x8c, 0x2b, 0x28, 0x8f, + 0x7b, 0xdc, 0x8e, 0x29, 0xdd, 0x7a, 0xdb, 0x7c, 0x88, 0x2f, + 0x7d, 0xda, 0x2e, 0x89, 0x8a, 0x2d, 0xd9, 0x7e, 0x2c, 0x8b, + 0x7f, 0xd8, 0x20, 0x87, 0x73, 0xd4, 0x86, 0x21, 0xd5, 0x72, + 0x71, 0xd6, 0x22, 0x85, 0xd7, 0x70, 0x84, 0x23, 0x82, 0x25, + 0xd1, 0x76, 0x24, 0x83, 0x77, 0xd0, 0xd3, 0x74, 0x80, 0x27, + 0x75, 0xd2, 0x26, 0x81, 0xcb, 0x6c, 0x98, 0x3f, 0x6d, 0xca, + 0x3e, 0x99, 0x9a, 0x3d, 0xc9, 0x6e, 0x3c, 0x9b, 0x6f, 0xc8, + 0x69, 0xce, 0x3a, 0x9d, 0xcf, 0x68, 0x9c, 0x3b, 0x38, 0x9f, + 0x6b, 0xcc, 0x9e, 0x39, 0xcd, 0x6a, 0x92, 0x35, 0xc1, 0x66, + 0x34, 0x93, 0x67, 0xc0, 0xc3, 0x64, 0x90, 0x37, 0x65, 0xc2, + 0x36, 0x91, 0x30, 0x97, 0x63, 0xc4, 0x96, 0x31, 0xc5, 0x62, + 0x61, 0xc6, 0x32, 0x95, 0xc7, 0x60, 0x94, 0x33, 0x00, 0xa8, + 0x4d, 0xe5, 0x9a, 0x32, 0xd7, 0x7f, 0x29, 0x81, 0x64, 0xcc, + 0xb3, 0x1b, 0xfe, 0x56, 0x52, 0xfa, 0x1f, 0xb7, 0xc8, 0x60, + 0x85, 0x2d, 0x7b, 0xd3, 0x36, 0x9e, 0xe1, 0x49, 0xac, 0x04, + 0xa4, 0x0c, 0xe9, 0x41, 0x3e, 0x96, 0x73, 0xdb, 0x8d, 0x25, + 0xc0, 0x68, 0x17, 0xbf, 0x5a, 0xf2, 0xf6, 0x5e, 0xbb, 0x13, + 0x6c, 0xc4, 0x21, 0x89, 0xdf, 0x77, 0x92, 0x3a, 0x45, 0xed, + 0x08, 0xa0, 0x55, 0xfd, 0x18, 0xb0, 0xcf, 0x67, 0x82, 0x2a, + 0x7c, 0xd4, 0x31, 0x99, 0xe6, 0x4e, 0xab, 0x03, 0x07, 0xaf, + 0x4a, 0xe2, 0x9d, 0x35, 0xd0, 0x78, 0x2e, 0x86, 0x63, 0xcb, + 0xb4, 0x1c, 0xf9, 0x51, 0xf1, 0x59, 0xbc, 0x14, 0x6b, 0xc3, + 0x26, 0x8e, 0xd8, 0x70, 0x95, 0x3d, 0x42, 0xea, 0x0f, 0xa7, + 0xa3, 0x0b, 0xee, 0x46, 0x39, 0x91, 0x74, 0xdc, 0x8a, 0x22, + 0xc7, 0x6f, 0x10, 0xb8, 0x5d, 0xf5, 0xaa, 0x02, 0xe7, 0x4f, + 0x30, 0x98, 0x7d, 0xd5, 0x83, 0x2b, 0xce, 0x66, 0x19, 0xb1, + 0x54, 0xfc, 0xf8, 0x50, 0xb5, 0x1d, 0x62, 0xca, 0x2f, 0x87, + 0xd1, 0x79, 0x9c, 0x34, 0x4b, 0xe3, 0x06, 0xae, 0x0e, 0xa6, + 0x43, 0xeb, 0x94, 0x3c, 0xd9, 0x71, 0x27, 0x8f, 0x6a, 0xc2, + 0xbd, 0x15, 0xf0, 0x58, 0x5c, 0xf4, 0x11, 0xb9, 0xc6, 0x6e, + 0x8b, 0x23, 0x75, 0xdd, 0x38, 0x90, 0xef, 0x47, 0xa2, 0x0a, + 0xff, 0x57, 0xb2, 0x1a, 0x65, 0xcd, 0x28, 0x80, 0xd6, 0x7e, + 0x9b, 0x33, 0x4c, 0xe4, 0x01, 0xa9, 0xad, 0x05, 0xe0, 0x48, + 0x37, 0x9f, 0x7a, 0xd2, 0x84, 0x2c, 0xc9, 0x61, 0x1e, 0xb6, + 0x53, 0xfb, 0x5b, 0xf3, 0x16, 0xbe, 0xc1, 0x69, 0x8c, 0x24, + 0x72, 0xda, 0x3f, 0x97, 0xe8, 0x40, 0xa5, 0x0d, 0x09, 0xa1, + 0x44, 0xec, 0x93, 0x3b, 0xde, 0x76, 0x20, 0x88, 0x6d, 0xc5, + 0xba, 0x12, 0xf7, 0x5f, 0x00, 0xa9, 0x4f, 0xe6, 0x9e, 0x37, + 0xd1, 0x78, 0x21, 0x88, 0x6e, 0xc7, 0xbf, 0x16, 0xf0, 0x59, + 0x42, 0xeb, 0x0d, 0xa4, 0xdc, 0x75, 0x93, 0x3a, 0x63, 0xca, + 0x2c, 0x85, 0xfd, 0x54, 0xb2, 0x1b, 0x84, 0x2d, 0xcb, 0x62, + 0x1a, 0xb3, 0x55, 0xfc, 0xa5, 0x0c, 0xea, 0x43, 0x3b, 0x92, + 0x74, 0xdd, 0xc6, 0x6f, 0x89, 0x20, 0x58, 0xf1, 0x17, 0xbe, + 0xe7, 0x4e, 0xa8, 0x01, 0x79, 0xd0, 0x36, 0x9f, 0x15, 0xbc, + 0x5a, 0xf3, 0x8b, 0x22, 0xc4, 0x6d, 0x34, 0x9d, 0x7b, 0xd2, + 0xaa, 0x03, 0xe5, 0x4c, 0x57, 0xfe, 0x18, 0xb1, 0xc9, 0x60, + 0x86, 0x2f, 0x76, 0xdf, 0x39, 0x90, 0xe8, 0x41, 0xa7, 0x0e, + 0x91, 0x38, 0xde, 0x77, 0x0f, 0xa6, 0x40, 0xe9, 0xb0, 0x19, + 0xff, 0x56, 0x2e, 0x87, 0x61, 0xc8, 0xd3, 0x7a, 0x9c, 0x35, + 0x4d, 0xe4, 0x02, 0xab, 0xf2, 0x5b, 0xbd, 0x14, 0x6c, 0xc5, + 0x23, 0x8a, 0x2a, 0x83, 0x65, 0xcc, 0xb4, 0x1d, 0xfb, 0x52, + 0x0b, 0xa2, 0x44, 0xed, 0x95, 0x3c, 0xda, 0x73, 0x68, 0xc1, + 0x27, 0x8e, 0xf6, 0x5f, 0xb9, 0x10, 0x49, 0xe0, 0x06, 0xaf, + 0xd7, 0x7e, 0x98, 0x31, 0xae, 0x07, 0xe1, 0x48, 0x30, 0x99, + 0x7f, 0xd6, 0x8f, 0x26, 0xc0, 0x69, 0x11, 0xb8, 0x5e, 0xf7, + 0xec, 0x45, 0xa3, 0x0a, 0x72, 0xdb, 0x3d, 0x94, 0xcd, 0x64, + 0x82, 0x2b, 0x53, 0xfa, 0x1c, 0xb5, 0x3f, 0x96, 0x70, 0xd9, + 0xa1, 0x08, 0xee, 0x47, 0x1e, 0xb7, 0x51, 0xf8, 0x80, 0x29, + 0xcf, 0x66, 0x7d, 0xd4, 0x32, 0x9b, 0xe3, 0x4a, 0xac, 0x05, + 0x5c, 0xf5, 0x13, 0xba, 0xc2, 0x6b, 0x8d, 0x24, 0xbb, 0x12, + 0xf4, 0x5d, 0x25, 0x8c, 0x6a, 0xc3, 0x9a, 0x33, 0xd5, 0x7c, + 0x04, 0xad, 0x4b, 0xe2, 0xf9, 0x50, 0xb6, 0x1f, 0x67, 0xce, + 0x28, 0x81, 0xd8, 0x71, 0x97, 0x3e, 0x46, 0xef, 0x09, 0xa0, + 0x00, 0xaa, 0x49, 0xe3, 0x92, 0x38, 0xdb, 0x71, 0x39, 0x93, + 0x70, 0xda, 0xab, 0x01, 0xe2, 0x48, 0x72, 0xd8, 0x3b, 0x91, + 0xe0, 0x4a, 0xa9, 0x03, 0x4b, 0xe1, 0x02, 0xa8, 0xd9, 0x73, + 0x90, 0x3a, 0xe4, 0x4e, 0xad, 0x07, 0x76, 0xdc, 0x3f, 0x95, + 0xdd, 0x77, 0x94, 0x3e, 0x4f, 0xe5, 0x06, 0xac, 0x96, 0x3c, + 0xdf, 0x75, 0x04, 0xae, 0x4d, 0xe7, 0xaf, 0x05, 0xe6, 0x4c, + 0x3d, 0x97, 0x74, 0xde, 0xd5, 0x7f, 0x9c, 0x36, 0x47, 0xed, + 0x0e, 0xa4, 0xec, 0x46, 0xa5, 0x0f, 0x7e, 0xd4, 0x37, 0x9d, + 0xa7, 0x0d, 0xee, 0x44, 0x35, 0x9f, 0x7c, 0xd6, 0x9e, 0x34, + 0xd7, 0x7d, 0x0c, 0xa6, 0x45, 0xef, 0x31, 0x9b, 0x78, 0xd2, + 0xa3, 0x09, 0xea, 0x40, 0x08, 0xa2, 0x41, 0xeb, 0x9a, 0x30, + 0xd3, 0x79, 0x43, 0xe9, 0x0a, 0xa0, 0xd1, 0x7b, 0x98, 0x32, + 0x7a, 0xd0, 0x33, 0x99, 0xe8, 0x42, 0xa1, 0x0b, 0xb7, 0x1d, + 0xfe, 0x54, 0x25, 0x8f, 0x6c, 0xc6, 0x8e, 0x24, 0xc7, 0x6d, + 0x1c, 0xb6, 0x55, 0xff, 0xc5, 0x6f, 0x8c, 0x26, 0x57, 0xfd, + 0x1e, 0xb4, 0xfc, 0x56, 0xb5, 0x1f, 0x6e, 0xc4, 0x27, 0x8d, + 0x53, 0xf9, 0x1a, 0xb0, 0xc1, 0x6b, 0x88, 0x22, 0x6a, 0xc0, + 0x23, 0x89, 0xf8, 0x52, 0xb1, 0x1b, 0x21, 0x8b, 0x68, 0xc2, + 0xb3, 0x19, 0xfa, 0x50, 0x18, 0xb2, 0x51, 0xfb, 0x8a, 0x20, + 0xc3, 0x69, 0x62, 0xc8, 0x2b, 0x81, 0xf0, 0x5a, 0xb9, 0x13, + 0x5b, 0xf1, 0x12, 0xb8, 0xc9, 0x63, 0x80, 0x2a, 0x10, 0xba, + 0x59, 0xf3, 0x82, 0x28, 0xcb, 0x61, 0x29, 0x83, 0x60, 0xca, + 0xbb, 0x11, 0xf2, 0x58, 0x86, 0x2c, 0xcf, 0x65, 0x14, 0xbe, + 0x5d, 0xf7, 0xbf, 0x15, 0xf6, 0x5c, 0x2d, 0x87, 0x64, 0xce, + 0xf4, 0x5e, 0xbd, 0x17, 0x66, 0xcc, 0x2f, 0x85, 0xcd, 0x67, + 0x84, 0x2e, 0x5f, 0xf5, 0x16, 0xbc, 0x00, 0xab, 0x4b, 0xe0, + 0x96, 0x3d, 0xdd, 0x76, 0x31, 0x9a, 0x7a, 0xd1, 0xa7, 0x0c, + 0xec, 0x47, 0x62, 0xc9, 0x29, 0x82, 0xf4, 0x5f, 0xbf, 0x14, + 0x53, 0xf8, 0x18, 0xb3, 0xc5, 0x6e, 0x8e, 0x25, 0xc4, 0x6f, + 0x8f, 0x24, 0x52, 0xf9, 0x19, 0xb2, 0xf5, 0x5e, 0xbe, 0x15, + 0x63, 0xc8, 0x28, 0x83, 0xa6, 0x0d, 0xed, 0x46, 0x30, 0x9b, + 0x7b, 0xd0, 0x97, 0x3c, 0xdc, 0x77, 0x01, 0xaa, 0x4a, 0xe1, + 0x95, 0x3e, 0xde, 0x75, 0x03, 0xa8, 0x48, 0xe3, 0xa4, 0x0f, + 0xef, 0x44, 0x32, 0x99, 0x79, 0xd2, 0xf7, 0x5c, 0xbc, 0x17, + 0x61, 0xca, 0x2a, 0x81, 0xc6, 0x6d, 0x8d, 0x26, 0x50, 0xfb, + 0x1b, 0xb0, 0x51, 0xfa, 0x1a, 0xb1, 0xc7, 0x6c, 0x8c, 0x27, + 0x60, 0xcb, 0x2b, 0x80, 0xf6, 0x5d, 0xbd, 0x16, 0x33, 0x98, + 0x78, 0xd3, 0xa5, 0x0e, 0xee, 0x45, 0x02, 0xa9, 0x49, 0xe2, + 0x94, 0x3f, 0xdf, 0x74, 0x37, 0x9c, 0x7c, 0xd7, 0xa1, 0x0a, + 0xea, 0x41, 0x06, 0xad, 0x4d, 0xe6, 0x90, 0x3b, 0xdb, 0x70, + 0x55, 0xfe, 0x1e, 0xb5, 0xc3, 0x68, 0x88, 0x23, 0x64, 0xcf, + 0x2f, 0x84, 0xf2, 0x59, 0xb9, 0x12, 0xf3, 0x58, 0xb8, 0x13, + 0x65, 0xce, 0x2e, 0x85, 0xc2, 0x69, 0x89, 0x22, 0x54, 0xff, + 0x1f, 0xb4, 0x91, 0x3a, 0xda, 0x71, 0x07, 0xac, 0x4c, 0xe7, + 0xa0, 0x0b, 0xeb, 0x40, 0x36, 0x9d, 0x7d, 0xd6, 0xa2, 0x09, + 0xe9, 0x42, 0x34, 0x9f, 0x7f, 0xd4, 0x93, 0x38, 0xd8, 0x73, + 0x05, 0xae, 0x4e, 0xe5, 0xc0, 0x6b, 0x8b, 0x20, 0x56, 0xfd, + 0x1d, 0xb6, 0xf1, 0x5a, 0xba, 0x11, 0x67, 0xcc, 0x2c, 0x87, + 0x66, 0xcd, 0x2d, 0x86, 0xf0, 0x5b, 0xbb, 0x10, 0x57, 0xfc, + 0x1c, 0xb7, 0xc1, 0x6a, 0x8a, 0x21, 0x04, 0xaf, 0x4f, 0xe4, + 0x92, 0x39, 0xd9, 0x72, 0x35, 0x9e, 0x7e, 0xd5, 0xa3, 0x08, + 0xe8, 0x43, 0x00, 0xac, 0x45, 0xe9, 0x8a, 0x26, 0xcf, 0x63, + 0x09, 0xa5, 0x4c, 0xe0, 0x83, 0x2f, 0xc6, 0x6a, 0x12, 0xbe, + 0x57, 0xfb, 0x98, 0x34, 0xdd, 0x71, 0x1b, 0xb7, 0x5e, 0xf2, + 0x91, 0x3d, 0xd4, 0x78, 0x24, 0x88, 0x61, 0xcd, 0xae, 0x02, + 0xeb, 0x47, 0x2d, 0x81, 0x68, 0xc4, 0xa7, 0x0b, 0xe2, 0x4e, + 0x36, 0x9a, 0x73, 0xdf, 0xbc, 0x10, 0xf9, 0x55, 0x3f, 0x93, + 0x7a, 0xd6, 0xb5, 0x19, 0xf0, 0x5c, 0x48, 0xe4, 0x0d, 0xa1, + 0xc2, 0x6e, 0x87, 0x2b, 0x41, 0xed, 0x04, 0xa8, 0xcb, 0x67, + 0x8e, 0x22, 0x5a, 0xf6, 0x1f, 0xb3, 0xd0, 0x7c, 0x95, 0x39, + 0x53, 0xff, 0x16, 0xba, 0xd9, 0x75, 0x9c, 0x30, 0x6c, 0xc0, + 0x29, 0x85, 0xe6, 0x4a, 0xa3, 0x0f, 0x65, 0xc9, 0x20, 0x8c, + 0xef, 0x43, 0xaa, 0x06, 0x7e, 0xd2, 0x3b, 0x97, 0xf4, 0x58, + 0xb1, 0x1d, 0x77, 0xdb, 0x32, 0x9e, 0xfd, 0x51, 0xb8, 0x14, + 0x90, 0x3c, 0xd5, 0x79, 0x1a, 0xb6, 0x5f, 0xf3, 0x99, 0x35, + 0xdc, 0x70, 0x13, 0xbf, 0x56, 0xfa, 0x82, 0x2e, 0xc7, 0x6b, + 0x08, 0xa4, 0x4d, 0xe1, 0x8b, 0x27, 0xce, 0x62, 0x01, 0xad, + 0x44, 0xe8, 0xb4, 0x18, 0xf1, 0x5d, 0x3e, 0x92, 0x7b, 0xd7, + 0xbd, 0x11, 0xf8, 0x54, 0x37, 0x9b, 0x72, 0xde, 0xa6, 0x0a, + 0xe3, 0x4f, 0x2c, 0x80, 0x69, 0xc5, 0xaf, 0x03, 0xea, 0x46, + 0x25, 0x89, 0x60, 0xcc, 0xd8, 0x74, 0x9d, 0x31, 0x52, 0xfe, + 0x17, 0xbb, 0xd1, 0x7d, 0x94, 0x38, 0x5b, 0xf7, 0x1e, 0xb2, + 0xca, 0x66, 0x8f, 0x23, 0x40, 0xec, 0x05, 0xa9, 0xc3, 0x6f, + 0x86, 0x2a, 0x49, 0xe5, 0x0c, 0xa0, 0xfc, 0x50, 0xb9, 0x15, + 0x76, 0xda, 0x33, 0x9f, 0xf5, 0x59, 0xb0, 0x1c, 0x7f, 0xd3, + 0x3a, 0x96, 0xee, 0x42, 0xab, 0x07, 0x64, 0xc8, 0x21, 0x8d, + 0xe7, 0x4b, 0xa2, 0x0e, 0x6d, 0xc1, 0x28, 0x84, 0x00, 0xad, + 0x47, 0xea, 0x8e, 0x23, 0xc9, 0x64, 0x01, 0xac, 0x46, 0xeb, + 0x8f, 0x22, 0xc8, 0x65, 0x02, 0xaf, 0x45, 0xe8, 0x8c, 0x21, + 0xcb, 0x66, 0x03, 0xae, 0x44, 0xe9, 0x8d, 0x20, 0xca, 0x67, + 0x04, 0xa9, 0x43, 0xee, 0x8a, 0x27, 0xcd, 0x60, 0x05, 0xa8, + 0x42, 0xef, 0x8b, 0x26, 0xcc, 0x61, 0x06, 0xab, 0x41, 0xec, + 0x88, 0x25, 0xcf, 0x62, 0x07, 0xaa, 0x40, 0xed, 0x89, 0x24, + 0xce, 0x63, 0x08, 0xa5, 0x4f, 0xe2, 0x86, 0x2b, 0xc1, 0x6c, + 0x09, 0xa4, 0x4e, 0xe3, 0x87, 0x2a, 0xc0, 0x6d, 0x0a, 0xa7, + 0x4d, 0xe0, 0x84, 0x29, 0xc3, 0x6e, 0x0b, 0xa6, 0x4c, 0xe1, + 0x85, 0x28, 0xc2, 0x6f, 0x0c, 0xa1, 0x4b, 0xe6, 0x82, 0x2f, + 0xc5, 0x68, 0x0d, 0xa0, 0x4a, 0xe7, 0x83, 0x2e, 0xc4, 0x69, + 0x0e, 0xa3, 0x49, 0xe4, 0x80, 0x2d, 0xc7, 0x6a, 0x0f, 0xa2, + 0x48, 0xe5, 0x81, 0x2c, 0xc6, 0x6b, 0x10, 0xbd, 0x57, 0xfa, + 0x9e, 0x33, 0xd9, 0x74, 0x11, 0xbc, 0x56, 0xfb, 0x9f, 0x32, + 0xd8, 0x75, 0x12, 0xbf, 0x55, 0xf8, 0x9c, 0x31, 0xdb, 0x76, + 0x13, 0xbe, 0x54, 0xf9, 0x9d, 0x30, 0xda, 0x77, 0x14, 0xb9, + 0x53, 0xfe, 0x9a, 0x37, 0xdd, 0x70, 0x15, 0xb8, 0x52, 0xff, + 0x9b, 0x36, 0xdc, 0x71, 0x16, 0xbb, 0x51, 0xfc, 0x98, 0x35, + 0xdf, 0x72, 0x17, 0xba, 0x50, 0xfd, 0x99, 0x34, 0xde, 0x73, + 0x18, 0xb5, 0x5f, 0xf2, 0x96, 0x3b, 0xd1, 0x7c, 0x19, 0xb4, + 0x5e, 0xf3, 0x97, 0x3a, 0xd0, 0x7d, 0x1a, 0xb7, 0x5d, 0xf0, + 0x94, 0x39, 0xd3, 0x7e, 0x1b, 0xb6, 0x5c, 0xf1, 0x95, 0x38, + 0xd2, 0x7f, 0x1c, 0xb1, 0x5b, 0xf6, 0x92, 0x3f, 0xd5, 0x78, + 0x1d, 0xb0, 0x5a, 0xf7, 0x93, 0x3e, 0xd4, 0x79, 0x1e, 0xb3, + 0x59, 0xf4, 0x90, 0x3d, 0xd7, 0x7a, 0x1f, 0xb2, 0x58, 0xf5, + 0x91, 0x3c, 0xd6, 0x7b, 0x00, 0xae, 0x41, 0xef, 0x82, 0x2c, + 0xc3, 0x6d, 0x19, 0xb7, 0x58, 0xf6, 0x9b, 0x35, 0xda, 0x74, + 0x32, 0x9c, 0x73, 0xdd, 0xb0, 0x1e, 0xf1, 0x5f, 0x2b, 0x85, + 0x6a, 0xc4, 0xa9, 0x07, 0xe8, 0x46, 0x64, 0xca, 0x25, 0x8b, + 0xe6, 0x48, 0xa7, 0x09, 0x7d, 0xd3, 0x3c, 0x92, 0xff, 0x51, + 0xbe, 0x10, 0x56, 0xf8, 0x17, 0xb9, 0xd4, 0x7a, 0x95, 0x3b, + 0x4f, 0xe1, 0x0e, 0xa0, 0xcd, 0x63, 0x8c, 0x22, 0xc8, 0x66, + 0x89, 0x27, 0x4a, 0xe4, 0x0b, 0xa5, 0xd1, 0x7f, 0x90, 0x3e, + 0x53, 0xfd, 0x12, 0xbc, 0xfa, 0x54, 0xbb, 0x15, 0x78, 0xd6, + 0x39, 0x97, 0xe3, 0x4d, 0xa2, 0x0c, 0x61, 0xcf, 0x20, 0x8e, + 0xac, 0x02, 0xed, 0x43, 0x2e, 0x80, 0x6f, 0xc1, 0xb5, 0x1b, + 0xf4, 0x5a, 0x37, 0x99, 0x76, 0xd8, 0x9e, 0x30, 0xdf, 0x71, + 0x1c, 0xb2, 0x5d, 0xf3, 0x87, 0x29, 0xc6, 0x68, 0x05, 0xab, + 0x44, 0xea, 0x8d, 0x23, 0xcc, 0x62, 0x0f, 0xa1, 0x4e, 0xe0, + 0x94, 0x3a, 0xd5, 0x7b, 0x16, 0xb8, 0x57, 0xf9, 0xbf, 0x11, + 0xfe, 0x50, 0x3d, 0x93, 0x7c, 0xd2, 0xa6, 0x08, 0xe7, 0x49, + 0x24, 0x8a, 0x65, 0xcb, 0xe9, 0x47, 0xa8, 0x06, 0x6b, 0xc5, + 0x2a, 0x84, 0xf0, 0x5e, 0xb1, 0x1f, 0x72, 0xdc, 0x33, 0x9d, + 0xdb, 0x75, 0x9a, 0x34, 0x59, 0xf7, 0x18, 0xb6, 0xc2, 0x6c, + 0x83, 0x2d, 0x40, 0xee, 0x01, 0xaf, 0x45, 0xeb, 0x04, 0xaa, + 0xc7, 0x69, 0x86, 0x28, 0x5c, 0xf2, 0x1d, 0xb3, 0xde, 0x70, + 0x9f, 0x31, 0x77, 0xd9, 0x36, 0x98, 0xf5, 0x5b, 0xb4, 0x1a, + 0x6e, 0xc0, 0x2f, 0x81, 0xec, 0x42, 0xad, 0x03, 0x21, 0x8f, + 0x60, 0xce, 0xa3, 0x0d, 0xe2, 0x4c, 0x38, 0x96, 0x79, 0xd7, + 0xba, 0x14, 0xfb, 0x55, 0x13, 0xbd, 0x52, 0xfc, 0x91, 0x3f, + 0xd0, 0x7e, 0x0a, 0xa4, 0x4b, 0xe5, 0x88, 0x26, 0xc9, 0x67, + 0x00, 0xaf, 0x43, 0xec, 0x86, 0x29, 0xc5, 0x6a, 0x11, 0xbe, + 0x52, 0xfd, 0x97, 0x38, 0xd4, 0x7b, 0x22, 0x8d, 0x61, 0xce, + 0xa4, 0x0b, 0xe7, 0x48, 0x33, 0x9c, 0x70, 0xdf, 0xb5, 0x1a, + 0xf6, 0x59, 0x44, 0xeb, 0x07, 0xa8, 0xc2, 0x6d, 0x81, 0x2e, + 0x55, 0xfa, 0x16, 0xb9, 0xd3, 0x7c, 0x90, 0x3f, 0x66, 0xc9, + 0x25, 0x8a, 0xe0, 0x4f, 0xa3, 0x0c, 0x77, 0xd8, 0x34, 0x9b, + 0xf1, 0x5e, 0xb2, 0x1d, 0x88, 0x27, 0xcb, 0x64, 0x0e, 0xa1, + 0x4d, 0xe2, 0x99, 0x36, 0xda, 0x75, 0x1f, 0xb0, 0x5c, 0xf3, + 0xaa, 0x05, 0xe9, 0x46, 0x2c, 0x83, 0x6f, 0xc0, 0xbb, 0x14, + 0xf8, 0x57, 0x3d, 0x92, 0x7e, 0xd1, 0xcc, 0x63, 0x8f, 0x20, + 0x4a, 0xe5, 0x09, 0xa6, 0xdd, 0x72, 0x9e, 0x31, 0x5b, 0xf4, + 0x18, 0xb7, 0xee, 0x41, 0xad, 0x02, 0x68, 0xc7, 0x2b, 0x84, + 0xff, 0x50, 0xbc, 0x13, 0x79, 0xd6, 0x3a, 0x95, 0x0d, 0xa2, + 0x4e, 0xe1, 0x8b, 0x24, 0xc8, 0x67, 0x1c, 0xb3, 0x5f, 0xf0, + 0x9a, 0x35, 0xd9, 0x76, 0x2f, 0x80, 0x6c, 0xc3, 0xa9, 0x06, + 0xea, 0x45, 0x3e, 0x91, 0x7d, 0xd2, 0xb8, 0x17, 0xfb, 0x54, + 0x49, 0xe6, 0x0a, 0xa5, 0xcf, 0x60, 0x8c, 0x23, 0x58, 0xf7, + 0x1b, 0xb4, 0xde, 0x71, 0x9d, 0x32, 0x6b, 0xc4, 0x28, 0x87, + 0xed, 0x42, 0xae, 0x01, 0x7a, 0xd5, 0x39, 0x96, 0xfc, 0x53, + 0xbf, 0x10, 0x85, 0x2a, 0xc6, 0x69, 0x03, 0xac, 0x40, 0xef, + 0x94, 0x3b, 0xd7, 0x78, 0x12, 0xbd, 0x51, 0xfe, 0xa7, 0x08, + 0xe4, 0x4b, 0x21, 0x8e, 0x62, 0xcd, 0xb6, 0x19, 0xf5, 0x5a, + 0x30, 0x9f, 0x73, 0xdc, 0xc1, 0x6e, 0x82, 0x2d, 0x47, 0xe8, + 0x04, 0xab, 0xd0, 0x7f, 0x93, 0x3c, 0x56, 0xf9, 0x15, 0xba, + 0xe3, 0x4c, 0xa0, 0x0f, 0x65, 0xca, 0x26, 0x89, 0xf2, 0x5d, + 0xb1, 0x1e, 0x74, 0xdb, 0x37, 0x98, 0x00, 0xb0, 0x7d, 0xcd, + 0xfa, 0x4a, 0x87, 0x37, 0xe9, 0x59, 0x94, 0x24, 0x13, 0xa3, + 0x6e, 0xde, 0xcf, 0x7f, 0xb2, 0x02, 0x35, 0x85, 0x48, 0xf8, + 0x26, 0x96, 0x5b, 0xeb, 0xdc, 0x6c, 0xa1, 0x11, 0x83, 0x33, + 0xfe, 0x4e, 0x79, 0xc9, 0x04, 0xb4, 0x6a, 0xda, 0x17, 0xa7, + 0x90, 0x20, 0xed, 0x5d, 0x4c, 0xfc, 0x31, 0x81, 0xb6, 0x06, + 0xcb, 0x7b, 0xa5, 0x15, 0xd8, 0x68, 0x5f, 0xef, 0x22, 0x92, + 0x1b, 0xab, 0x66, 0xd6, 0xe1, 0x51, 0x9c, 0x2c, 0xf2, 0x42, + 0x8f, 0x3f, 0x08, 0xb8, 0x75, 0xc5, 0xd4, 0x64, 0xa9, 0x19, + 0x2e, 0x9e, 0x53, 0xe3, 0x3d, 0x8d, 0x40, 0xf0, 0xc7, 0x77, + 0xba, 0x0a, 0x98, 0x28, 0xe5, 0x55, 0x62, 0xd2, 0x1f, 0xaf, + 0x71, 0xc1, 0x0c, 0xbc, 0x8b, 0x3b, 0xf6, 0x46, 0x57, 0xe7, + 0x2a, 0x9a, 0xad, 0x1d, 0xd0, 0x60, 0xbe, 0x0e, 0xc3, 0x73, + 0x44, 0xf4, 0x39, 0x89, 0x36, 0x86, 0x4b, 0xfb, 0xcc, 0x7c, + 0xb1, 0x01, 0xdf, 0x6f, 0xa2, 0x12, 0x25, 0x95, 0x58, 0xe8, + 0xf9, 0x49, 0x84, 0x34, 0x03, 0xb3, 0x7e, 0xce, 0x10, 0xa0, + 0x6d, 0xdd, 0xea, 0x5a, 0x97, 0x27, 0xb5, 0x05, 0xc8, 0x78, + 0x4f, 0xff, 0x32, 0x82, 0x5c, 0xec, 0x21, 0x91, 0xa6, 0x16, + 0xdb, 0x6b, 0x7a, 0xca, 0x07, 0xb7, 0x80, 0x30, 0xfd, 0x4d, + 0x93, 0x23, 0xee, 0x5e, 0x69, 0xd9, 0x14, 0xa4, 0x2d, 0x9d, + 0x50, 0xe0, 0xd7, 0x67, 0xaa, 0x1a, 0xc4, 0x74, 0xb9, 0x09, + 0x3e, 0x8e, 0x43, 0xf3, 0xe2, 0x52, 0x9f, 0x2f, 0x18, 0xa8, + 0x65, 0xd5, 0x0b, 0xbb, 0x76, 0xc6, 0xf1, 0x41, 0x8c, 0x3c, + 0xae, 0x1e, 0xd3, 0x63, 0x54, 0xe4, 0x29, 0x99, 0x47, 0xf7, + 0x3a, 0x8a, 0xbd, 0x0d, 0xc0, 0x70, 0x61, 0xd1, 0x1c, 0xac, + 0x9b, 0x2b, 0xe6, 0x56, 0x88, 0x38, 0xf5, 0x45, 0x72, 0xc2, + 0x0f, 0xbf, 0x00, 0xb1, 0x7f, 0xce, 0xfe, 0x4f, 0x81, 0x30, + 0xe1, 0x50, 0x9e, 0x2f, 0x1f, 0xae, 0x60, 0xd1, 0xdf, 0x6e, + 0xa0, 0x11, 0x21, 0x90, 0x5e, 0xef, 0x3e, 0x8f, 0x41, 0xf0, + 0xc0, 0x71, 0xbf, 0x0e, 0xa3, 0x12, 0xdc, 0x6d, 0x5d, 0xec, + 0x22, 0x93, 0x42, 0xf3, 0x3d, 0x8c, 0xbc, 0x0d, 0xc3, 0x72, + 0x7c, 0xcd, 0x03, 0xb2, 0x82, 0x33, 0xfd, 0x4c, 0x9d, 0x2c, + 0xe2, 0x53, 0x63, 0xd2, 0x1c, 0xad, 0x5b, 0xea, 0x24, 0x95, + 0xa5, 0x14, 0xda, 0x6b, 0xba, 0x0b, 0xc5, 0x74, 0x44, 0xf5, + 0x3b, 0x8a, 0x84, 0x35, 0xfb, 0x4a, 0x7a, 0xcb, 0x05, 0xb4, + 0x65, 0xd4, 0x1a, 0xab, 0x9b, 0x2a, 0xe4, 0x55, 0xf8, 0x49, + 0x87, 0x36, 0x06, 0xb7, 0x79, 0xc8, 0x19, 0xa8, 0x66, 0xd7, + 0xe7, 0x56, 0x98, 0x29, 0x27, 0x96, 0x58, 0xe9, 0xd9, 0x68, + 0xa6, 0x17, 0xc6, 0x77, 0xb9, 0x08, 0x38, 0x89, 0x47, 0xf6, + 0xb6, 0x07, 0xc9, 0x78, 0x48, 0xf9, 0x37, 0x86, 0x57, 0xe6, + 0x28, 0x99, 0xa9, 0x18, 0xd6, 0x67, 0x69, 0xd8, 0x16, 0xa7, + 0x97, 0x26, 0xe8, 0x59, 0x88, 0x39, 0xf7, 0x46, 0x76, 0xc7, + 0x09, 0xb8, 0x15, 0xa4, 0x6a, 0xdb, 0xeb, 0x5a, 0x94, 0x25, + 0xf4, 0x45, 0x8b, 0x3a, 0x0a, 0xbb, 0x75, 0xc4, 0xca, 0x7b, + 0xb5, 0x04, 0x34, 0x85, 0x4b, 0xfa, 0x2b, 0x9a, 0x54, 0xe5, + 0xd5, 0x64, 0xaa, 0x1b, 0xed, 0x5c, 0x92, 0x23, 0x13, 0xa2, + 0x6c, 0xdd, 0x0c, 0xbd, 0x73, 0xc2, 0xf2, 0x43, 0x8d, 0x3c, + 0x32, 0x83, 0x4d, 0xfc, 0xcc, 0x7d, 0xb3, 0x02, 0xd3, 0x62, + 0xac, 0x1d, 0x2d, 0x9c, 0x52, 0xe3, 0x4e, 0xff, 0x31, 0x80, + 0xb0, 0x01, 0xcf, 0x7e, 0xaf, 0x1e, 0xd0, 0x61, 0x51, 0xe0, + 0x2e, 0x9f, 0x91, 0x20, 0xee, 0x5f, 0x6f, 0xde, 0x10, 0xa1, + 0x70, 0xc1, 0x0f, 0xbe, 0x8e, 0x3f, 0xf1, 0x40, 0x00, 0xb2, + 0x79, 0xcb, 0xf2, 0x40, 0x8b, 0x39, 0xf9, 0x4b, 0x80, 0x32, + 0x0b, 0xb9, 0x72, 0xc0, 0xef, 0x5d, 0x96, 0x24, 0x1d, 0xaf, + 0x64, 0xd6, 0x16, 0xa4, 0x6f, 0xdd, 0xe4, 0x56, 0x9d, 0x2f, + 0xc3, 0x71, 0xba, 0x08, 0x31, 0x83, 0x48, 0xfa, 0x3a, 0x88, + 0x43, 0xf1, 0xc8, 0x7a, 0xb1, 0x03, 0x2c, 0x9e, 0x55, 0xe7, + 0xde, 0x6c, 0xa7, 0x15, 0xd5, 0x67, 0xac, 0x1e, 0x27, 0x95, + 0x5e, 0xec, 0x9b, 0x29, 0xe2, 0x50, 0x69, 0xdb, 0x10, 0xa2, + 0x62, 0xd0, 0x1b, 0xa9, 0x90, 0x22, 0xe9, 0x5b, 0x74, 0xc6, + 0x0d, 0xbf, 0x86, 0x34, 0xff, 0x4d, 0x8d, 0x3f, 0xf4, 0x46, + 0x7f, 0xcd, 0x06, 0xb4, 0x58, 0xea, 0x21, 0x93, 0xaa, 0x18, + 0xd3, 0x61, 0xa1, 0x13, 0xd8, 0x6a, 0x53, 0xe1, 0x2a, 0x98, + 0xb7, 0x05, 0xce, 0x7c, 0x45, 0xf7, 0x3c, 0x8e, 0x4e, 0xfc, + 0x37, 0x85, 0xbc, 0x0e, 0xc5, 0x77, 0x2b, 0x99, 0x52, 0xe0, + 0xd9, 0x6b, 0xa0, 0x12, 0xd2, 0x60, 0xab, 0x19, 0x20, 0x92, + 0x59, 0xeb, 0xc4, 0x76, 0xbd, 0x0f, 0x36, 0x84, 0x4f, 0xfd, + 0x3d, 0x8f, 0x44, 0xf6, 0xcf, 0x7d, 0xb6, 0x04, 0xe8, 0x5a, + 0x91, 0x23, 0x1a, 0xa8, 0x63, 0xd1, 0x11, 0xa3, 0x68, 0xda, + 0xe3, 0x51, 0x9a, 0x28, 0x07, 0xb5, 0x7e, 0xcc, 0xf5, 0x47, + 0x8c, 0x3e, 0xfe, 0x4c, 0x87, 0x35, 0x0c, 0xbe, 0x75, 0xc7, + 0xb0, 0x02, 0xc9, 0x7b, 0x42, 0xf0, 0x3b, 0x89, 0x49, 0xfb, + 0x30, 0x82, 0xbb, 0x09, 0xc2, 0x70, 0x5f, 0xed, 0x26, 0x94, + 0xad, 0x1f, 0xd4, 0x66, 0xa6, 0x14, 0xdf, 0x6d, 0x54, 0xe6, + 0x2d, 0x9f, 0x73, 0xc1, 0x0a, 0xb8, 0x81, 0x33, 0xf8, 0x4a, + 0x8a, 0x38, 0xf3, 0x41, 0x78, 0xca, 0x01, 0xb3, 0x9c, 0x2e, + 0xe5, 0x57, 0x6e, 0xdc, 0x17, 0xa5, 0x65, 0xd7, 0x1c, 0xae, + 0x97, 0x25, 0xee, 0x5c, 0x00, 0xb3, 0x7b, 0xc8, 0xf6, 0x45, + 0x8d, 0x3e, 0xf1, 0x42, 0x8a, 0x39, 0x07, 0xb4, 0x7c, 0xcf, + 0xff, 0x4c, 0x84, 0x37, 0x09, 0xba, 0x72, 0xc1, 0x0e, 0xbd, + 0x75, 0xc6, 0xf8, 0x4b, 0x83, 0x30, 0xe3, 0x50, 0x98, 0x2b, + 0x15, 0xa6, 0x6e, 0xdd, 0x12, 0xa1, 0x69, 0xda, 0xe4, 0x57, + 0x9f, 0x2c, 0x1c, 0xaf, 0x67, 0xd4, 0xea, 0x59, 0x91, 0x22, + 0xed, 0x5e, 0x96, 0x25, 0x1b, 0xa8, 0x60, 0xd3, 0xdb, 0x68, + 0xa0, 0x13, 0x2d, 0x9e, 0x56, 0xe5, 0x2a, 0x99, 0x51, 0xe2, + 0xdc, 0x6f, 0xa7, 0x14, 0x24, 0x97, 0x5f, 0xec, 0xd2, 0x61, + 0xa9, 0x1a, 0xd5, 0x66, 0xae, 0x1d, 0x23, 0x90, 0x58, 0xeb, + 0x38, 0x8b, 0x43, 0xf0, 0xce, 0x7d, 0xb5, 0x06, 0xc9, 0x7a, + 0xb2, 0x01, 0x3f, 0x8c, 0x44, 0xf7, 0xc7, 0x74, 0xbc, 0x0f, + 0x31, 0x82, 0x4a, 0xf9, 0x36, 0x85, 0x4d, 0xfe, 0xc0, 0x73, + 0xbb, 0x08, 0xab, 0x18, 0xd0, 0x63, 0x5d, 0xee, 0x26, 0x95, + 0x5a, 0xe9, 0x21, 0x92, 0xac, 0x1f, 0xd7, 0x64, 0x54, 0xe7, + 0x2f, 0x9c, 0xa2, 0x11, 0xd9, 0x6a, 0xa5, 0x16, 0xde, 0x6d, + 0x53, 0xe0, 0x28, 0x9b, 0x48, 0xfb, 0x33, 0x80, 0xbe, 0x0d, + 0xc5, 0x76, 0xb9, 0x0a, 0xc2, 0x71, 0x4f, 0xfc, 0x34, 0x87, + 0xb7, 0x04, 0xcc, 0x7f, 0x41, 0xf2, 0x3a, 0x89, 0x46, 0xf5, + 0x3d, 0x8e, 0xb0, 0x03, 0xcb, 0x78, 0x70, 0xc3, 0x0b, 0xb8, + 0x86, 0x35, 0xfd, 0x4e, 0x81, 0x32, 0xfa, 0x49, 0x77, 0xc4, + 0x0c, 0xbf, 0x8f, 0x3c, 0xf4, 0x47, 0x79, 0xca, 0x02, 0xb1, + 0x7e, 0xcd, 0x05, 0xb6, 0x88, 0x3b, 0xf3, 0x40, 0x93, 0x20, + 0xe8, 0x5b, 0x65, 0xd6, 0x1e, 0xad, 0x62, 0xd1, 0x19, 0xaa, + 0x94, 0x27, 0xef, 0x5c, 0x6c, 0xdf, 0x17, 0xa4, 0x9a, 0x29, + 0xe1, 0x52, 0x9d, 0x2e, 0xe6, 0x55, 0x6b, 0xd8, 0x10, 0xa3, + 0x00, 0xb4, 0x75, 0xc1, 0xea, 0x5e, 0x9f, 0x2b, 0xc9, 0x7d, + 0xbc, 0x08, 0x23, 0x97, 0x56, 0xe2, 0x8f, 0x3b, 0xfa, 0x4e, + 0x65, 0xd1, 0x10, 0xa4, 0x46, 0xf2, 0x33, 0x87, 0xac, 0x18, + 0xd9, 0x6d, 0x03, 0xb7, 0x76, 0xc2, 0xe9, 0x5d, 0x9c, 0x28, + 0xca, 0x7e, 0xbf, 0x0b, 0x20, 0x94, 0x55, 0xe1, 0x8c, 0x38, + 0xf9, 0x4d, 0x66, 0xd2, 0x13, 0xa7, 0x45, 0xf1, 0x30, 0x84, + 0xaf, 0x1b, 0xda, 0x6e, 0x06, 0xb2, 0x73, 0xc7, 0xec, 0x58, + 0x99, 0x2d, 0xcf, 0x7b, 0xba, 0x0e, 0x25, 0x91, 0x50, 0xe4, + 0x89, 0x3d, 0xfc, 0x48, 0x63, 0xd7, 0x16, 0xa2, 0x40, 0xf4, + 0x35, 0x81, 0xaa, 0x1e, 0xdf, 0x6b, 0x05, 0xb1, 0x70, 0xc4, + 0xef, 0x5b, 0x9a, 0x2e, 0xcc, 0x78, 0xb9, 0x0d, 0x26, 0x92, + 0x53, 0xe7, 0x8a, 0x3e, 0xff, 0x4b, 0x60, 0xd4, 0x15, 0xa1, + 0x43, 0xf7, 0x36, 0x82, 0xa9, 0x1d, 0xdc, 0x68, 0x0c, 0xb8, + 0x79, 0xcd, 0xe6, 0x52, 0x93, 0x27, 0xc5, 0x71, 0xb0, 0x04, + 0x2f, 0x9b, 0x5a, 0xee, 0x83, 0x37, 0xf6, 0x42, 0x69, 0xdd, + 0x1c, 0xa8, 0x4a, 0xfe, 0x3f, 0x8b, 0xa0, 0x14, 0xd5, 0x61, + 0x0f, 0xbb, 0x7a, 0xce, 0xe5, 0x51, 0x90, 0x24, 0xc6, 0x72, + 0xb3, 0x07, 0x2c, 0x98, 0x59, 0xed, 0x80, 0x34, 0xf5, 0x41, + 0x6a, 0xde, 0x1f, 0xab, 0x49, 0xfd, 0x3c, 0x88, 0xa3, 0x17, + 0xd6, 0x62, 0x0a, 0xbe, 0x7f, 0xcb, 0xe0, 0x54, 0x95, 0x21, + 0xc3, 0x77, 0xb6, 0x02, 0x29, 0x9d, 0x5c, 0xe8, 0x85, 0x31, + 0xf0, 0x44, 0x6f, 0xdb, 0x1a, 0xae, 0x4c, 0xf8, 0x39, 0x8d, + 0xa6, 0x12, 0xd3, 0x67, 0x09, 0xbd, 0x7c, 0xc8, 0xe3, 0x57, + 0x96, 0x22, 0xc0, 0x74, 0xb5, 0x01, 0x2a, 0x9e, 0x5f, 0xeb, + 0x86, 0x32, 0xf3, 0x47, 0x6c, 0xd8, 0x19, 0xad, 0x4f, 0xfb, + 0x3a, 0x8e, 0xa5, 0x11, 0xd0, 0x64, 0x00, 0xb5, 0x77, 0xc2, + 0xee, 0x5b, 0x99, 0x2c, 0xc1, 0x74, 0xb6, 0x03, 0x2f, 0x9a, + 0x58, 0xed, 0x9f, 0x2a, 0xe8, 0x5d, 0x71, 0xc4, 0x06, 0xb3, + 0x5e, 0xeb, 0x29, 0x9c, 0xb0, 0x05, 0xc7, 0x72, 0x23, 0x96, + 0x54, 0xe1, 0xcd, 0x78, 0xba, 0x0f, 0xe2, 0x57, 0x95, 0x20, + 0x0c, 0xb9, 0x7b, 0xce, 0xbc, 0x09, 0xcb, 0x7e, 0x52, 0xe7, + 0x25, 0x90, 0x7d, 0xc8, 0x0a, 0xbf, 0x93, 0x26, 0xe4, 0x51, + 0x46, 0xf3, 0x31, 0x84, 0xa8, 0x1d, 0xdf, 0x6a, 0x87, 0x32, + 0xf0, 0x45, 0x69, 0xdc, 0x1e, 0xab, 0xd9, 0x6c, 0xae, 0x1b, + 0x37, 0x82, 0x40, 0xf5, 0x18, 0xad, 0x6f, 0xda, 0xf6, 0x43, + 0x81, 0x34, 0x65, 0xd0, 0x12, 0xa7, 0x8b, 0x3e, 0xfc, 0x49, + 0xa4, 0x11, 0xd3, 0x66, 0x4a, 0xff, 0x3d, 0x88, 0xfa, 0x4f, + 0x8d, 0x38, 0x14, 0xa1, 0x63, 0xd6, 0x3b, 0x8e, 0x4c, 0xf9, + 0xd5, 0x60, 0xa2, 0x17, 0x8c, 0x39, 0xfb, 0x4e, 0x62, 0xd7, + 0x15, 0xa0, 0x4d, 0xf8, 0x3a, 0x8f, 0xa3, 0x16, 0xd4, 0x61, + 0x13, 0xa6, 0x64, 0xd1, 0xfd, 0x48, 0x8a, 0x3f, 0xd2, 0x67, + 0xa5, 0x10, 0x3c, 0x89, 0x4b, 0xfe, 0xaf, 0x1a, 0xd8, 0x6d, + 0x41, 0xf4, 0x36, 0x83, 0x6e, 0xdb, 0x19, 0xac, 0x80, 0x35, + 0xf7, 0x42, 0x30, 0x85, 0x47, 0xf2, 0xde, 0x6b, 0xa9, 0x1c, + 0xf1, 0x44, 0x86, 0x33, 0x1f, 0xaa, 0x68, 0xdd, 0xca, 0x7f, + 0xbd, 0x08, 0x24, 0x91, 0x53, 0xe6, 0x0b, 0xbe, 0x7c, 0xc9, + 0xe5, 0x50, 0x92, 0x27, 0x55, 0xe0, 0x22, 0x97, 0xbb, 0x0e, + 0xcc, 0x79, 0x94, 0x21, 0xe3, 0x56, 0x7a, 0xcf, 0x0d, 0xb8, + 0xe9, 0x5c, 0x9e, 0x2b, 0x07, 0xb2, 0x70, 0xc5, 0x28, 0x9d, + 0x5f, 0xea, 0xc6, 0x73, 0xb1, 0x04, 0x76, 0xc3, 0x01, 0xb4, + 0x98, 0x2d, 0xef, 0x5a, 0xb7, 0x02, 0xc0, 0x75, 0x59, 0xec, + 0x2e, 0x9b, 0x00, 0xb6, 0x71, 0xc7, 0xe2, 0x54, 0x93, 0x25, + 0xd9, 0x6f, 0xa8, 0x1e, 0x3b, 0x8d, 0x4a, 0xfc, 0xaf, 0x19, + 0xde, 0x68, 0x4d, 0xfb, 0x3c, 0x8a, 0x76, 0xc0, 0x07, 0xb1, + 0x94, 0x22, 0xe5, 0x53, 0x43, 0xf5, 0x32, 0x84, 0xa1, 0x17, + 0xd0, 0x66, 0x9a, 0x2c, 0xeb, 0x5d, 0x78, 0xce, 0x09, 0xbf, + 0xec, 0x5a, 0x9d, 0x2b, 0x0e, 0xb8, 0x7f, 0xc9, 0x35, 0x83, + 0x44, 0xf2, 0xd7, 0x61, 0xa6, 0x10, 0x86, 0x30, 0xf7, 0x41, + 0x64, 0xd2, 0x15, 0xa3, 0x5f, 0xe9, 0x2e, 0x98, 0xbd, 0x0b, + 0xcc, 0x7a, 0x29, 0x9f, 0x58, 0xee, 0xcb, 0x7d, 0xba, 0x0c, + 0xf0, 0x46, 0x81, 0x37, 0x12, 0xa4, 0x63, 0xd5, 0xc5, 0x73, + 0xb4, 0x02, 0x27, 0x91, 0x56, 0xe0, 0x1c, 0xaa, 0x6d, 0xdb, + 0xfe, 0x48, 0x8f, 0x39, 0x6a, 0xdc, 0x1b, 0xad, 0x88, 0x3e, + 0xf9, 0x4f, 0xb3, 0x05, 0xc2, 0x74, 0x51, 0xe7, 0x20, 0x96, + 0x11, 0xa7, 0x60, 0xd6, 0xf3, 0x45, 0x82, 0x34, 0xc8, 0x7e, + 0xb9, 0x0f, 0x2a, 0x9c, 0x5b, 0xed, 0xbe, 0x08, 0xcf, 0x79, + 0x5c, 0xea, 0x2d, 0x9b, 0x67, 0xd1, 0x16, 0xa0, 0x85, 0x33, + 0xf4, 0x42, 0x52, 0xe4, 0x23, 0x95, 0xb0, 0x06, 0xc1, 0x77, + 0x8b, 0x3d, 0xfa, 0x4c, 0x69, 0xdf, 0x18, 0xae, 0xfd, 0x4b, + 0x8c, 0x3a, 0x1f, 0xa9, 0x6e, 0xd8, 0x24, 0x92, 0x55, 0xe3, + 0xc6, 0x70, 0xb7, 0x01, 0x97, 0x21, 0xe6, 0x50, 0x75, 0xc3, + 0x04, 0xb2, 0x4e, 0xf8, 0x3f, 0x89, 0xac, 0x1a, 0xdd, 0x6b, + 0x38, 0x8e, 0x49, 0xff, 0xda, 0x6c, 0xab, 0x1d, 0xe1, 0x57, + 0x90, 0x26, 0x03, 0xb5, 0x72, 0xc4, 0xd4, 0x62, 0xa5, 0x13, + 0x36, 0x80, 0x47, 0xf1, 0x0d, 0xbb, 0x7c, 0xca, 0xef, 0x59, + 0x9e, 0x28, 0x7b, 0xcd, 0x0a, 0xbc, 0x99, 0x2f, 0xe8, 0x5e, + 0xa2, 0x14, 0xd3, 0x65, 0x40, 0xf6, 0x31, 0x87, 0x00, 0xb7, + 0x73, 0xc4, 0xe6, 0x51, 0x95, 0x22, 0xd1, 0x66, 0xa2, 0x15, + 0x37, 0x80, 0x44, 0xf3, 0xbf, 0x08, 0xcc, 0x7b, 0x59, 0xee, + 0x2a, 0x9d, 0x6e, 0xd9, 0x1d, 0xaa, 0x88, 0x3f, 0xfb, 0x4c, + 0x63, 0xd4, 0x10, 0xa7, 0x85, 0x32, 0xf6, 0x41, 0xb2, 0x05, + 0xc1, 0x76, 0x54, 0xe3, 0x27, 0x90, 0xdc, 0x6b, 0xaf, 0x18, + 0x3a, 0x8d, 0x49, 0xfe, 0x0d, 0xba, 0x7e, 0xc9, 0xeb, 0x5c, + 0x98, 0x2f, 0xc6, 0x71, 0xb5, 0x02, 0x20, 0x97, 0x53, 0xe4, + 0x17, 0xa0, 0x64, 0xd3, 0xf1, 0x46, 0x82, 0x35, 0x79, 0xce, + 0x0a, 0xbd, 0x9f, 0x28, 0xec, 0x5b, 0xa8, 0x1f, 0xdb, 0x6c, + 0x4e, 0xf9, 0x3d, 0x8a, 0xa5, 0x12, 0xd6, 0x61, 0x43, 0xf4, + 0x30, 0x87, 0x74, 0xc3, 0x07, 0xb0, 0x92, 0x25, 0xe1, 0x56, + 0x1a, 0xad, 0x69, 0xde, 0xfc, 0x4b, 0x8f, 0x38, 0xcb, 0x7c, + 0xb8, 0x0f, 0x2d, 0x9a, 0x5e, 0xe9, 0x91, 0x26, 0xe2, 0x55, + 0x77, 0xc0, 0x04, 0xb3, 0x40, 0xf7, 0x33, 0x84, 0xa6, 0x11, + 0xd5, 0x62, 0x2e, 0x99, 0x5d, 0xea, 0xc8, 0x7f, 0xbb, 0x0c, + 0xff, 0x48, 0x8c, 0x3b, 0x19, 0xae, 0x6a, 0xdd, 0xf2, 0x45, + 0x81, 0x36, 0x14, 0xa3, 0x67, 0xd0, 0x23, 0x94, 0x50, 0xe7, + 0xc5, 0x72, 0xb6, 0x01, 0x4d, 0xfa, 0x3e, 0x89, 0xab, 0x1c, + 0xd8, 0x6f, 0x9c, 0x2b, 0xef, 0x58, 0x7a, 0xcd, 0x09, 0xbe, + 0x57, 0xe0, 0x24, 0x93, 0xb1, 0x06, 0xc2, 0x75, 0x86, 0x31, + 0xf5, 0x42, 0x60, 0xd7, 0x13, 0xa4, 0xe8, 0x5f, 0x9b, 0x2c, + 0x0e, 0xb9, 0x7d, 0xca, 0x39, 0x8e, 0x4a, 0xfd, 0xdf, 0x68, + 0xac, 0x1b, 0x34, 0x83, 0x47, 0xf0, 0xd2, 0x65, 0xa1, 0x16, + 0xe5, 0x52, 0x96, 0x21, 0x03, 0xb4, 0x70, 0xc7, 0x8b, 0x3c, + 0xf8, 0x4f, 0x6d, 0xda, 0x1e, 0xa9, 0x5a, 0xed, 0x29, 0x9e, + 0xbc, 0x0b, 0xcf, 0x78, 0x00, 0xb8, 0x6d, 0xd5, 0xda, 0x62, + 0xb7, 0x0f, 0xa9, 0x11, 0xc4, 0x7c, 0x73, 0xcb, 0x1e, 0xa6, + 0x4f, 0xf7, 0x22, 0x9a, 0x95, 0x2d, 0xf8, 0x40, 0xe6, 0x5e, + 0x8b, 0x33, 0x3c, 0x84, 0x51, 0xe9, 0x9e, 0x26, 0xf3, 0x4b, + 0x44, 0xfc, 0x29, 0x91, 0x37, 0x8f, 0x5a, 0xe2, 0xed, 0x55, + 0x80, 0x38, 0xd1, 0x69, 0xbc, 0x04, 0x0b, 0xb3, 0x66, 0xde, + 0x78, 0xc0, 0x15, 0xad, 0xa2, 0x1a, 0xcf, 0x77, 0x21, 0x99, + 0x4c, 0xf4, 0xfb, 0x43, 0x96, 0x2e, 0x88, 0x30, 0xe5, 0x5d, + 0x52, 0xea, 0x3f, 0x87, 0x6e, 0xd6, 0x03, 0xbb, 0xb4, 0x0c, + 0xd9, 0x61, 0xc7, 0x7f, 0xaa, 0x12, 0x1d, 0xa5, 0x70, 0xc8, + 0xbf, 0x07, 0xd2, 0x6a, 0x65, 0xdd, 0x08, 0xb0, 0x16, 0xae, + 0x7b, 0xc3, 0xcc, 0x74, 0xa1, 0x19, 0xf0, 0x48, 0x9d, 0x25, + 0x2a, 0x92, 0x47, 0xff, 0x59, 0xe1, 0x34, 0x8c, 0x83, 0x3b, + 0xee, 0x56, 0x42, 0xfa, 0x2f, 0x97, 0x98, 0x20, 0xf5, 0x4d, + 0xeb, 0x53, 0x86, 0x3e, 0x31, 0x89, 0x5c, 0xe4, 0x0d, 0xb5, + 0x60, 0xd8, 0xd7, 0x6f, 0xba, 0x02, 0xa4, 0x1c, 0xc9, 0x71, + 0x7e, 0xc6, 0x13, 0xab, 0xdc, 0x64, 0xb1, 0x09, 0x06, 0xbe, + 0x6b, 0xd3, 0x75, 0xcd, 0x18, 0xa0, 0xaf, 0x17, 0xc2, 0x7a, + 0x93, 0x2b, 0xfe, 0x46, 0x49, 0xf1, 0x24, 0x9c, 0x3a, 0x82, + 0x57, 0xef, 0xe0, 0x58, 0x8d, 0x35, 0x63, 0xdb, 0x0e, 0xb6, + 0xb9, 0x01, 0xd4, 0x6c, 0xca, 0x72, 0xa7, 0x1f, 0x10, 0xa8, + 0x7d, 0xc5, 0x2c, 0x94, 0x41, 0xf9, 0xf6, 0x4e, 0x9b, 0x23, + 0x85, 0x3d, 0xe8, 0x50, 0x5f, 0xe7, 0x32, 0x8a, 0xfd, 0x45, + 0x90, 0x28, 0x27, 0x9f, 0x4a, 0xf2, 0x54, 0xec, 0x39, 0x81, + 0x8e, 0x36, 0xe3, 0x5b, 0xb2, 0x0a, 0xdf, 0x67, 0x68, 0xd0, + 0x05, 0xbd, 0x1b, 0xa3, 0x76, 0xce, 0xc1, 0x79, 0xac, 0x14, + 0x00, 0xb9, 0x6f, 0xd6, 0xde, 0x67, 0xb1, 0x08, 0xa1, 0x18, + 0xce, 0x77, 0x7f, 0xc6, 0x10, 0xa9, 0x5f, 0xe6, 0x30, 0x89, + 0x81, 0x38, 0xee, 0x57, 0xfe, 0x47, 0x91, 0x28, 0x20, 0x99, + 0x4f, 0xf6, 0xbe, 0x07, 0xd1, 0x68, 0x60, 0xd9, 0x0f, 0xb6, + 0x1f, 0xa6, 0x70, 0xc9, 0xc1, 0x78, 0xae, 0x17, 0xe1, 0x58, + 0x8e, 0x37, 0x3f, 0x86, 0x50, 0xe9, 0x40, 0xf9, 0x2f, 0x96, + 0x9e, 0x27, 0xf1, 0x48, 0x61, 0xd8, 0x0e, 0xb7, 0xbf, 0x06, + 0xd0, 0x69, 0xc0, 0x79, 0xaf, 0x16, 0x1e, 0xa7, 0x71, 0xc8, + 0x3e, 0x87, 0x51, 0xe8, 0xe0, 0x59, 0x8f, 0x36, 0x9f, 0x26, + 0xf0, 0x49, 0x41, 0xf8, 0x2e, 0x97, 0xdf, 0x66, 0xb0, 0x09, + 0x01, 0xb8, 0x6e, 0xd7, 0x7e, 0xc7, 0x11, 0xa8, 0xa0, 0x19, + 0xcf, 0x76, 0x80, 0x39, 0xef, 0x56, 0x5e, 0xe7, 0x31, 0x88, + 0x21, 0x98, 0x4e, 0xf7, 0xff, 0x46, 0x90, 0x29, 0xc2, 0x7b, + 0xad, 0x14, 0x1c, 0xa5, 0x73, 0xca, 0x63, 0xda, 0x0c, 0xb5, + 0xbd, 0x04, 0xd2, 0x6b, 0x9d, 0x24, 0xf2, 0x4b, 0x43, 0xfa, + 0x2c, 0x95, 0x3c, 0x85, 0x53, 0xea, 0xe2, 0x5b, 0x8d, 0x34, + 0x7c, 0xc5, 0x13, 0xaa, 0xa2, 0x1b, 0xcd, 0x74, 0xdd, 0x64, + 0xb2, 0x0b, 0x03, 0xba, 0x6c, 0xd5, 0x23, 0x9a, 0x4c, 0xf5, + 0xfd, 0x44, 0x92, 0x2b, 0x82, 0x3b, 0xed, 0x54, 0x5c, 0xe5, + 0x33, 0x8a, 0xa3, 0x1a, 0xcc, 0x75, 0x7d, 0xc4, 0x12, 0xab, + 0x02, 0xbb, 0x6d, 0xd4, 0xdc, 0x65, 0xb3, 0x0a, 0xfc, 0x45, + 0x93, 0x2a, 0x22, 0x9b, 0x4d, 0xf4, 0x5d, 0xe4, 0x32, 0x8b, + 0x83, 0x3a, 0xec, 0x55, 0x1d, 0xa4, 0x72, 0xcb, 0xc3, 0x7a, + 0xac, 0x15, 0xbc, 0x05, 0xd3, 0x6a, 0x62, 0xdb, 0x0d, 0xb4, + 0x42, 0xfb, 0x2d, 0x94, 0x9c, 0x25, 0xf3, 0x4a, 0xe3, 0x5a, + 0x8c, 0x35, 0x3d, 0x84, 0x52, 0xeb, 0x00, 0xba, 0x69, 0xd3, + 0xd2, 0x68, 0xbb, 0x01, 0xb9, 0x03, 0xd0, 0x6a, 0x6b, 0xd1, + 0x02, 0xb8, 0x6f, 0xd5, 0x06, 0xbc, 0xbd, 0x07, 0xd4, 0x6e, + 0xd6, 0x6c, 0xbf, 0x05, 0x04, 0xbe, 0x6d, 0xd7, 0xde, 0x64, + 0xb7, 0x0d, 0x0c, 0xb6, 0x65, 0xdf, 0x67, 0xdd, 0x0e, 0xb4, + 0xb5, 0x0f, 0xdc, 0x66, 0xb1, 0x0b, 0xd8, 0x62, 0x63, 0xd9, + 0x0a, 0xb0, 0x08, 0xb2, 0x61, 0xdb, 0xda, 0x60, 0xb3, 0x09, + 0xa1, 0x1b, 0xc8, 0x72, 0x73, 0xc9, 0x1a, 0xa0, 0x18, 0xa2, + 0x71, 0xcb, 0xca, 0x70, 0xa3, 0x19, 0xce, 0x74, 0xa7, 0x1d, + 0x1c, 0xa6, 0x75, 0xcf, 0x77, 0xcd, 0x1e, 0xa4, 0xa5, 0x1f, + 0xcc, 0x76, 0x7f, 0xc5, 0x16, 0xac, 0xad, 0x17, 0xc4, 0x7e, + 0xc6, 0x7c, 0xaf, 0x15, 0x14, 0xae, 0x7d, 0xc7, 0x10, 0xaa, + 0x79, 0xc3, 0xc2, 0x78, 0xab, 0x11, 0xa9, 0x13, 0xc0, 0x7a, + 0x7b, 0xc1, 0x12, 0xa8, 0x5f, 0xe5, 0x36, 0x8c, 0x8d, 0x37, + 0xe4, 0x5e, 0xe6, 0x5c, 0x8f, 0x35, 0x34, 0x8e, 0x5d, 0xe7, + 0x30, 0x8a, 0x59, 0xe3, 0xe2, 0x58, 0x8b, 0x31, 0x89, 0x33, + 0xe0, 0x5a, 0x5b, 0xe1, 0x32, 0x88, 0x81, 0x3b, 0xe8, 0x52, + 0x53, 0xe9, 0x3a, 0x80, 0x38, 0x82, 0x51, 0xeb, 0xea, 0x50, + 0x83, 0x39, 0xee, 0x54, 0x87, 0x3d, 0x3c, 0x86, 0x55, 0xef, + 0x57, 0xed, 0x3e, 0x84, 0x85, 0x3f, 0xec, 0x56, 0xfe, 0x44, + 0x97, 0x2d, 0x2c, 0x96, 0x45, 0xff, 0x47, 0xfd, 0x2e, 0x94, + 0x95, 0x2f, 0xfc, 0x46, 0x91, 0x2b, 0xf8, 0x42, 0x43, 0xf9, + 0x2a, 0x90, 0x28, 0x92, 0x41, 0xfb, 0xfa, 0x40, 0x93, 0x29, + 0x20, 0x9a, 0x49, 0xf3, 0xf2, 0x48, 0x9b, 0x21, 0x99, 0x23, + 0xf0, 0x4a, 0x4b, 0xf1, 0x22, 0x98, 0x4f, 0xf5, 0x26, 0x9c, + 0x9d, 0x27, 0xf4, 0x4e, 0xf6, 0x4c, 0x9f, 0x25, 0x24, 0x9e, + 0x4d, 0xf7, 0x00, 0xbb, 0x6b, 0xd0, 0xd6, 0x6d, 0xbd, 0x06, + 0xb1, 0x0a, 0xda, 0x61, 0x67, 0xdc, 0x0c, 0xb7, 0x7f, 0xc4, + 0x14, 0xaf, 0xa9, 0x12, 0xc2, 0x79, 0xce, 0x75, 0xa5, 0x1e, + 0x18, 0xa3, 0x73, 0xc8, 0xfe, 0x45, 0x95, 0x2e, 0x28, 0x93, + 0x43, 0xf8, 0x4f, 0xf4, 0x24, 0x9f, 0x99, 0x22, 0xf2, 0x49, + 0x81, 0x3a, 0xea, 0x51, 0x57, 0xec, 0x3c, 0x87, 0x30, 0x8b, + 0x5b, 0xe0, 0xe6, 0x5d, 0x8d, 0x36, 0xe1, 0x5a, 0x8a, 0x31, + 0x37, 0x8c, 0x5c, 0xe7, 0x50, 0xeb, 0x3b, 0x80, 0x86, 0x3d, + 0xed, 0x56, 0x9e, 0x25, 0xf5, 0x4e, 0x48, 0xf3, 0x23, 0x98, + 0x2f, 0x94, 0x44, 0xff, 0xf9, 0x42, 0x92, 0x29, 0x1f, 0xa4, + 0x74, 0xcf, 0xc9, 0x72, 0xa2, 0x19, 0xae, 0x15, 0xc5, 0x7e, + 0x78, 0xc3, 0x13, 0xa8, 0x60, 0xdb, 0x0b, 0xb0, 0xb6, 0x0d, + 0xdd, 0x66, 0xd1, 0x6a, 0xba, 0x01, 0x07, 0xbc, 0x6c, 0xd7, + 0xdf, 0x64, 0xb4, 0x0f, 0x09, 0xb2, 0x62, 0xd9, 0x6e, 0xd5, + 0x05, 0xbe, 0xb8, 0x03, 0xd3, 0x68, 0xa0, 0x1b, 0xcb, 0x70, + 0x76, 0xcd, 0x1d, 0xa6, 0x11, 0xaa, 0x7a, 0xc1, 0xc7, 0x7c, + 0xac, 0x17, 0x21, 0x9a, 0x4a, 0xf1, 0xf7, 0x4c, 0x9c, 0x27, + 0x90, 0x2b, 0xfb, 0x40, 0x46, 0xfd, 0x2d, 0x96, 0x5e, 0xe5, + 0x35, 0x8e, 0x88, 0x33, 0xe3, 0x58, 0xef, 0x54, 0x84, 0x3f, + 0x39, 0x82, 0x52, 0xe9, 0x3e, 0x85, 0x55, 0xee, 0xe8, 0x53, + 0x83, 0x38, 0x8f, 0x34, 0xe4, 0x5f, 0x59, 0xe2, 0x32, 0x89, + 0x41, 0xfa, 0x2a, 0x91, 0x97, 0x2c, 0xfc, 0x47, 0xf0, 0x4b, + 0x9b, 0x20, 0x26, 0x9d, 0x4d, 0xf6, 0xc0, 0x7b, 0xab, 0x10, + 0x16, 0xad, 0x7d, 0xc6, 0x71, 0xca, 0x1a, 0xa1, 0xa7, 0x1c, + 0xcc, 0x77, 0xbf, 0x04, 0xd4, 0x6f, 0x69, 0xd2, 0x02, 0xb9, + 0x0e, 0xb5, 0x65, 0xde, 0xd8, 0x63, 0xb3, 0x08, 0x00, 0xbc, + 0x65, 0xd9, 0xca, 0x76, 0xaf, 0x13, 0x89, 0x35, 0xec, 0x50, + 0x43, 0xff, 0x26, 0x9a, 0x0f, 0xb3, 0x6a, 0xd6, 0xc5, 0x79, + 0xa0, 0x1c, 0x86, 0x3a, 0xe3, 0x5f, 0x4c, 0xf0, 0x29, 0x95, + 0x1e, 0xa2, 0x7b, 0xc7, 0xd4, 0x68, 0xb1, 0x0d, 0x97, 0x2b, + 0xf2, 0x4e, 0x5d, 0xe1, 0x38, 0x84, 0x11, 0xad, 0x74, 0xc8, + 0xdb, 0x67, 0xbe, 0x02, 0x98, 0x24, 0xfd, 0x41, 0x52, 0xee, + 0x37, 0x8b, 0x3c, 0x80, 0x59, 0xe5, 0xf6, 0x4a, 0x93, 0x2f, + 0xb5, 0x09, 0xd0, 0x6c, 0x7f, 0xc3, 0x1a, 0xa6, 0x33, 0x8f, + 0x56, 0xea, 0xf9, 0x45, 0x9c, 0x20, 0xba, 0x06, 0xdf, 0x63, + 0x70, 0xcc, 0x15, 0xa9, 0x22, 0x9e, 0x47, 0xfb, 0xe8, 0x54, + 0x8d, 0x31, 0xab, 0x17, 0xce, 0x72, 0x61, 0xdd, 0x04, 0xb8, + 0x2d, 0x91, 0x48, 0xf4, 0xe7, 0x5b, 0x82, 0x3e, 0xa4, 0x18, + 0xc1, 0x7d, 0x6e, 0xd2, 0x0b, 0xb7, 0x78, 0xc4, 0x1d, 0xa1, + 0xb2, 0x0e, 0xd7, 0x6b, 0xf1, 0x4d, 0x94, 0x28, 0x3b, 0x87, + 0x5e, 0xe2, 0x77, 0xcb, 0x12, 0xae, 0xbd, 0x01, 0xd8, 0x64, + 0xfe, 0x42, 0x9b, 0x27, 0x34, 0x88, 0x51, 0xed, 0x66, 0xda, + 0x03, 0xbf, 0xac, 0x10, 0xc9, 0x75, 0xef, 0x53, 0x8a, 0x36, + 0x25, 0x99, 0x40, 0xfc, 0x69, 0xd5, 0x0c, 0xb0, 0xa3, 0x1f, + 0xc6, 0x7a, 0xe0, 0x5c, 0x85, 0x39, 0x2a, 0x96, 0x4f, 0xf3, + 0x44, 0xf8, 0x21, 0x9d, 0x8e, 0x32, 0xeb, 0x57, 0xcd, 0x71, + 0xa8, 0x14, 0x07, 0xbb, 0x62, 0xde, 0x4b, 0xf7, 0x2e, 0x92, + 0x81, 0x3d, 0xe4, 0x58, 0xc2, 0x7e, 0xa7, 0x1b, 0x08, 0xb4, + 0x6d, 0xd1, 0x5a, 0xe6, 0x3f, 0x83, 0x90, 0x2c, 0xf5, 0x49, + 0xd3, 0x6f, 0xb6, 0x0a, 0x19, 0xa5, 0x7c, 0xc0, 0x55, 0xe9, + 0x30, 0x8c, 0x9f, 0x23, 0xfa, 0x46, 0xdc, 0x60, 0xb9, 0x05, + 0x16, 0xaa, 0x73, 0xcf, 0x00, 0xbd, 0x67, 0xda, 0xce, 0x73, + 0xa9, 0x14, 0x81, 0x3c, 0xe6, 0x5b, 0x4f, 0xf2, 0x28, 0x95, + 0x1f, 0xa2, 0x78, 0xc5, 0xd1, 0x6c, 0xb6, 0x0b, 0x9e, 0x23, + 0xf9, 0x44, 0x50, 0xed, 0x37, 0x8a, 0x3e, 0x83, 0x59, 0xe4, + 0xf0, 0x4d, 0x97, 0x2a, 0xbf, 0x02, 0xd8, 0x65, 0x71, 0xcc, + 0x16, 0xab, 0x21, 0x9c, 0x46, 0xfb, 0xef, 0x52, 0x88, 0x35, + 0xa0, 0x1d, 0xc7, 0x7a, 0x6e, 0xd3, 0x09, 0xb4, 0x7c, 0xc1, + 0x1b, 0xa6, 0xb2, 0x0f, 0xd5, 0x68, 0xfd, 0x40, 0x9a, 0x27, + 0x33, 0x8e, 0x54, 0xe9, 0x63, 0xde, 0x04, 0xb9, 0xad, 0x10, + 0xca, 0x77, 0xe2, 0x5f, 0x85, 0x38, 0x2c, 0x91, 0x4b, 0xf6, + 0x42, 0xff, 0x25, 0x98, 0x8c, 0x31, 0xeb, 0x56, 0xc3, 0x7e, + 0xa4, 0x19, 0x0d, 0xb0, 0x6a, 0xd7, 0x5d, 0xe0, 0x3a, 0x87, + 0x93, 0x2e, 0xf4, 0x49, 0xdc, 0x61, 0xbb, 0x06, 0x12, 0xaf, + 0x75, 0xc8, 0xf8, 0x45, 0x9f, 0x22, 0x36, 0x8b, 0x51, 0xec, + 0x79, 0xc4, 0x1e, 0xa3, 0xb7, 0x0a, 0xd0, 0x6d, 0xe7, 0x5a, + 0x80, 0x3d, 0x29, 0x94, 0x4e, 0xf3, 0x66, 0xdb, 0x01, 0xbc, + 0xa8, 0x15, 0xcf, 0x72, 0xc6, 0x7b, 0xa1, 0x1c, 0x08, 0xb5, + 0x6f, 0xd2, 0x47, 0xfa, 0x20, 0x9d, 0x89, 0x34, 0xee, 0x53, + 0xd9, 0x64, 0xbe, 0x03, 0x17, 0xaa, 0x70, 0xcd, 0x58, 0xe5, + 0x3f, 0x82, 0x96, 0x2b, 0xf1, 0x4c, 0x84, 0x39, 0xe3, 0x5e, + 0x4a, 0xf7, 0x2d, 0x90, 0x05, 0xb8, 0x62, 0xdf, 0xcb, 0x76, + 0xac, 0x11, 0x9b, 0x26, 0xfc, 0x41, 0x55, 0xe8, 0x32, 0x8f, + 0x1a, 0xa7, 0x7d, 0xc0, 0xd4, 0x69, 0xb3, 0x0e, 0xba, 0x07, + 0xdd, 0x60, 0x74, 0xc9, 0x13, 0xae, 0x3b, 0x86, 0x5c, 0xe1, + 0xf5, 0x48, 0x92, 0x2f, 0xa5, 0x18, 0xc2, 0x7f, 0x6b, 0xd6, + 0x0c, 0xb1, 0x24, 0x99, 0x43, 0xfe, 0xea, 0x57, 0x8d, 0x30, + 0x00, 0xbe, 0x61, 0xdf, 0xc2, 0x7c, 0xa3, 0x1d, 0x99, 0x27, + 0xf8, 0x46, 0x5b, 0xe5, 0x3a, 0x84, 0x2f, 0x91, 0x4e, 0xf0, + 0xed, 0x53, 0x8c, 0x32, 0xb6, 0x08, 0xd7, 0x69, 0x74, 0xca, + 0x15, 0xab, 0x5e, 0xe0, 0x3f, 0x81, 0x9c, 0x22, 0xfd, 0x43, + 0xc7, 0x79, 0xa6, 0x18, 0x05, 0xbb, 0x64, 0xda, 0x71, 0xcf, + 0x10, 0xae, 0xb3, 0x0d, 0xd2, 0x6c, 0xe8, 0x56, 0x89, 0x37, + 0x2a, 0x94, 0x4b, 0xf5, 0xbc, 0x02, 0xdd, 0x63, 0x7e, 0xc0, + 0x1f, 0xa1, 0x25, 0x9b, 0x44, 0xfa, 0xe7, 0x59, 0x86, 0x38, + 0x93, 0x2d, 0xf2, 0x4c, 0x51, 0xef, 0x30, 0x8e, 0x0a, 0xb4, + 0x6b, 0xd5, 0xc8, 0x76, 0xa9, 0x17, 0xe2, 0x5c, 0x83, 0x3d, + 0x20, 0x9e, 0x41, 0xff, 0x7b, 0xc5, 0x1a, 0xa4, 0xb9, 0x07, + 0xd8, 0x66, 0xcd, 0x73, 0xac, 0x12, 0x0f, 0xb1, 0x6e, 0xd0, + 0x54, 0xea, 0x35, 0x8b, 0x96, 0x28, 0xf7, 0x49, 0x65, 0xdb, + 0x04, 0xba, 0xa7, 0x19, 0xc6, 0x78, 0xfc, 0x42, 0x9d, 0x23, + 0x3e, 0x80, 0x5f, 0xe1, 0x4a, 0xf4, 0x2b, 0x95, 0x88, 0x36, + 0xe9, 0x57, 0xd3, 0x6d, 0xb2, 0x0c, 0x11, 0xaf, 0x70, 0xce, + 0x3b, 0x85, 0x5a, 0xe4, 0xf9, 0x47, 0x98, 0x26, 0xa2, 0x1c, + 0xc3, 0x7d, 0x60, 0xde, 0x01, 0xbf, 0x14, 0xaa, 0x75, 0xcb, + 0xd6, 0x68, 0xb7, 0x09, 0x8d, 0x33, 0xec, 0x52, 0x4f, 0xf1, + 0x2e, 0x90, 0xd9, 0x67, 0xb8, 0x06, 0x1b, 0xa5, 0x7a, 0xc4, + 0x40, 0xfe, 0x21, 0x9f, 0x82, 0x3c, 0xe3, 0x5d, 0xf6, 0x48, + 0x97, 0x29, 0x34, 0x8a, 0x55, 0xeb, 0x6f, 0xd1, 0x0e, 0xb0, + 0xad, 0x13, 0xcc, 0x72, 0x87, 0x39, 0xe6, 0x58, 0x45, 0xfb, + 0x24, 0x9a, 0x1e, 0xa0, 0x7f, 0xc1, 0xdc, 0x62, 0xbd, 0x03, + 0xa8, 0x16, 0xc9, 0x77, 0x6a, 0xd4, 0x0b, 0xb5, 0x31, 0x8f, + 0x50, 0xee, 0xf3, 0x4d, 0x92, 0x2c, 0x00, 0xbf, 0x63, 0xdc, + 0xc6, 0x79, 0xa5, 0x1a, 0x91, 0x2e, 0xf2, 0x4d, 0x57, 0xe8, + 0x34, 0x8b, 0x3f, 0x80, 0x5c, 0xe3, 0xf9, 0x46, 0x9a, 0x25, + 0xae, 0x11, 0xcd, 0x72, 0x68, 0xd7, 0x0b, 0xb4, 0x7e, 0xc1, + 0x1d, 0xa2, 0xb8, 0x07, 0xdb, 0x64, 0xef, 0x50, 0x8c, 0x33, + 0x29, 0x96, 0x4a, 0xf5, 0x41, 0xfe, 0x22, 0x9d, 0x87, 0x38, + 0xe4, 0x5b, 0xd0, 0x6f, 0xb3, 0x0c, 0x16, 0xa9, 0x75, 0xca, + 0xfc, 0x43, 0x9f, 0x20, 0x3a, 0x85, 0x59, 0xe6, 0x6d, 0xd2, + 0x0e, 0xb1, 0xab, 0x14, 0xc8, 0x77, 0xc3, 0x7c, 0xa0, 0x1f, + 0x05, 0xba, 0x66, 0xd9, 0x52, 0xed, 0x31, 0x8e, 0x94, 0x2b, + 0xf7, 0x48, 0x82, 0x3d, 0xe1, 0x5e, 0x44, 0xfb, 0x27, 0x98, + 0x13, 0xac, 0x70, 0xcf, 0xd5, 0x6a, 0xb6, 0x09, 0xbd, 0x02, + 0xde, 0x61, 0x7b, 0xc4, 0x18, 0xa7, 0x2c, 0x93, 0x4f, 0xf0, + 0xea, 0x55, 0x89, 0x36, 0xe5, 0x5a, 0x86, 0x39, 0x23, 0x9c, + 0x40, 0xff, 0x74, 0xcb, 0x17, 0xa8, 0xb2, 0x0d, 0xd1, 0x6e, + 0xda, 0x65, 0xb9, 0x06, 0x1c, 0xa3, 0x7f, 0xc0, 0x4b, 0xf4, + 0x28, 0x97, 0x8d, 0x32, 0xee, 0x51, 0x9b, 0x24, 0xf8, 0x47, + 0x5d, 0xe2, 0x3e, 0x81, 0x0a, 0xb5, 0x69, 0xd6, 0xcc, 0x73, + 0xaf, 0x10, 0xa4, 0x1b, 0xc7, 0x78, 0x62, 0xdd, 0x01, 0xbe, + 0x35, 0x8a, 0x56, 0xe9, 0xf3, 0x4c, 0x90, 0x2f, 0x19, 0xa6, + 0x7a, 0xc5, 0xdf, 0x60, 0xbc, 0x03, 0x88, 0x37, 0xeb, 0x54, + 0x4e, 0xf1, 0x2d, 0x92, 0x26, 0x99, 0x45, 0xfa, 0xe0, 0x5f, + 0x83, 0x3c, 0xb7, 0x08, 0xd4, 0x6b, 0x71, 0xce, 0x12, 0xad, + 0x67, 0xd8, 0x04, 0xbb, 0xa1, 0x1e, 0xc2, 0x7d, 0xf6, 0x49, + 0x95, 0x2a, 0x30, 0x8f, 0x53, 0xec, 0x58, 0xe7, 0x3b, 0x84, + 0x9e, 0x21, 0xfd, 0x42, 0xc9, 0x76, 0xaa, 0x15, 0x0f, 0xb0, + 0x6c, 0xd3, 0x00, 0xc0, 0x9d, 0x5d, 0x27, 0xe7, 0xba, 0x7a, + 0x4e, 0x8e, 0xd3, 0x13, 0x69, 0xa9, 0xf4, 0x34, 0x9c, 0x5c, + 0x01, 0xc1, 0xbb, 0x7b, 0x26, 0xe6, 0xd2, 0x12, 0x4f, 0x8f, + 0xf5, 0x35, 0x68, 0xa8, 0x25, 0xe5, 0xb8, 0x78, 0x02, 0xc2, + 0x9f, 0x5f, 0x6b, 0xab, 0xf6, 0x36, 0x4c, 0x8c, 0xd1, 0x11, + 0xb9, 0x79, 0x24, 0xe4, 0x9e, 0x5e, 0x03, 0xc3, 0xf7, 0x37, + 0x6a, 0xaa, 0xd0, 0x10, 0x4d, 0x8d, 0x4a, 0x8a, 0xd7, 0x17, + 0x6d, 0xad, 0xf0, 0x30, 0x04, 0xc4, 0x99, 0x59, 0x23, 0xe3, + 0xbe, 0x7e, 0xd6, 0x16, 0x4b, 0x8b, 0xf1, 0x31, 0x6c, 0xac, + 0x98, 0x58, 0x05, 0xc5, 0xbf, 0x7f, 0x22, 0xe2, 0x6f, 0xaf, + 0xf2, 0x32, 0x48, 0x88, 0xd5, 0x15, 0x21, 0xe1, 0xbc, 0x7c, + 0x06, 0xc6, 0x9b, 0x5b, 0xf3, 0x33, 0x6e, 0xae, 0xd4, 0x14, + 0x49, 0x89, 0xbd, 0x7d, 0x20, 0xe0, 0x9a, 0x5a, 0x07, 0xc7, + 0x94, 0x54, 0x09, 0xc9, 0xb3, 0x73, 0x2e, 0xee, 0xda, 0x1a, + 0x47, 0x87, 0xfd, 0x3d, 0x60, 0xa0, 0x08, 0xc8, 0x95, 0x55, + 0x2f, 0xef, 0xb2, 0x72, 0x46, 0x86, 0xdb, 0x1b, 0x61, 0xa1, + 0xfc, 0x3c, 0xb1, 0x71, 0x2c, 0xec, 0x96, 0x56, 0x0b, 0xcb, + 0xff, 0x3f, 0x62, 0xa2, 0xd8, 0x18, 0x45, 0x85, 0x2d, 0xed, + 0xb0, 0x70, 0x0a, 0xca, 0x97, 0x57, 0x63, 0xa3, 0xfe, 0x3e, + 0x44, 0x84, 0xd9, 0x19, 0xde, 0x1e, 0x43, 0x83, 0xf9, 0x39, + 0x64, 0xa4, 0x90, 0x50, 0x0d, 0xcd, 0xb7, 0x77, 0x2a, 0xea, + 0x42, 0x82, 0xdf, 0x1f, 0x65, 0xa5, 0xf8, 0x38, 0x0c, 0xcc, + 0x91, 0x51, 0x2b, 0xeb, 0xb6, 0x76, 0xfb, 0x3b, 0x66, 0xa6, + 0xdc, 0x1c, 0x41, 0x81, 0xb5, 0x75, 0x28, 0xe8, 0x92, 0x52, + 0x0f, 0xcf, 0x67, 0xa7, 0xfa, 0x3a, 0x40, 0x80, 0xdd, 0x1d, + 0x29, 0xe9, 0xb4, 0x74, 0x0e, 0xce, 0x93, 0x53, 0x00, 0xc1, + 0x9f, 0x5e, 0x23, 0xe2, 0xbc, 0x7d, 0x46, 0x87, 0xd9, 0x18, + 0x65, 0xa4, 0xfa, 0x3b, 0x8c, 0x4d, 0x13, 0xd2, 0xaf, 0x6e, + 0x30, 0xf1, 0xca, 0x0b, 0x55, 0x94, 0xe9, 0x28, 0x76, 0xb7, + 0x05, 0xc4, 0x9a, 0x5b, 0x26, 0xe7, 0xb9, 0x78, 0x43, 0x82, + 0xdc, 0x1d, 0x60, 0xa1, 0xff, 0x3e, 0x89, 0x48, 0x16, 0xd7, + 0xaa, 0x6b, 0x35, 0xf4, 0xcf, 0x0e, 0x50, 0x91, 0xec, 0x2d, + 0x73, 0xb2, 0x0a, 0xcb, 0x95, 0x54, 0x29, 0xe8, 0xb6, 0x77, + 0x4c, 0x8d, 0xd3, 0x12, 0x6f, 0xae, 0xf0, 0x31, 0x86, 0x47, + 0x19, 0xd8, 0xa5, 0x64, 0x3a, 0xfb, 0xc0, 0x01, 0x5f, 0x9e, + 0xe3, 0x22, 0x7c, 0xbd, 0x0f, 0xce, 0x90, 0x51, 0x2c, 0xed, + 0xb3, 0x72, 0x49, 0x88, 0xd6, 0x17, 0x6a, 0xab, 0xf5, 0x34, + 0x83, 0x42, 0x1c, 0xdd, 0xa0, 0x61, 0x3f, 0xfe, 0xc5, 0x04, + 0x5a, 0x9b, 0xe6, 0x27, 0x79, 0xb8, 0x14, 0xd5, 0x8b, 0x4a, + 0x37, 0xf6, 0xa8, 0x69, 0x52, 0x93, 0xcd, 0x0c, 0x71, 0xb0, + 0xee, 0x2f, 0x98, 0x59, 0x07, 0xc6, 0xbb, 0x7a, 0x24, 0xe5, + 0xde, 0x1f, 0x41, 0x80, 0xfd, 0x3c, 0x62, 0xa3, 0x11, 0xd0, + 0x8e, 0x4f, 0x32, 0xf3, 0xad, 0x6c, 0x57, 0x96, 0xc8, 0x09, + 0x74, 0xb5, 0xeb, 0x2a, 0x9d, 0x5c, 0x02, 0xc3, 0xbe, 0x7f, + 0x21, 0xe0, 0xdb, 0x1a, 0x44, 0x85, 0xf8, 0x39, 0x67, 0xa6, + 0x1e, 0xdf, 0x81, 0x40, 0x3d, 0xfc, 0xa2, 0x63, 0x58, 0x99, + 0xc7, 0x06, 0x7b, 0xba, 0xe4, 0x25, 0x92, 0x53, 0x0d, 0xcc, + 0xb1, 0x70, 0x2e, 0xef, 0xd4, 0x15, 0x4b, 0x8a, 0xf7, 0x36, + 0x68, 0xa9, 0x1b, 0xda, 0x84, 0x45, 0x38, 0xf9, 0xa7, 0x66, + 0x5d, 0x9c, 0xc2, 0x03, 0x7e, 0xbf, 0xe1, 0x20, 0x97, 0x56, + 0x08, 0xc9, 0xb4, 0x75, 0x2b, 0xea, 0xd1, 0x10, 0x4e, 0x8f, + 0xf2, 0x33, 0x6d, 0xac, 0x00, 0xc2, 0x99, 0x5b, 0x2f, 0xed, + 0xb6, 0x74, 0x5e, 0x9c, 0xc7, 0x05, 0x71, 0xb3, 0xe8, 0x2a, + 0xbc, 0x7e, 0x25, 0xe7, 0x93, 0x51, 0x0a, 0xc8, 0xe2, 0x20, + 0x7b, 0xb9, 0xcd, 0x0f, 0x54, 0x96, 0x65, 0xa7, 0xfc, 0x3e, + 0x4a, 0x88, 0xd3, 0x11, 0x3b, 0xf9, 0xa2, 0x60, 0x14, 0xd6, + 0x8d, 0x4f, 0xd9, 0x1b, 0x40, 0x82, 0xf6, 0x34, 0x6f, 0xad, + 0x87, 0x45, 0x1e, 0xdc, 0xa8, 0x6a, 0x31, 0xf3, 0xca, 0x08, + 0x53, 0x91, 0xe5, 0x27, 0x7c, 0xbe, 0x94, 0x56, 0x0d, 0xcf, + 0xbb, 0x79, 0x22, 0xe0, 0x76, 0xb4, 0xef, 0x2d, 0x59, 0x9b, + 0xc0, 0x02, 0x28, 0xea, 0xb1, 0x73, 0x07, 0xc5, 0x9e, 0x5c, + 0xaf, 0x6d, 0x36, 0xf4, 0x80, 0x42, 0x19, 0xdb, 0xf1, 0x33, + 0x68, 0xaa, 0xde, 0x1c, 0x47, 0x85, 0x13, 0xd1, 0x8a, 0x48, + 0x3c, 0xfe, 0xa5, 0x67, 0x4d, 0x8f, 0xd4, 0x16, 0x62, 0xa0, + 0xfb, 0x39, 0x89, 0x4b, 0x10, 0xd2, 0xa6, 0x64, 0x3f, 0xfd, + 0xd7, 0x15, 0x4e, 0x8c, 0xf8, 0x3a, 0x61, 0xa3, 0x35, 0xf7, + 0xac, 0x6e, 0x1a, 0xd8, 0x83, 0x41, 0x6b, 0xa9, 0xf2, 0x30, + 0x44, 0x86, 0xdd, 0x1f, 0xec, 0x2e, 0x75, 0xb7, 0xc3, 0x01, + 0x5a, 0x98, 0xb2, 0x70, 0x2b, 0xe9, 0x9d, 0x5f, 0x04, 0xc6, + 0x50, 0x92, 0xc9, 0x0b, 0x7f, 0xbd, 0xe6, 0x24, 0x0e, 0xcc, + 0x97, 0x55, 0x21, 0xe3, 0xb8, 0x7a, 0x43, 0x81, 0xda, 0x18, + 0x6c, 0xae, 0xf5, 0x37, 0x1d, 0xdf, 0x84, 0x46, 0x32, 0xf0, + 0xab, 0x69, 0xff, 0x3d, 0x66, 0xa4, 0xd0, 0x12, 0x49, 0x8b, + 0xa1, 0x63, 0x38, 0xfa, 0x8e, 0x4c, 0x17, 0xd5, 0x26, 0xe4, + 0xbf, 0x7d, 0x09, 0xcb, 0x90, 0x52, 0x78, 0xba, 0xe1, 0x23, + 0x57, 0x95, 0xce, 0x0c, 0x9a, 0x58, 0x03, 0xc1, 0xb5, 0x77, + 0x2c, 0xee, 0xc4, 0x06, 0x5d, 0x9f, 0xeb, 0x29, 0x72, 0xb0, + 0x00, 0xc3, 0x9b, 0x58, 0x2b, 0xe8, 0xb0, 0x73, 0x56, 0x95, + 0xcd, 0x0e, 0x7d, 0xbe, 0xe6, 0x25, 0xac, 0x6f, 0x37, 0xf4, + 0x87, 0x44, 0x1c, 0xdf, 0xfa, 0x39, 0x61, 0xa2, 0xd1, 0x12, + 0x4a, 0x89, 0x45, 0x86, 0xde, 0x1d, 0x6e, 0xad, 0xf5, 0x36, + 0x13, 0xd0, 0x88, 0x4b, 0x38, 0xfb, 0xa3, 0x60, 0xe9, 0x2a, + 0x72, 0xb1, 0xc2, 0x01, 0x59, 0x9a, 0xbf, 0x7c, 0x24, 0xe7, + 0x94, 0x57, 0x0f, 0xcc, 0x8a, 0x49, 0x11, 0xd2, 0xa1, 0x62, + 0x3a, 0xf9, 0xdc, 0x1f, 0x47, 0x84, 0xf7, 0x34, 0x6c, 0xaf, + 0x26, 0xe5, 0xbd, 0x7e, 0x0d, 0xce, 0x96, 0x55, 0x70, 0xb3, + 0xeb, 0x28, 0x5b, 0x98, 0xc0, 0x03, 0xcf, 0x0c, 0x54, 0x97, + 0xe4, 0x27, 0x7f, 0xbc, 0x99, 0x5a, 0x02, 0xc1, 0xb2, 0x71, + 0x29, 0xea, 0x63, 0xa0, 0xf8, 0x3b, 0x48, 0x8b, 0xd3, 0x10, + 0x35, 0xf6, 0xae, 0x6d, 0x1e, 0xdd, 0x85, 0x46, 0x09, 0xca, + 0x92, 0x51, 0x22, 0xe1, 0xb9, 0x7a, 0x5f, 0x9c, 0xc4, 0x07, + 0x74, 0xb7, 0xef, 0x2c, 0xa5, 0x66, 0x3e, 0xfd, 0x8e, 0x4d, + 0x15, 0xd6, 0xf3, 0x30, 0x68, 0xab, 0xd8, 0x1b, 0x43, 0x80, + 0x4c, 0x8f, 0xd7, 0x14, 0x67, 0xa4, 0xfc, 0x3f, 0x1a, 0xd9, + 0x81, 0x42, 0x31, 0xf2, 0xaa, 0x69, 0xe0, 0x23, 0x7b, 0xb8, + 0xcb, 0x08, 0x50, 0x93, 0xb6, 0x75, 0x2d, 0xee, 0x9d, 0x5e, + 0x06, 0xc5, 0x83, 0x40, 0x18, 0xdb, 0xa8, 0x6b, 0x33, 0xf0, + 0xd5, 0x16, 0x4e, 0x8d, 0xfe, 0x3d, 0x65, 0xa6, 0x2f, 0xec, + 0xb4, 0x77, 0x04, 0xc7, 0x9f, 0x5c, 0x79, 0xba, 0xe2, 0x21, + 0x52, 0x91, 0xc9, 0x0a, 0xc6, 0x05, 0x5d, 0x9e, 0xed, 0x2e, + 0x76, 0xb5, 0x90, 0x53, 0x0b, 0xc8, 0xbb, 0x78, 0x20, 0xe3, + 0x6a, 0xa9, 0xf1, 0x32, 0x41, 0x82, 0xda, 0x19, 0x3c, 0xff, + 0xa7, 0x64, 0x17, 0xd4, 0x8c, 0x4f, 0x00, 0xc4, 0x95, 0x51, + 0x37, 0xf3, 0xa2, 0x66, 0x6e, 0xaa, 0xfb, 0x3f, 0x59, 0x9d, + 0xcc, 0x08, 0xdc, 0x18, 0x49, 0x8d, 0xeb, 0x2f, 0x7e, 0xba, + 0xb2, 0x76, 0x27, 0xe3, 0x85, 0x41, 0x10, 0xd4, 0xa5, 0x61, + 0x30, 0xf4, 0x92, 0x56, 0x07, 0xc3, 0xcb, 0x0f, 0x5e, 0x9a, + 0xfc, 0x38, 0x69, 0xad, 0x79, 0xbd, 0xec, 0x28, 0x4e, 0x8a, + 0xdb, 0x1f, 0x17, 0xd3, 0x82, 0x46, 0x20, 0xe4, 0xb5, 0x71, + 0x57, 0x93, 0xc2, 0x06, 0x60, 0xa4, 0xf5, 0x31, 0x39, 0xfd, + 0xac, 0x68, 0x0e, 0xca, 0x9b, 0x5f, 0x8b, 0x4f, 0x1e, 0xda, + 0xbc, 0x78, 0x29, 0xed, 0xe5, 0x21, 0x70, 0xb4, 0xd2, 0x16, + 0x47, 0x83, 0xf2, 0x36, 0x67, 0xa3, 0xc5, 0x01, 0x50, 0x94, + 0x9c, 0x58, 0x09, 0xcd, 0xab, 0x6f, 0x3e, 0xfa, 0x2e, 0xea, + 0xbb, 0x7f, 0x19, 0xdd, 0x8c, 0x48, 0x40, 0x84, 0xd5, 0x11, + 0x77, 0xb3, 0xe2, 0x26, 0xae, 0x6a, 0x3b, 0xff, 0x99, 0x5d, + 0x0c, 0xc8, 0xc0, 0x04, 0x55, 0x91, 0xf7, 0x33, 0x62, 0xa6, + 0x72, 0xb6, 0xe7, 0x23, 0x45, 0x81, 0xd0, 0x14, 0x1c, 0xd8, + 0x89, 0x4d, 0x2b, 0xef, 0xbe, 0x7a, 0x0b, 0xcf, 0x9e, 0x5a, + 0x3c, 0xf8, 0xa9, 0x6d, 0x65, 0xa1, 0xf0, 0x34, 0x52, 0x96, + 0xc7, 0x03, 0xd7, 0x13, 0x42, 0x86, 0xe0, 0x24, 0x75, 0xb1, + 0xb9, 0x7d, 0x2c, 0xe8, 0x8e, 0x4a, 0x1b, 0xdf, 0xf9, 0x3d, + 0x6c, 0xa8, 0xce, 0x0a, 0x5b, 0x9f, 0x97, 0x53, 0x02, 0xc6, + 0xa0, 0x64, 0x35, 0xf1, 0x25, 0xe1, 0xb0, 0x74, 0x12, 0xd6, + 0x87, 0x43, 0x4b, 0x8f, 0xde, 0x1a, 0x7c, 0xb8, 0xe9, 0x2d, + 0x5c, 0x98, 0xc9, 0x0d, 0x6b, 0xaf, 0xfe, 0x3a, 0x32, 0xf6, + 0xa7, 0x63, 0x05, 0xc1, 0x90, 0x54, 0x80, 0x44, 0x15, 0xd1, + 0xb7, 0x73, 0x22, 0xe6, 0xee, 0x2a, 0x7b, 0xbf, 0xd9, 0x1d, + 0x4c, 0x88, 0x00, 0xc5, 0x97, 0x52, 0x33, 0xf6, 0xa4, 0x61, + 0x66, 0xa3, 0xf1, 0x34, 0x55, 0x90, 0xc2, 0x07, 0xcc, 0x09, + 0x5b, 0x9e, 0xff, 0x3a, 0x68, 0xad, 0xaa, 0x6f, 0x3d, 0xf8, + 0x99, 0x5c, 0x0e, 0xcb, 0x85, 0x40, 0x12, 0xd7, 0xb6, 0x73, + 0x21, 0xe4, 0xe3, 0x26, 0x74, 0xb1, 0xd0, 0x15, 0x47, 0x82, + 0x49, 0x8c, 0xde, 0x1b, 0x7a, 0xbf, 0xed, 0x28, 0x2f, 0xea, + 0xb8, 0x7d, 0x1c, 0xd9, 0x8b, 0x4e, 0x17, 0xd2, 0x80, 0x45, + 0x24, 0xe1, 0xb3, 0x76, 0x71, 0xb4, 0xe6, 0x23, 0x42, 0x87, + 0xd5, 0x10, 0xdb, 0x1e, 0x4c, 0x89, 0xe8, 0x2d, 0x7f, 0xba, + 0xbd, 0x78, 0x2a, 0xef, 0x8e, 0x4b, 0x19, 0xdc, 0x92, 0x57, + 0x05, 0xc0, 0xa1, 0x64, 0x36, 0xf3, 0xf4, 0x31, 0x63, 0xa6, + 0xc7, 0x02, 0x50, 0x95, 0x5e, 0x9b, 0xc9, 0x0c, 0x6d, 0xa8, + 0xfa, 0x3f, 0x38, 0xfd, 0xaf, 0x6a, 0x0b, 0xce, 0x9c, 0x59, + 0x2e, 0xeb, 0xb9, 0x7c, 0x1d, 0xd8, 0x8a, 0x4f, 0x48, 0x8d, + 0xdf, 0x1a, 0x7b, 0xbe, 0xec, 0x29, 0xe2, 0x27, 0x75, 0xb0, + 0xd1, 0x14, 0x46, 0x83, 0x84, 0x41, 0x13, 0xd6, 0xb7, 0x72, + 0x20, 0xe5, 0xab, 0x6e, 0x3c, 0xf9, 0x98, 0x5d, 0x0f, 0xca, + 0xcd, 0x08, 0x5a, 0x9f, 0xfe, 0x3b, 0x69, 0xac, 0x67, 0xa2, + 0xf0, 0x35, 0x54, 0x91, 0xc3, 0x06, 0x01, 0xc4, 0x96, 0x53, + 0x32, 0xf7, 0xa5, 0x60, 0x39, 0xfc, 0xae, 0x6b, 0x0a, 0xcf, + 0x9d, 0x58, 0x5f, 0x9a, 0xc8, 0x0d, 0x6c, 0xa9, 0xfb, 0x3e, + 0xf5, 0x30, 0x62, 0xa7, 0xc6, 0x03, 0x51, 0x94, 0x93, 0x56, + 0x04, 0xc1, 0xa0, 0x65, 0x37, 0xf2, 0xbc, 0x79, 0x2b, 0xee, + 0x8f, 0x4a, 0x18, 0xdd, 0xda, 0x1f, 0x4d, 0x88, 0xe9, 0x2c, + 0x7e, 0xbb, 0x70, 0xb5, 0xe7, 0x22, 0x43, 0x86, 0xd4, 0x11, + 0x16, 0xd3, 0x81, 0x44, 0x25, 0xe0, 0xb2, 0x77, 0x00, 0xc6, + 0x91, 0x57, 0x3f, 0xf9, 0xae, 0x68, 0x7e, 0xb8, 0xef, 0x29, + 0x41, 0x87, 0xd0, 0x16, 0xfc, 0x3a, 0x6d, 0xab, 0xc3, 0x05, + 0x52, 0x94, 0x82, 0x44, 0x13, 0xd5, 0xbd, 0x7b, 0x2c, 0xea, + 0xe5, 0x23, 0x74, 0xb2, 0xda, 0x1c, 0x4b, 0x8d, 0x9b, 0x5d, + 0x0a, 0xcc, 0xa4, 0x62, 0x35, 0xf3, 0x19, 0xdf, 0x88, 0x4e, + 0x26, 0xe0, 0xb7, 0x71, 0x67, 0xa1, 0xf6, 0x30, 0x58, 0x9e, + 0xc9, 0x0f, 0xd7, 0x11, 0x46, 0x80, 0xe8, 0x2e, 0x79, 0xbf, + 0xa9, 0x6f, 0x38, 0xfe, 0x96, 0x50, 0x07, 0xc1, 0x2b, 0xed, + 0xba, 0x7c, 0x14, 0xd2, 0x85, 0x43, 0x55, 0x93, 0xc4, 0x02, + 0x6a, 0xac, 0xfb, 0x3d, 0x32, 0xf4, 0xa3, 0x65, 0x0d, 0xcb, + 0x9c, 0x5a, 0x4c, 0x8a, 0xdd, 0x1b, 0x73, 0xb5, 0xe2, 0x24, + 0xce, 0x08, 0x5f, 0x99, 0xf1, 0x37, 0x60, 0xa6, 0xb0, 0x76, + 0x21, 0xe7, 0x8f, 0x49, 0x1e, 0xd8, 0xb3, 0x75, 0x22, 0xe4, + 0x8c, 0x4a, 0x1d, 0xdb, 0xcd, 0x0b, 0x5c, 0x9a, 0xf2, 0x34, + 0x63, 0xa5, 0x4f, 0x89, 0xde, 0x18, 0x70, 0xb6, 0xe1, 0x27, + 0x31, 0xf7, 0xa0, 0x66, 0x0e, 0xc8, 0x9f, 0x59, 0x56, 0x90, + 0xc7, 0x01, 0x69, 0xaf, 0xf8, 0x3e, 0x28, 0xee, 0xb9, 0x7f, + 0x17, 0xd1, 0x86, 0x40, 0xaa, 0x6c, 0x3b, 0xfd, 0x95, 0x53, + 0x04, 0xc2, 0xd4, 0x12, 0x45, 0x83, 0xeb, 0x2d, 0x7a, 0xbc, + 0x64, 0xa2, 0xf5, 0x33, 0x5b, 0x9d, 0xca, 0x0c, 0x1a, 0xdc, + 0x8b, 0x4d, 0x25, 0xe3, 0xb4, 0x72, 0x98, 0x5e, 0x09, 0xcf, + 0xa7, 0x61, 0x36, 0xf0, 0xe6, 0x20, 0x77, 0xb1, 0xd9, 0x1f, + 0x48, 0x8e, 0x81, 0x47, 0x10, 0xd6, 0xbe, 0x78, 0x2f, 0xe9, + 0xff, 0x39, 0x6e, 0xa8, 0xc0, 0x06, 0x51, 0x97, 0x7d, 0xbb, + 0xec, 0x2a, 0x42, 0x84, 0xd3, 0x15, 0x03, 0xc5, 0x92, 0x54, + 0x3c, 0xfa, 0xad, 0x6b, 0x00, 0xc7, 0x93, 0x54, 0x3b, 0xfc, + 0xa8, 0x6f, 0x76, 0xb1, 0xe5, 0x22, 0x4d, 0x8a, 0xde, 0x19, + 0xec, 0x2b, 0x7f, 0xb8, 0xd7, 0x10, 0x44, 0x83, 0x9a, 0x5d, + 0x09, 0xce, 0xa1, 0x66, 0x32, 0xf5, 0xc5, 0x02, 0x56, 0x91, + 0xfe, 0x39, 0x6d, 0xaa, 0xb3, 0x74, 0x20, 0xe7, 0x88, 0x4f, + 0x1b, 0xdc, 0x29, 0xee, 0xba, 0x7d, 0x12, 0xd5, 0x81, 0x46, + 0x5f, 0x98, 0xcc, 0x0b, 0x64, 0xa3, 0xf7, 0x30, 0x97, 0x50, + 0x04, 0xc3, 0xac, 0x6b, 0x3f, 0xf8, 0xe1, 0x26, 0x72, 0xb5, + 0xda, 0x1d, 0x49, 0x8e, 0x7b, 0xbc, 0xe8, 0x2f, 0x40, 0x87, + 0xd3, 0x14, 0x0d, 0xca, 0x9e, 0x59, 0x36, 0xf1, 0xa5, 0x62, + 0x52, 0x95, 0xc1, 0x06, 0x69, 0xae, 0xfa, 0x3d, 0x24, 0xe3, + 0xb7, 0x70, 0x1f, 0xd8, 0x8c, 0x4b, 0xbe, 0x79, 0x2d, 0xea, + 0x85, 0x42, 0x16, 0xd1, 0xc8, 0x0f, 0x5b, 0x9c, 0xf3, 0x34, + 0x60, 0xa7, 0x33, 0xf4, 0xa0, 0x67, 0x08, 0xcf, 0x9b, 0x5c, + 0x45, 0x82, 0xd6, 0x11, 0x7e, 0xb9, 0xed, 0x2a, 0xdf, 0x18, + 0x4c, 0x8b, 0xe4, 0x23, 0x77, 0xb0, 0xa9, 0x6e, 0x3a, 0xfd, + 0x92, 0x55, 0x01, 0xc6, 0xf6, 0x31, 0x65, 0xa2, 0xcd, 0x0a, + 0x5e, 0x99, 0x80, 0x47, 0x13, 0xd4, 0xbb, 0x7c, 0x28, 0xef, + 0x1a, 0xdd, 0x89, 0x4e, 0x21, 0xe6, 0xb2, 0x75, 0x6c, 0xab, + 0xff, 0x38, 0x57, 0x90, 0xc4, 0x03, 0xa4, 0x63, 0x37, 0xf0, + 0x9f, 0x58, 0x0c, 0xcb, 0xd2, 0x15, 0x41, 0x86, 0xe9, 0x2e, + 0x7a, 0xbd, 0x48, 0x8f, 0xdb, 0x1c, 0x73, 0xb4, 0xe0, 0x27, + 0x3e, 0xf9, 0xad, 0x6a, 0x05, 0xc2, 0x96, 0x51, 0x61, 0xa6, + 0xf2, 0x35, 0x5a, 0x9d, 0xc9, 0x0e, 0x17, 0xd0, 0x84, 0x43, + 0x2c, 0xeb, 0xbf, 0x78, 0x8d, 0x4a, 0x1e, 0xd9, 0xb6, 0x71, + 0x25, 0xe2, 0xfb, 0x3c, 0x68, 0xaf, 0xc0, 0x07, 0x53, 0x94, + 0x00, 0xc8, 0x8d, 0x45, 0x07, 0xcf, 0x8a, 0x42, 0x0e, 0xc6, + 0x83, 0x4b, 0x09, 0xc1, 0x84, 0x4c, 0x1c, 0xd4, 0x91, 0x59, + 0x1b, 0xd3, 0x96, 0x5e, 0x12, 0xda, 0x9f, 0x57, 0x15, 0xdd, + 0x98, 0x50, 0x38, 0xf0, 0xb5, 0x7d, 0x3f, 0xf7, 0xb2, 0x7a, + 0x36, 0xfe, 0xbb, 0x73, 0x31, 0xf9, 0xbc, 0x74, 0x24, 0xec, + 0xa9, 0x61, 0x23, 0xeb, 0xae, 0x66, 0x2a, 0xe2, 0xa7, 0x6f, + 0x2d, 0xe5, 0xa0, 0x68, 0x70, 0xb8, 0xfd, 0x35, 0x77, 0xbf, + 0xfa, 0x32, 0x7e, 0xb6, 0xf3, 0x3b, 0x79, 0xb1, 0xf4, 0x3c, + 0x6c, 0xa4, 0xe1, 0x29, 0x6b, 0xa3, 0xe6, 0x2e, 0x62, 0xaa, + 0xef, 0x27, 0x65, 0xad, 0xe8, 0x20, 0x48, 0x80, 0xc5, 0x0d, + 0x4f, 0x87, 0xc2, 0x0a, 0x46, 0x8e, 0xcb, 0x03, 0x41, 0x89, + 0xcc, 0x04, 0x54, 0x9c, 0xd9, 0x11, 0x53, 0x9b, 0xde, 0x16, + 0x5a, 0x92, 0xd7, 0x1f, 0x5d, 0x95, 0xd0, 0x18, 0xe0, 0x28, + 0x6d, 0xa5, 0xe7, 0x2f, 0x6a, 0xa2, 0xee, 0x26, 0x63, 0xab, + 0xe9, 0x21, 0x64, 0xac, 0xfc, 0x34, 0x71, 0xb9, 0xfb, 0x33, + 0x76, 0xbe, 0xf2, 0x3a, 0x7f, 0xb7, 0xf5, 0x3d, 0x78, 0xb0, + 0xd8, 0x10, 0x55, 0x9d, 0xdf, 0x17, 0x52, 0x9a, 0xd6, 0x1e, + 0x5b, 0x93, 0xd1, 0x19, 0x5c, 0x94, 0xc4, 0x0c, 0x49, 0x81, + 0xc3, 0x0b, 0x4e, 0x86, 0xca, 0x02, 0x47, 0x8f, 0xcd, 0x05, + 0x40, 0x88, 0x90, 0x58, 0x1d, 0xd5, 0x97, 0x5f, 0x1a, 0xd2, + 0x9e, 0x56, 0x13, 0xdb, 0x99, 0x51, 0x14, 0xdc, 0x8c, 0x44, + 0x01, 0xc9, 0x8b, 0x43, 0x06, 0xce, 0x82, 0x4a, 0x0f, 0xc7, + 0x85, 0x4d, 0x08, 0xc0, 0xa8, 0x60, 0x25, 0xed, 0xaf, 0x67, + 0x22, 0xea, 0xa6, 0x6e, 0x2b, 0xe3, 0xa1, 0x69, 0x2c, 0xe4, + 0xb4, 0x7c, 0x39, 0xf1, 0xb3, 0x7b, 0x3e, 0xf6, 0xba, 0x72, + 0x37, 0xff, 0xbd, 0x75, 0x30, 0xf8, 0x00, 0xc9, 0x8f, 0x46, + 0x03, 0xca, 0x8c, 0x45, 0x06, 0xcf, 0x89, 0x40, 0x05, 0xcc, + 0x8a, 0x43, 0x0c, 0xc5, 0x83, 0x4a, 0x0f, 0xc6, 0x80, 0x49, + 0x0a, 0xc3, 0x85, 0x4c, 0x09, 0xc0, 0x86, 0x4f, 0x18, 0xd1, + 0x97, 0x5e, 0x1b, 0xd2, 0x94, 0x5d, 0x1e, 0xd7, 0x91, 0x58, + 0x1d, 0xd4, 0x92, 0x5b, 0x14, 0xdd, 0x9b, 0x52, 0x17, 0xde, + 0x98, 0x51, 0x12, 0xdb, 0x9d, 0x54, 0x11, 0xd8, 0x9e, 0x57, + 0x30, 0xf9, 0xbf, 0x76, 0x33, 0xfa, 0xbc, 0x75, 0x36, 0xff, + 0xb9, 0x70, 0x35, 0xfc, 0xba, 0x73, 0x3c, 0xf5, 0xb3, 0x7a, + 0x3f, 0xf6, 0xb0, 0x79, 0x3a, 0xf3, 0xb5, 0x7c, 0x39, 0xf0, + 0xb6, 0x7f, 0x28, 0xe1, 0xa7, 0x6e, 0x2b, 0xe2, 0xa4, 0x6d, + 0x2e, 0xe7, 0xa1, 0x68, 0x2d, 0xe4, 0xa2, 0x6b, 0x24, 0xed, + 0xab, 0x62, 0x27, 0xee, 0xa8, 0x61, 0x22, 0xeb, 0xad, 0x64, + 0x21, 0xe8, 0xae, 0x67, 0x60, 0xa9, 0xef, 0x26, 0x63, 0xaa, + 0xec, 0x25, 0x66, 0xaf, 0xe9, 0x20, 0x65, 0xac, 0xea, 0x23, + 0x6c, 0xa5, 0xe3, 0x2a, 0x6f, 0xa6, 0xe0, 0x29, 0x6a, 0xa3, + 0xe5, 0x2c, 0x69, 0xa0, 0xe6, 0x2f, 0x78, 0xb1, 0xf7, 0x3e, + 0x7b, 0xb2, 0xf4, 0x3d, 0x7e, 0xb7, 0xf1, 0x38, 0x7d, 0xb4, + 0xf2, 0x3b, 0x74, 0xbd, 0xfb, 0x32, 0x77, 0xbe, 0xf8, 0x31, + 0x72, 0xbb, 0xfd, 0x34, 0x71, 0xb8, 0xfe, 0x37, 0x50, 0x99, + 0xdf, 0x16, 0x53, 0x9a, 0xdc, 0x15, 0x56, 0x9f, 0xd9, 0x10, + 0x55, 0x9c, 0xda, 0x13, 0x5c, 0x95, 0xd3, 0x1a, 0x5f, 0x96, + 0xd0, 0x19, 0x5a, 0x93, 0xd5, 0x1c, 0x59, 0x90, 0xd6, 0x1f, + 0x48, 0x81, 0xc7, 0x0e, 0x4b, 0x82, 0xc4, 0x0d, 0x4e, 0x87, + 0xc1, 0x08, 0x4d, 0x84, 0xc2, 0x0b, 0x44, 0x8d, 0xcb, 0x02, + 0x47, 0x8e, 0xc8, 0x01, 0x42, 0x8b, 0xcd, 0x04, 0x41, 0x88, + 0xce, 0x07, 0x00, 0xca, 0x89, 0x43, 0x0f, 0xc5, 0x86, 0x4c, + 0x1e, 0xd4, 0x97, 0x5d, 0x11, 0xdb, 0x98, 0x52, 0x3c, 0xf6, + 0xb5, 0x7f, 0x33, 0xf9, 0xba, 0x70, 0x22, 0xe8, 0xab, 0x61, + 0x2d, 0xe7, 0xa4, 0x6e, 0x78, 0xb2, 0xf1, 0x3b, 0x77, 0xbd, + 0xfe, 0x34, 0x66, 0xac, 0xef, 0x25, 0x69, 0xa3, 0xe0, 0x2a, + 0x44, 0x8e, 0xcd, 0x07, 0x4b, 0x81, 0xc2, 0x08, 0x5a, 0x90, + 0xd3, 0x19, 0x55, 0x9f, 0xdc, 0x16, 0xf0, 0x3a, 0x79, 0xb3, + 0xff, 0x35, 0x76, 0xbc, 0xee, 0x24, 0x67, 0xad, 0xe1, 0x2b, + 0x68, 0xa2, 0xcc, 0x06, 0x45, 0x8f, 0xc3, 0x09, 0x4a, 0x80, + 0xd2, 0x18, 0x5b, 0x91, 0xdd, 0x17, 0x54, 0x9e, 0x88, 0x42, + 0x01, 0xcb, 0x87, 0x4d, 0x0e, 0xc4, 0x96, 0x5c, 0x1f, 0xd5, + 0x99, 0x53, 0x10, 0xda, 0xb4, 0x7e, 0x3d, 0xf7, 0xbb, 0x71, + 0x32, 0xf8, 0xaa, 0x60, 0x23, 0xe9, 0xa5, 0x6f, 0x2c, 0xe6, + 0xfd, 0x37, 0x74, 0xbe, 0xf2, 0x38, 0x7b, 0xb1, 0xe3, 0x29, + 0x6a, 0xa0, 0xec, 0x26, 0x65, 0xaf, 0xc1, 0x0b, 0x48, 0x82, + 0xce, 0x04, 0x47, 0x8d, 0xdf, 0x15, 0x56, 0x9c, 0xd0, 0x1a, + 0x59, 0x93, 0x85, 0x4f, 0x0c, 0xc6, 0x8a, 0x40, 0x03, 0xc9, + 0x9b, 0x51, 0x12, 0xd8, 0x94, 0x5e, 0x1d, 0xd7, 0xb9, 0x73, + 0x30, 0xfa, 0xb6, 0x7c, 0x3f, 0xf5, 0xa7, 0x6d, 0x2e, 0xe4, + 0xa8, 0x62, 0x21, 0xeb, 0x0d, 0xc7, 0x84, 0x4e, 0x02, 0xc8, + 0x8b, 0x41, 0x13, 0xd9, 0x9a, 0x50, 0x1c, 0xd6, 0x95, 0x5f, + 0x31, 0xfb, 0xb8, 0x72, 0x3e, 0xf4, 0xb7, 0x7d, 0x2f, 0xe5, + 0xa6, 0x6c, 0x20, 0xea, 0xa9, 0x63, 0x75, 0xbf, 0xfc, 0x36, + 0x7a, 0xb0, 0xf3, 0x39, 0x6b, 0xa1, 0xe2, 0x28, 0x64, 0xae, + 0xed, 0x27, 0x49, 0x83, 0xc0, 0x0a, 0x46, 0x8c, 0xcf, 0x05, + 0x57, 0x9d, 0xde, 0x14, 0x58, 0x92, 0xd1, 0x1b, 0x00, 0xcb, + 0x8b, 0x40, 0x0b, 0xc0, 0x80, 0x4b, 0x16, 0xdd, 0x9d, 0x56, + 0x1d, 0xd6, 0x96, 0x5d, 0x2c, 0xe7, 0xa7, 0x6c, 0x27, 0xec, + 0xac, 0x67, 0x3a, 0xf1, 0xb1, 0x7a, 0x31, 0xfa, 0xba, 0x71, + 0x58, 0x93, 0xd3, 0x18, 0x53, 0x98, 0xd8, 0x13, 0x4e, 0x85, + 0xc5, 0x0e, 0x45, 0x8e, 0xce, 0x05, 0x74, 0xbf, 0xff, 0x34, + 0x7f, 0xb4, 0xf4, 0x3f, 0x62, 0xa9, 0xe9, 0x22, 0x69, 0xa2, + 0xe2, 0x29, 0xb0, 0x7b, 0x3b, 0xf0, 0xbb, 0x70, 0x30, 0xfb, + 0xa6, 0x6d, 0x2d, 0xe6, 0xad, 0x66, 0x26, 0xed, 0x9c, 0x57, + 0x17, 0xdc, 0x97, 0x5c, 0x1c, 0xd7, 0x8a, 0x41, 0x01, 0xca, + 0x81, 0x4a, 0x0a, 0xc1, 0xe8, 0x23, 0x63, 0xa8, 0xe3, 0x28, + 0x68, 0xa3, 0xfe, 0x35, 0x75, 0xbe, 0xf5, 0x3e, 0x7e, 0xb5, + 0xc4, 0x0f, 0x4f, 0x84, 0xcf, 0x04, 0x44, 0x8f, 0xd2, 0x19, + 0x59, 0x92, 0xd9, 0x12, 0x52, 0x99, 0x7d, 0xb6, 0xf6, 0x3d, + 0x76, 0xbd, 0xfd, 0x36, 0x6b, 0xa0, 0xe0, 0x2b, 0x60, 0xab, + 0xeb, 0x20, 0x51, 0x9a, 0xda, 0x11, 0x5a, 0x91, 0xd1, 0x1a, + 0x47, 0x8c, 0xcc, 0x07, 0x4c, 0x87, 0xc7, 0x0c, 0x25, 0xee, + 0xae, 0x65, 0x2e, 0xe5, 0xa5, 0x6e, 0x33, 0xf8, 0xb8, 0x73, + 0x38, 0xf3, 0xb3, 0x78, 0x09, 0xc2, 0x82, 0x49, 0x02, 0xc9, + 0x89, 0x42, 0x1f, 0xd4, 0x94, 0x5f, 0x14, 0xdf, 0x9f, 0x54, + 0xcd, 0x06, 0x46, 0x8d, 0xc6, 0x0d, 0x4d, 0x86, 0xdb, 0x10, + 0x50, 0x9b, 0xd0, 0x1b, 0x5b, 0x90, 0xe1, 0x2a, 0x6a, 0xa1, + 0xea, 0x21, 0x61, 0xaa, 0xf7, 0x3c, 0x7c, 0xb7, 0xfc, 0x37, + 0x77, 0xbc, 0x95, 0x5e, 0x1e, 0xd5, 0x9e, 0x55, 0x15, 0xde, + 0x83, 0x48, 0x08, 0xc3, 0x88, 0x43, 0x03, 0xc8, 0xb9, 0x72, + 0x32, 0xf9, 0xb2, 0x79, 0x39, 0xf2, 0xaf, 0x64, 0x24, 0xef, + 0xa4, 0x6f, 0x2f, 0xe4, 0x00, 0xcc, 0x85, 0x49, 0x17, 0xdb, + 0x92, 0x5e, 0x2e, 0xe2, 0xab, 0x67, 0x39, 0xf5, 0xbc, 0x70, + 0x5c, 0x90, 0xd9, 0x15, 0x4b, 0x87, 0xce, 0x02, 0x72, 0xbe, + 0xf7, 0x3b, 0x65, 0xa9, 0xe0, 0x2c, 0xb8, 0x74, 0x3d, 0xf1, + 0xaf, 0x63, 0x2a, 0xe6, 0x96, 0x5a, 0x13, 0xdf, 0x81, 0x4d, + 0x04, 0xc8, 0xe4, 0x28, 0x61, 0xad, 0xf3, 0x3f, 0x76, 0xba, + 0xca, 0x06, 0x4f, 0x83, 0xdd, 0x11, 0x58, 0x94, 0x6d, 0xa1, + 0xe8, 0x24, 0x7a, 0xb6, 0xff, 0x33, 0x43, 0x8f, 0xc6, 0x0a, + 0x54, 0x98, 0xd1, 0x1d, 0x31, 0xfd, 0xb4, 0x78, 0x26, 0xea, + 0xa3, 0x6f, 0x1f, 0xd3, 0x9a, 0x56, 0x08, 0xc4, 0x8d, 0x41, + 0xd5, 0x19, 0x50, 0x9c, 0xc2, 0x0e, 0x47, 0x8b, 0xfb, 0x37, + 0x7e, 0xb2, 0xec, 0x20, 0x69, 0xa5, 0x89, 0x45, 0x0c, 0xc0, + 0x9e, 0x52, 0x1b, 0xd7, 0xa7, 0x6b, 0x22, 0xee, 0xb0, 0x7c, + 0x35, 0xf9, 0xda, 0x16, 0x5f, 0x93, 0xcd, 0x01, 0x48, 0x84, + 0xf4, 0x38, 0x71, 0xbd, 0xe3, 0x2f, 0x66, 0xaa, 0x86, 0x4a, + 0x03, 0xcf, 0x91, 0x5d, 0x14, 0xd8, 0xa8, 0x64, 0x2d, 0xe1, + 0xbf, 0x73, 0x3a, 0xf6, 0x62, 0xae, 0xe7, 0x2b, 0x75, 0xb9, + 0xf0, 0x3c, 0x4c, 0x80, 0xc9, 0x05, 0x5b, 0x97, 0xde, 0x12, + 0x3e, 0xf2, 0xbb, 0x77, 0x29, 0xe5, 0xac, 0x60, 0x10, 0xdc, + 0x95, 0x59, 0x07, 0xcb, 0x82, 0x4e, 0xb7, 0x7b, 0x32, 0xfe, + 0xa0, 0x6c, 0x25, 0xe9, 0x99, 0x55, 0x1c, 0xd0, 0x8e, 0x42, + 0x0b, 0xc7, 0xeb, 0x27, 0x6e, 0xa2, 0xfc, 0x30, 0x79, 0xb5, + 0xc5, 0x09, 0x40, 0x8c, 0xd2, 0x1e, 0x57, 0x9b, 0x0f, 0xc3, + 0x8a, 0x46, 0x18, 0xd4, 0x9d, 0x51, 0x21, 0xed, 0xa4, 0x68, + 0x36, 0xfa, 0xb3, 0x7f, 0x53, 0x9f, 0xd6, 0x1a, 0x44, 0x88, + 0xc1, 0x0d, 0x7d, 0xb1, 0xf8, 0x34, 0x6a, 0xa6, 0xef, 0x23, + 0x00, 0xcd, 0x87, 0x4a, 0x13, 0xde, 0x94, 0x59, 0x26, 0xeb, + 0xa1, 0x6c, 0x35, 0xf8, 0xb2, 0x7f, 0x4c, 0x81, 0xcb, 0x06, + 0x5f, 0x92, 0xd8, 0x15, 0x6a, 0xa7, 0xed, 0x20, 0x79, 0xb4, + 0xfe, 0x33, 0x98, 0x55, 0x1f, 0xd2, 0x8b, 0x46, 0x0c, 0xc1, + 0xbe, 0x73, 0x39, 0xf4, 0xad, 0x60, 0x2a, 0xe7, 0xd4, 0x19, + 0x53, 0x9e, 0xc7, 0x0a, 0x40, 0x8d, 0xf2, 0x3f, 0x75, 0xb8, + 0xe1, 0x2c, 0x66, 0xab, 0x2d, 0xe0, 0xaa, 0x67, 0x3e, 0xf3, + 0xb9, 0x74, 0x0b, 0xc6, 0x8c, 0x41, 0x18, 0xd5, 0x9f, 0x52, + 0x61, 0xac, 0xe6, 0x2b, 0x72, 0xbf, 0xf5, 0x38, 0x47, 0x8a, + 0xc0, 0x0d, 0x54, 0x99, 0xd3, 0x1e, 0xb5, 0x78, 0x32, 0xff, + 0xa6, 0x6b, 0x21, 0xec, 0x93, 0x5e, 0x14, 0xd9, 0x80, 0x4d, + 0x07, 0xca, 0xf9, 0x34, 0x7e, 0xb3, 0xea, 0x27, 0x6d, 0xa0, + 0xdf, 0x12, 0x58, 0x95, 0xcc, 0x01, 0x4b, 0x86, 0x5a, 0x97, + 0xdd, 0x10, 0x49, 0x84, 0xce, 0x03, 0x7c, 0xb1, 0xfb, 0x36, + 0x6f, 0xa2, 0xe8, 0x25, 0x16, 0xdb, 0x91, 0x5c, 0x05, 0xc8, + 0x82, 0x4f, 0x30, 0xfd, 0xb7, 0x7a, 0x23, 0xee, 0xa4, 0x69, + 0xc2, 0x0f, 0x45, 0x88, 0xd1, 0x1c, 0x56, 0x9b, 0xe4, 0x29, + 0x63, 0xae, 0xf7, 0x3a, 0x70, 0xbd, 0x8e, 0x43, 0x09, 0xc4, + 0x9d, 0x50, 0x1a, 0xd7, 0xa8, 0x65, 0x2f, 0xe2, 0xbb, 0x76, + 0x3c, 0xf1, 0x77, 0xba, 0xf0, 0x3d, 0x64, 0xa9, 0xe3, 0x2e, + 0x51, 0x9c, 0xd6, 0x1b, 0x42, 0x8f, 0xc5, 0x08, 0x3b, 0xf6, + 0xbc, 0x71, 0x28, 0xe5, 0xaf, 0x62, 0x1d, 0xd0, 0x9a, 0x57, + 0x0e, 0xc3, 0x89, 0x44, 0xef, 0x22, 0x68, 0xa5, 0xfc, 0x31, + 0x7b, 0xb6, 0xc9, 0x04, 0x4e, 0x83, 0xda, 0x17, 0x5d, 0x90, + 0xa3, 0x6e, 0x24, 0xe9, 0xb0, 0x7d, 0x37, 0xfa, 0x85, 0x48, + 0x02, 0xcf, 0x96, 0x5b, 0x11, 0xdc, 0x00, 0xce, 0x81, 0x4f, + 0x1f, 0xd1, 0x9e, 0x50, 0x3e, 0xf0, 0xbf, 0x71, 0x21, 0xef, + 0xa0, 0x6e, 0x7c, 0xb2, 0xfd, 0x33, 0x63, 0xad, 0xe2, 0x2c, + 0x42, 0x8c, 0xc3, 0x0d, 0x5d, 0x93, 0xdc, 0x12, 0xf8, 0x36, + 0x79, 0xb7, 0xe7, 0x29, 0x66, 0xa8, 0xc6, 0x08, 0x47, 0x89, + 0xd9, 0x17, 0x58, 0x96, 0x84, 0x4a, 0x05, 0xcb, 0x9b, 0x55, + 0x1a, 0xd4, 0xba, 0x74, 0x3b, 0xf5, 0xa5, 0x6b, 0x24, 0xea, + 0xed, 0x23, 0x6c, 0xa2, 0xf2, 0x3c, 0x73, 0xbd, 0xd3, 0x1d, + 0x52, 0x9c, 0xcc, 0x02, 0x4d, 0x83, 0x91, 0x5f, 0x10, 0xde, + 0x8e, 0x40, 0x0f, 0xc1, 0xaf, 0x61, 0x2e, 0xe0, 0xb0, 0x7e, + 0x31, 0xff, 0x15, 0xdb, 0x94, 0x5a, 0x0a, 0xc4, 0x8b, 0x45, + 0x2b, 0xe5, 0xaa, 0x64, 0x34, 0xfa, 0xb5, 0x7b, 0x69, 0xa7, + 0xe8, 0x26, 0x76, 0xb8, 0xf7, 0x39, 0x57, 0x99, 0xd6, 0x18, + 0x48, 0x86, 0xc9, 0x07, 0xc7, 0x09, 0x46, 0x88, 0xd8, 0x16, + 0x59, 0x97, 0xf9, 0x37, 0x78, 0xb6, 0xe6, 0x28, 0x67, 0xa9, + 0xbb, 0x75, 0x3a, 0xf4, 0xa4, 0x6a, 0x25, 0xeb, 0x85, 0x4b, + 0x04, 0xca, 0x9a, 0x54, 0x1b, 0xd5, 0x3f, 0xf1, 0xbe, 0x70, + 0x20, 0xee, 0xa1, 0x6f, 0x01, 0xcf, 0x80, 0x4e, 0x1e, 0xd0, + 0x9f, 0x51, 0x43, 0x8d, 0xc2, 0x0c, 0x5c, 0x92, 0xdd, 0x13, + 0x7d, 0xb3, 0xfc, 0x32, 0x62, 0xac, 0xe3, 0x2d, 0x2a, 0xe4, + 0xab, 0x65, 0x35, 0xfb, 0xb4, 0x7a, 0x14, 0xda, 0x95, 0x5b, + 0x0b, 0xc5, 0x8a, 0x44, 0x56, 0x98, 0xd7, 0x19, 0x49, 0x87, + 0xc8, 0x06, 0x68, 0xa6, 0xe9, 0x27, 0x77, 0xb9, 0xf6, 0x38, + 0xd2, 0x1c, 0x53, 0x9d, 0xcd, 0x03, 0x4c, 0x82, 0xec, 0x22, + 0x6d, 0xa3, 0xf3, 0x3d, 0x72, 0xbc, 0xae, 0x60, 0x2f, 0xe1, + 0xb1, 0x7f, 0x30, 0xfe, 0x90, 0x5e, 0x11, 0xdf, 0x8f, 0x41, + 0x0e, 0xc0, 0x00, 0xcf, 0x83, 0x4c, 0x1b, 0xd4, 0x98, 0x57, + 0x36, 0xf9, 0xb5, 0x7a, 0x2d, 0xe2, 0xae, 0x61, 0x6c, 0xa3, + 0xef, 0x20, 0x77, 0xb8, 0xf4, 0x3b, 0x5a, 0x95, 0xd9, 0x16, + 0x41, 0x8e, 0xc2, 0x0d, 0xd8, 0x17, 0x5b, 0x94, 0xc3, 0x0c, + 0x40, 0x8f, 0xee, 0x21, 0x6d, 0xa2, 0xf5, 0x3a, 0x76, 0xb9, + 0xb4, 0x7b, 0x37, 0xf8, 0xaf, 0x60, 0x2c, 0xe3, 0x82, 0x4d, + 0x01, 0xce, 0x99, 0x56, 0x1a, 0xd5, 0xad, 0x62, 0x2e, 0xe1, + 0xb6, 0x79, 0x35, 0xfa, 0x9b, 0x54, 0x18, 0xd7, 0x80, 0x4f, + 0x03, 0xcc, 0xc1, 0x0e, 0x42, 0x8d, 0xda, 0x15, 0x59, 0x96, + 0xf7, 0x38, 0x74, 0xbb, 0xec, 0x23, 0x6f, 0xa0, 0x75, 0xba, + 0xf6, 0x39, 0x6e, 0xa1, 0xed, 0x22, 0x43, 0x8c, 0xc0, 0x0f, + 0x58, 0x97, 0xdb, 0x14, 0x19, 0xd6, 0x9a, 0x55, 0x02, 0xcd, + 0x81, 0x4e, 0x2f, 0xe0, 0xac, 0x63, 0x34, 0xfb, 0xb7, 0x78, + 0x47, 0x88, 0xc4, 0x0b, 0x5c, 0x93, 0xdf, 0x10, 0x71, 0xbe, + 0xf2, 0x3d, 0x6a, 0xa5, 0xe9, 0x26, 0x2b, 0xe4, 0xa8, 0x67, + 0x30, 0xff, 0xb3, 0x7c, 0x1d, 0xd2, 0x9e, 0x51, 0x06, 0xc9, + 0x85, 0x4a, 0x9f, 0x50, 0x1c, 0xd3, 0x84, 0x4b, 0x07, 0xc8, + 0xa9, 0x66, 0x2a, 0xe5, 0xb2, 0x7d, 0x31, 0xfe, 0xf3, 0x3c, + 0x70, 0xbf, 0xe8, 0x27, 0x6b, 0xa4, 0xc5, 0x0a, 0x46, 0x89, + 0xde, 0x11, 0x5d, 0x92, 0xea, 0x25, 0x69, 0xa6, 0xf1, 0x3e, + 0x72, 0xbd, 0xdc, 0x13, 0x5f, 0x90, 0xc7, 0x08, 0x44, 0x8b, + 0x86, 0x49, 0x05, 0xca, 0x9d, 0x52, 0x1e, 0xd1, 0xb0, 0x7f, + 0x33, 0xfc, 0xab, 0x64, 0x28, 0xe7, 0x32, 0xfd, 0xb1, 0x7e, + 0x29, 0xe6, 0xaa, 0x65, 0x04, 0xcb, 0x87, 0x48, 0x1f, 0xd0, + 0x9c, 0x53, 0x5e, 0x91, 0xdd, 0x12, 0x45, 0x8a, 0xc6, 0x09, + 0x68, 0xa7, 0xeb, 0x24, 0x73, 0xbc, 0xf0, 0x3f, 0x00, 0xd0, + 0xbd, 0x6d, 0x67, 0xb7, 0xda, 0x0a, 0xce, 0x1e, 0x73, 0xa3, + 0xa9, 0x79, 0x14, 0xc4, 0x81, 0x51, 0x3c, 0xec, 0xe6, 0x36, + 0x5b, 0x8b, 0x4f, 0x9f, 0xf2, 0x22, 0x28, 0xf8, 0x95, 0x45, + 0x1f, 0xcf, 0xa2, 0x72, 0x78, 0xa8, 0xc5, 0x15, 0xd1, 0x01, + 0x6c, 0xbc, 0xb6, 0x66, 0x0b, 0xdb, 0x9e, 0x4e, 0x23, 0xf3, + 0xf9, 0x29, 0x44, 0x94, 0x50, 0x80, 0xed, 0x3d, 0x37, 0xe7, + 0x8a, 0x5a, 0x3e, 0xee, 0x83, 0x53, 0x59, 0x89, 0xe4, 0x34, + 0xf0, 0x20, 0x4d, 0x9d, 0x97, 0x47, 0x2a, 0xfa, 0xbf, 0x6f, + 0x02, 0xd2, 0xd8, 0x08, 0x65, 0xb5, 0x71, 0xa1, 0xcc, 0x1c, + 0x16, 0xc6, 0xab, 0x7b, 0x21, 0xf1, 0x9c, 0x4c, 0x46, 0x96, + 0xfb, 0x2b, 0xef, 0x3f, 0x52, 0x82, 0x88, 0x58, 0x35, 0xe5, + 0xa0, 0x70, 0x1d, 0xcd, 0xc7, 0x17, 0x7a, 0xaa, 0x6e, 0xbe, + 0xd3, 0x03, 0x09, 0xd9, 0xb4, 0x64, 0x7c, 0xac, 0xc1, 0x11, + 0x1b, 0xcb, 0xa6, 0x76, 0xb2, 0x62, 0x0f, 0xdf, 0xd5, 0x05, + 0x68, 0xb8, 0xfd, 0x2d, 0x40, 0x90, 0x9a, 0x4a, 0x27, 0xf7, + 0x33, 0xe3, 0x8e, 0x5e, 0x54, 0x84, 0xe9, 0x39, 0x63, 0xb3, + 0xde, 0x0e, 0x04, 0xd4, 0xb9, 0x69, 0xad, 0x7d, 0x10, 0xc0, + 0xca, 0x1a, 0x77, 0xa7, 0xe2, 0x32, 0x5f, 0x8f, 0x85, 0x55, + 0x38, 0xe8, 0x2c, 0xfc, 0x91, 0x41, 0x4b, 0x9b, 0xf6, 0x26, + 0x42, 0x92, 0xff, 0x2f, 0x25, 0xf5, 0x98, 0x48, 0x8c, 0x5c, + 0x31, 0xe1, 0xeb, 0x3b, 0x56, 0x86, 0xc3, 0x13, 0x7e, 0xae, + 0xa4, 0x74, 0x19, 0xc9, 0x0d, 0xdd, 0xb0, 0x60, 0x6a, 0xba, + 0xd7, 0x07, 0x5d, 0x8d, 0xe0, 0x30, 0x3a, 0xea, 0x87, 0x57, + 0x93, 0x43, 0x2e, 0xfe, 0xf4, 0x24, 0x49, 0x99, 0xdc, 0x0c, + 0x61, 0xb1, 0xbb, 0x6b, 0x06, 0xd6, 0x12, 0xc2, 0xaf, 0x7f, + 0x75, 0xa5, 0xc8, 0x18, 0x00, 0xd1, 0xbf, 0x6e, 0x63, 0xb2, + 0xdc, 0x0d, 0xc6, 0x17, 0x79, 0xa8, 0xa5, 0x74, 0x1a, 0xcb, + 0x91, 0x40, 0x2e, 0xff, 0xf2, 0x23, 0x4d, 0x9c, 0x57, 0x86, + 0xe8, 0x39, 0x34, 0xe5, 0x8b, 0x5a, 0x3f, 0xee, 0x80, 0x51, + 0x5c, 0x8d, 0xe3, 0x32, 0xf9, 0x28, 0x46, 0x97, 0x9a, 0x4b, + 0x25, 0xf4, 0xae, 0x7f, 0x11, 0xc0, 0xcd, 0x1c, 0x72, 0xa3, + 0x68, 0xb9, 0xd7, 0x06, 0x0b, 0xda, 0xb4, 0x65, 0x7e, 0xaf, + 0xc1, 0x10, 0x1d, 0xcc, 0xa2, 0x73, 0xb8, 0x69, 0x07, 0xd6, + 0xdb, 0x0a, 0x64, 0xb5, 0xef, 0x3e, 0x50, 0x81, 0x8c, 0x5d, + 0x33, 0xe2, 0x29, 0xf8, 0x96, 0x47, 0x4a, 0x9b, 0xf5, 0x24, + 0x41, 0x90, 0xfe, 0x2f, 0x22, 0xf3, 0x9d, 0x4c, 0x87, 0x56, + 0x38, 0xe9, 0xe4, 0x35, 0x5b, 0x8a, 0xd0, 0x01, 0x6f, 0xbe, + 0xb3, 0x62, 0x0c, 0xdd, 0x16, 0xc7, 0xa9, 0x78, 0x75, 0xa4, + 0xca, 0x1b, 0xfc, 0x2d, 0x43, 0x92, 0x9f, 0x4e, 0x20, 0xf1, + 0x3a, 0xeb, 0x85, 0x54, 0x59, 0x88, 0xe6, 0x37, 0x6d, 0xbc, + 0xd2, 0x03, 0x0e, 0xdf, 0xb1, 0x60, 0xab, 0x7a, 0x14, 0xc5, + 0xc8, 0x19, 0x77, 0xa6, 0xc3, 0x12, 0x7c, 0xad, 0xa0, 0x71, + 0x1f, 0xce, 0x05, 0xd4, 0xba, 0x6b, 0x66, 0xb7, 0xd9, 0x08, + 0x52, 0x83, 0xed, 0x3c, 0x31, 0xe0, 0x8e, 0x5f, 0x94, 0x45, + 0x2b, 0xfa, 0xf7, 0x26, 0x48, 0x99, 0x82, 0x53, 0x3d, 0xec, + 0xe1, 0x30, 0x5e, 0x8f, 0x44, 0x95, 0xfb, 0x2a, 0x27, 0xf6, + 0x98, 0x49, 0x13, 0xc2, 0xac, 0x7d, 0x70, 0xa1, 0xcf, 0x1e, + 0xd5, 0x04, 0x6a, 0xbb, 0xb6, 0x67, 0x09, 0xd8, 0xbd, 0x6c, + 0x02, 0xd3, 0xde, 0x0f, 0x61, 0xb0, 0x7b, 0xaa, 0xc4, 0x15, + 0x18, 0xc9, 0xa7, 0x76, 0x2c, 0xfd, 0x93, 0x42, 0x4f, 0x9e, + 0xf0, 0x21, 0xea, 0x3b, 0x55, 0x84, 0x89, 0x58, 0x36, 0xe7, + 0x00, 0xd2, 0xb9, 0x6b, 0x6f, 0xbd, 0xd6, 0x04, 0xde, 0x0c, + 0x67, 0xb5, 0xb1, 0x63, 0x08, 0xda, 0xa1, 0x73, 0x18, 0xca, + 0xce, 0x1c, 0x77, 0xa5, 0x7f, 0xad, 0xc6, 0x14, 0x10, 0xc2, + 0xa9, 0x7b, 0x5f, 0x8d, 0xe6, 0x34, 0x30, 0xe2, 0x89, 0x5b, + 0x81, 0x53, 0x38, 0xea, 0xee, 0x3c, 0x57, 0x85, 0xfe, 0x2c, + 0x47, 0x95, 0x91, 0x43, 0x28, 0xfa, 0x20, 0xf2, 0x99, 0x4b, + 0x4f, 0x9d, 0xf6, 0x24, 0xbe, 0x6c, 0x07, 0xd5, 0xd1, 0x03, + 0x68, 0xba, 0x60, 0xb2, 0xd9, 0x0b, 0x0f, 0xdd, 0xb6, 0x64, + 0x1f, 0xcd, 0xa6, 0x74, 0x70, 0xa2, 0xc9, 0x1b, 0xc1, 0x13, + 0x78, 0xaa, 0xae, 0x7c, 0x17, 0xc5, 0xe1, 0x33, 0x58, 0x8a, + 0x8e, 0x5c, 0x37, 0xe5, 0x3f, 0xed, 0x86, 0x54, 0x50, 0x82, + 0xe9, 0x3b, 0x40, 0x92, 0xf9, 0x2b, 0x2f, 0xfd, 0x96, 0x44, + 0x9e, 0x4c, 0x27, 0xf5, 0xf1, 0x23, 0x48, 0x9a, 0x61, 0xb3, + 0xd8, 0x0a, 0x0e, 0xdc, 0xb7, 0x65, 0xbf, 0x6d, 0x06, 0xd4, + 0xd0, 0x02, 0x69, 0xbb, 0xc0, 0x12, 0x79, 0xab, 0xaf, 0x7d, + 0x16, 0xc4, 0x1e, 0xcc, 0xa7, 0x75, 0x71, 0xa3, 0xc8, 0x1a, + 0x3e, 0xec, 0x87, 0x55, 0x51, 0x83, 0xe8, 0x3a, 0xe0, 0x32, + 0x59, 0x8b, 0x8f, 0x5d, 0x36, 0xe4, 0x9f, 0x4d, 0x26, 0xf4, + 0xf0, 0x22, 0x49, 0x9b, 0x41, 0x93, 0xf8, 0x2a, 0x2e, 0xfc, + 0x97, 0x45, 0xdf, 0x0d, 0x66, 0xb4, 0xb0, 0x62, 0x09, 0xdb, + 0x01, 0xd3, 0xb8, 0x6a, 0x6e, 0xbc, 0xd7, 0x05, 0x7e, 0xac, + 0xc7, 0x15, 0x11, 0xc3, 0xa8, 0x7a, 0xa0, 0x72, 0x19, 0xcb, + 0xcf, 0x1d, 0x76, 0xa4, 0x80, 0x52, 0x39, 0xeb, 0xef, 0x3d, + 0x56, 0x84, 0x5e, 0x8c, 0xe7, 0x35, 0x31, 0xe3, 0x88, 0x5a, + 0x21, 0xf3, 0x98, 0x4a, 0x4e, 0x9c, 0xf7, 0x25, 0xff, 0x2d, + 0x46, 0x94, 0x90, 0x42, 0x29, 0xfb, 0x00, 0xd3, 0xbb, 0x68, + 0x6b, 0xb8, 0xd0, 0x03, 0xd6, 0x05, 0x6d, 0xbe, 0xbd, 0x6e, + 0x06, 0xd5, 0xb1, 0x62, 0x0a, 0xd9, 0xda, 0x09, 0x61, 0xb2, + 0x67, 0xb4, 0xdc, 0x0f, 0x0c, 0xdf, 0xb7, 0x64, 0x7f, 0xac, + 0xc4, 0x17, 0x14, 0xc7, 0xaf, 0x7c, 0xa9, 0x7a, 0x12, 0xc1, + 0xc2, 0x11, 0x79, 0xaa, 0xce, 0x1d, 0x75, 0xa6, 0xa5, 0x76, + 0x1e, 0xcd, 0x18, 0xcb, 0xa3, 0x70, 0x73, 0xa0, 0xc8, 0x1b, + 0xfe, 0x2d, 0x45, 0x96, 0x95, 0x46, 0x2e, 0xfd, 0x28, 0xfb, + 0x93, 0x40, 0x43, 0x90, 0xf8, 0x2b, 0x4f, 0x9c, 0xf4, 0x27, + 0x24, 0xf7, 0x9f, 0x4c, 0x99, 0x4a, 0x22, 0xf1, 0xf2, 0x21, + 0x49, 0x9a, 0x81, 0x52, 0x3a, 0xe9, 0xea, 0x39, 0x51, 0x82, + 0x57, 0x84, 0xec, 0x3f, 0x3c, 0xef, 0x87, 0x54, 0x30, 0xe3, + 0x8b, 0x58, 0x5b, 0x88, 0xe0, 0x33, 0xe6, 0x35, 0x5d, 0x8e, + 0x8d, 0x5e, 0x36, 0xe5, 0xe1, 0x32, 0x5a, 0x89, 0x8a, 0x59, + 0x31, 0xe2, 0x37, 0xe4, 0x8c, 0x5f, 0x5c, 0x8f, 0xe7, 0x34, + 0x50, 0x83, 0xeb, 0x38, 0x3b, 0xe8, 0x80, 0x53, 0x86, 0x55, + 0x3d, 0xee, 0xed, 0x3e, 0x56, 0x85, 0x9e, 0x4d, 0x25, 0xf6, + 0xf5, 0x26, 0x4e, 0x9d, 0x48, 0x9b, 0xf3, 0x20, 0x23, 0xf0, + 0x98, 0x4b, 0x2f, 0xfc, 0x94, 0x47, 0x44, 0x97, 0xff, 0x2c, + 0xf9, 0x2a, 0x42, 0x91, 0x92, 0x41, 0x29, 0xfa, 0x1f, 0xcc, + 0xa4, 0x77, 0x74, 0xa7, 0xcf, 0x1c, 0xc9, 0x1a, 0x72, 0xa1, + 0xa2, 0x71, 0x19, 0xca, 0xae, 0x7d, 0x15, 0xc6, 0xc5, 0x16, + 0x7e, 0xad, 0x78, 0xab, 0xc3, 0x10, 0x13, 0xc0, 0xa8, 0x7b, + 0x60, 0xb3, 0xdb, 0x08, 0x0b, 0xd8, 0xb0, 0x63, 0xb6, 0x65, + 0x0d, 0xde, 0xdd, 0x0e, 0x66, 0xb5, 0xd1, 0x02, 0x6a, 0xb9, + 0xba, 0x69, 0x01, 0xd2, 0x07, 0xd4, 0xbc, 0x6f, 0x6c, 0xbf, + 0xd7, 0x04, 0x00, 0xd4, 0xb5, 0x61, 0x77, 0xa3, 0xc2, 0x16, + 0xee, 0x3a, 0x5b, 0x8f, 0x99, 0x4d, 0x2c, 0xf8, 0xc1, 0x15, + 0x74, 0xa0, 0xb6, 0x62, 0x03, 0xd7, 0x2f, 0xfb, 0x9a, 0x4e, + 0x58, 0x8c, 0xed, 0x39, 0x9f, 0x4b, 0x2a, 0xfe, 0xe8, 0x3c, + 0x5d, 0x89, 0x71, 0xa5, 0xc4, 0x10, 0x06, 0xd2, 0xb3, 0x67, + 0x5e, 0x8a, 0xeb, 0x3f, 0x29, 0xfd, 0x9c, 0x48, 0xb0, 0x64, + 0x05, 0xd1, 0xc7, 0x13, 0x72, 0xa6, 0x23, 0xf7, 0x96, 0x42, + 0x54, 0x80, 0xe1, 0x35, 0xcd, 0x19, 0x78, 0xac, 0xba, 0x6e, + 0x0f, 0xdb, 0xe2, 0x36, 0x57, 0x83, 0x95, 0x41, 0x20, 0xf4, + 0x0c, 0xd8, 0xb9, 0x6d, 0x7b, 0xaf, 0xce, 0x1a, 0xbc, 0x68, + 0x09, 0xdd, 0xcb, 0x1f, 0x7e, 0xaa, 0x52, 0x86, 0xe7, 0x33, + 0x25, 0xf1, 0x90, 0x44, 0x7d, 0xa9, 0xc8, 0x1c, 0x0a, 0xde, + 0xbf, 0x6b, 0x93, 0x47, 0x26, 0xf2, 0xe4, 0x30, 0x51, 0x85, + 0x46, 0x92, 0xf3, 0x27, 0x31, 0xe5, 0x84, 0x50, 0xa8, 0x7c, + 0x1d, 0xc9, 0xdf, 0x0b, 0x6a, 0xbe, 0x87, 0x53, 0x32, 0xe6, + 0xf0, 0x24, 0x45, 0x91, 0x69, 0xbd, 0xdc, 0x08, 0x1e, 0xca, + 0xab, 0x7f, 0xd9, 0x0d, 0x6c, 0xb8, 0xae, 0x7a, 0x1b, 0xcf, + 0x37, 0xe3, 0x82, 0x56, 0x40, 0x94, 0xf5, 0x21, 0x18, 0xcc, + 0xad, 0x79, 0x6f, 0xbb, 0xda, 0x0e, 0xf6, 0x22, 0x43, 0x97, + 0x81, 0x55, 0x34, 0xe0, 0x65, 0xb1, 0xd0, 0x04, 0x12, 0xc6, + 0xa7, 0x73, 0x8b, 0x5f, 0x3e, 0xea, 0xfc, 0x28, 0x49, 0x9d, + 0xa4, 0x70, 0x11, 0xc5, 0xd3, 0x07, 0x66, 0xb2, 0x4a, 0x9e, + 0xff, 0x2b, 0x3d, 0xe9, 0x88, 0x5c, 0xfa, 0x2e, 0x4f, 0x9b, + 0x8d, 0x59, 0x38, 0xec, 0x14, 0xc0, 0xa1, 0x75, 0x63, 0xb7, + 0xd6, 0x02, 0x3b, 0xef, 0x8e, 0x5a, 0x4c, 0x98, 0xf9, 0x2d, + 0xd5, 0x01, 0x60, 0xb4, 0xa2, 0x76, 0x17, 0xc3, 0x00, 0xd5, + 0xb7, 0x62, 0x73, 0xa6, 0xc4, 0x11, 0xe6, 0x33, 0x51, 0x84, + 0x95, 0x40, 0x22, 0xf7, 0xd1, 0x04, 0x66, 0xb3, 0xa2, 0x77, + 0x15, 0xc0, 0x37, 0xe2, 0x80, 0x55, 0x44, 0x91, 0xf3, 0x26, + 0xbf, 0x6a, 0x08, 0xdd, 0xcc, 0x19, 0x7b, 0xae, 0x59, 0x8c, + 0xee, 0x3b, 0x2a, 0xff, 0x9d, 0x48, 0x6e, 0xbb, 0xd9, 0x0c, + 0x1d, 0xc8, 0xaa, 0x7f, 0x88, 0x5d, 0x3f, 0xea, 0xfb, 0x2e, + 0x4c, 0x99, 0x63, 0xb6, 0xd4, 0x01, 0x10, 0xc5, 0xa7, 0x72, + 0x85, 0x50, 0x32, 0xe7, 0xf6, 0x23, 0x41, 0x94, 0xb2, 0x67, + 0x05, 0xd0, 0xc1, 0x14, 0x76, 0xa3, 0x54, 0x81, 0xe3, 0x36, + 0x27, 0xf2, 0x90, 0x45, 0xdc, 0x09, 0x6b, 0xbe, 0xaf, 0x7a, + 0x18, 0xcd, 0x3a, 0xef, 0x8d, 0x58, 0x49, 0x9c, 0xfe, 0x2b, + 0x0d, 0xd8, 0xba, 0x6f, 0x7e, 0xab, 0xc9, 0x1c, 0xeb, 0x3e, + 0x5c, 0x89, 0x98, 0x4d, 0x2f, 0xfa, 0xc6, 0x13, 0x71, 0xa4, + 0xb5, 0x60, 0x02, 0xd7, 0x20, 0xf5, 0x97, 0x42, 0x53, 0x86, + 0xe4, 0x31, 0x17, 0xc2, 0xa0, 0x75, 0x64, 0xb1, 0xd3, 0x06, + 0xf1, 0x24, 0x46, 0x93, 0x82, 0x57, 0x35, 0xe0, 0x79, 0xac, + 0xce, 0x1b, 0x0a, 0xdf, 0xbd, 0x68, 0x9f, 0x4a, 0x28, 0xfd, + 0xec, 0x39, 0x5b, 0x8e, 0xa8, 0x7d, 0x1f, 0xca, 0xdb, 0x0e, + 0x6c, 0xb9, 0x4e, 0x9b, 0xf9, 0x2c, 0x3d, 0xe8, 0x8a, 0x5f, + 0xa5, 0x70, 0x12, 0xc7, 0xd6, 0x03, 0x61, 0xb4, 0x43, 0x96, + 0xf4, 0x21, 0x30, 0xe5, 0x87, 0x52, 0x74, 0xa1, 0xc3, 0x16, + 0x07, 0xd2, 0xb0, 0x65, 0x92, 0x47, 0x25, 0xf0, 0xe1, 0x34, + 0x56, 0x83, 0x1a, 0xcf, 0xad, 0x78, 0x69, 0xbc, 0xde, 0x0b, + 0xfc, 0x29, 0x4b, 0x9e, 0x8f, 0x5a, 0x38, 0xed, 0xcb, 0x1e, + 0x7c, 0xa9, 0xb8, 0x6d, 0x0f, 0xda, 0x2d, 0xf8, 0x9a, 0x4f, + 0x5e, 0x8b, 0xe9, 0x3c, 0x00, 0xd6, 0xb1, 0x67, 0x7f, 0xa9, + 0xce, 0x18, 0xfe, 0x28, 0x4f, 0x99, 0x81, 0x57, 0x30, 0xe6, + 0xe1, 0x37, 0x50, 0x86, 0x9e, 0x48, 0x2f, 0xf9, 0x1f, 0xc9, + 0xae, 0x78, 0x60, 0xb6, 0xd1, 0x07, 0xdf, 0x09, 0x6e, 0xb8, + 0xa0, 0x76, 0x11, 0xc7, 0x21, 0xf7, 0x90, 0x46, 0x5e, 0x88, + 0xef, 0x39, 0x3e, 0xe8, 0x8f, 0x59, 0x41, 0x97, 0xf0, 0x26, + 0xc0, 0x16, 0x71, 0xa7, 0xbf, 0x69, 0x0e, 0xd8, 0xa3, 0x75, + 0x12, 0xc4, 0xdc, 0x0a, 0x6d, 0xbb, 0x5d, 0x8b, 0xec, 0x3a, + 0x22, 0xf4, 0x93, 0x45, 0x42, 0x94, 0xf3, 0x25, 0x3d, 0xeb, + 0x8c, 0x5a, 0xbc, 0x6a, 0x0d, 0xdb, 0xc3, 0x15, 0x72, 0xa4, + 0x7c, 0xaa, 0xcd, 0x1b, 0x03, 0xd5, 0xb2, 0x64, 0x82, 0x54, + 0x33, 0xe5, 0xfd, 0x2b, 0x4c, 0x9a, 0x9d, 0x4b, 0x2c, 0xfa, + 0xe2, 0x34, 0x53, 0x85, 0x63, 0xb5, 0xd2, 0x04, 0x1c, 0xca, + 0xad, 0x7b, 0x5b, 0x8d, 0xea, 0x3c, 0x24, 0xf2, 0x95, 0x43, + 0xa5, 0x73, 0x14, 0xc2, 0xda, 0x0c, 0x6b, 0xbd, 0xba, 0x6c, + 0x0b, 0xdd, 0xc5, 0x13, 0x74, 0xa2, 0x44, 0x92, 0xf5, 0x23, + 0x3b, 0xed, 0x8a, 0x5c, 0x84, 0x52, 0x35, 0xe3, 0xfb, 0x2d, + 0x4a, 0x9c, 0x7a, 0xac, 0xcb, 0x1d, 0x05, 0xd3, 0xb4, 0x62, + 0x65, 0xb3, 0xd4, 0x02, 0x1a, 0xcc, 0xab, 0x7d, 0x9b, 0x4d, + 0x2a, 0xfc, 0xe4, 0x32, 0x55, 0x83, 0xf8, 0x2e, 0x49, 0x9f, + 0x87, 0x51, 0x36, 0xe0, 0x06, 0xd0, 0xb7, 0x61, 0x79, 0xaf, + 0xc8, 0x1e, 0x19, 0xcf, 0xa8, 0x7e, 0x66, 0xb0, 0xd7, 0x01, + 0xe7, 0x31, 0x56, 0x80, 0x98, 0x4e, 0x29, 0xff, 0x27, 0xf1, + 0x96, 0x40, 0x58, 0x8e, 0xe9, 0x3f, 0xd9, 0x0f, 0x68, 0xbe, + 0xa6, 0x70, 0x17, 0xc1, 0xc6, 0x10, 0x77, 0xa1, 0xb9, 0x6f, + 0x08, 0xde, 0x38, 0xee, 0x89, 0x5f, 0x47, 0x91, 0xf6, 0x20, + 0x00, 0xd7, 0xb3, 0x64, 0x7b, 0xac, 0xc8, 0x1f, 0xf6, 0x21, + 0x45, 0x92, 0x8d, 0x5a, 0x3e, 0xe9, 0xf1, 0x26, 0x42, 0x95, + 0x8a, 0x5d, 0x39, 0xee, 0x07, 0xd0, 0xb4, 0x63, 0x7c, 0xab, + 0xcf, 0x18, 0xff, 0x28, 0x4c, 0x9b, 0x84, 0x53, 0x37, 0xe0, + 0x09, 0xde, 0xba, 0x6d, 0x72, 0xa5, 0xc1, 0x16, 0x0e, 0xd9, + 0xbd, 0x6a, 0x75, 0xa2, 0xc6, 0x11, 0xf8, 0x2f, 0x4b, 0x9c, + 0x83, 0x54, 0x30, 0xe7, 0xe3, 0x34, 0x50, 0x87, 0x98, 0x4f, + 0x2b, 0xfc, 0x15, 0xc2, 0xa6, 0x71, 0x6e, 0xb9, 0xdd, 0x0a, + 0x12, 0xc5, 0xa1, 0x76, 0x69, 0xbe, 0xda, 0x0d, 0xe4, 0x33, + 0x57, 0x80, 0x9f, 0x48, 0x2c, 0xfb, 0x1c, 0xcb, 0xaf, 0x78, + 0x67, 0xb0, 0xd4, 0x03, 0xea, 0x3d, 0x59, 0x8e, 0x91, 0x46, + 0x22, 0xf5, 0xed, 0x3a, 0x5e, 0x89, 0x96, 0x41, 0x25, 0xf2, + 0x1b, 0xcc, 0xa8, 0x7f, 0x60, 0xb7, 0xd3, 0x04, 0xdb, 0x0c, + 0x68, 0xbf, 0xa0, 0x77, 0x13, 0xc4, 0x2d, 0xfa, 0x9e, 0x49, + 0x56, 0x81, 0xe5, 0x32, 0x2a, 0xfd, 0x99, 0x4e, 0x51, 0x86, + 0xe2, 0x35, 0xdc, 0x0b, 0x6f, 0xb8, 0xa7, 0x70, 0x14, 0xc3, + 0x24, 0xf3, 0x97, 0x40, 0x5f, 0x88, 0xec, 0x3b, 0xd2, 0x05, + 0x61, 0xb6, 0xa9, 0x7e, 0x1a, 0xcd, 0xd5, 0x02, 0x66, 0xb1, + 0xae, 0x79, 0x1d, 0xca, 0x23, 0xf4, 0x90, 0x47, 0x58, 0x8f, + 0xeb, 0x3c, 0x38, 0xef, 0x8b, 0x5c, 0x43, 0x94, 0xf0, 0x27, + 0xce, 0x19, 0x7d, 0xaa, 0xb5, 0x62, 0x06, 0xd1, 0xc9, 0x1e, + 0x7a, 0xad, 0xb2, 0x65, 0x01, 0xd6, 0x3f, 0xe8, 0x8c, 0x5b, + 0x44, 0x93, 0xf7, 0x20, 0xc7, 0x10, 0x74, 0xa3, 0xbc, 0x6b, + 0x0f, 0xd8, 0x31, 0xe6, 0x82, 0x55, 0x4a, 0x9d, 0xf9, 0x2e, + 0x36, 0xe1, 0x85, 0x52, 0x4d, 0x9a, 0xfe, 0x29, 0xc0, 0x17, + 0x73, 0xa4, 0xbb, 0x6c, 0x08, 0xdf, 0x00, 0xd8, 0xad, 0x75, + 0x47, 0x9f, 0xea, 0x32, 0x8e, 0x56, 0x23, 0xfb, 0xc9, 0x11, + 0x64, 0xbc, 0x01, 0xd9, 0xac, 0x74, 0x46, 0x9e, 0xeb, 0x33, + 0x8f, 0x57, 0x22, 0xfa, 0xc8, 0x10, 0x65, 0xbd, 0x02, 0xda, + 0xaf, 0x77, 0x45, 0x9d, 0xe8, 0x30, 0x8c, 0x54, 0x21, 0xf9, + 0xcb, 0x13, 0x66, 0xbe, 0x03, 0xdb, 0xae, 0x76, 0x44, 0x9c, + 0xe9, 0x31, 0x8d, 0x55, 0x20, 0xf8, 0xca, 0x12, 0x67, 0xbf, + 0x04, 0xdc, 0xa9, 0x71, 0x43, 0x9b, 0xee, 0x36, 0x8a, 0x52, + 0x27, 0xff, 0xcd, 0x15, 0x60, 0xb8, 0x05, 0xdd, 0xa8, 0x70, + 0x42, 0x9a, 0xef, 0x37, 0x8b, 0x53, 0x26, 0xfe, 0xcc, 0x14, + 0x61, 0xb9, 0x06, 0xde, 0xab, 0x73, 0x41, 0x99, 0xec, 0x34, + 0x88, 0x50, 0x25, 0xfd, 0xcf, 0x17, 0x62, 0xba, 0x07, 0xdf, + 0xaa, 0x72, 0x40, 0x98, 0xed, 0x35, 0x89, 0x51, 0x24, 0xfc, + 0xce, 0x16, 0x63, 0xbb, 0x08, 0xd0, 0xa5, 0x7d, 0x4f, 0x97, + 0xe2, 0x3a, 0x86, 0x5e, 0x2b, 0xf3, 0xc1, 0x19, 0x6c, 0xb4, + 0x09, 0xd1, 0xa4, 0x7c, 0x4e, 0x96, 0xe3, 0x3b, 0x87, 0x5f, + 0x2a, 0xf2, 0xc0, 0x18, 0x6d, 0xb5, 0x0a, 0xd2, 0xa7, 0x7f, + 0x4d, 0x95, 0xe0, 0x38, 0x84, 0x5c, 0x29, 0xf1, 0xc3, 0x1b, + 0x6e, 0xb6, 0x0b, 0xd3, 0xa6, 0x7e, 0x4c, 0x94, 0xe1, 0x39, + 0x85, 0x5d, 0x28, 0xf0, 0xc2, 0x1a, 0x6f, 0xb7, 0x0c, 0xd4, + 0xa1, 0x79, 0x4b, 0x93, 0xe6, 0x3e, 0x82, 0x5a, 0x2f, 0xf7, + 0xc5, 0x1d, 0x68, 0xb0, 0x0d, 0xd5, 0xa0, 0x78, 0x4a, 0x92, + 0xe7, 0x3f, 0x83, 0x5b, 0x2e, 0xf6, 0xc4, 0x1c, 0x69, 0xb1, + 0x0e, 0xd6, 0xa3, 0x7b, 0x49, 0x91, 0xe4, 0x3c, 0x80, 0x58, + 0x2d, 0xf5, 0xc7, 0x1f, 0x6a, 0xb2, 0x0f, 0xd7, 0xa2, 0x7a, + 0x48, 0x90, 0xe5, 0x3d, 0x81, 0x59, 0x2c, 0xf4, 0xc6, 0x1e, + 0x6b, 0xb3, 0x00, 0xd9, 0xaf, 0x76, 0x43, 0x9a, 0xec, 0x35, + 0x86, 0x5f, 0x29, 0xf0, 0xc5, 0x1c, 0x6a, 0xb3, 0x11, 0xc8, + 0xbe, 0x67, 0x52, 0x8b, 0xfd, 0x24, 0x97, 0x4e, 0x38, 0xe1, + 0xd4, 0x0d, 0x7b, 0xa2, 0x22, 0xfb, 0x8d, 0x54, 0x61, 0xb8, + 0xce, 0x17, 0xa4, 0x7d, 0x0b, 0xd2, 0xe7, 0x3e, 0x48, 0x91, + 0x33, 0xea, 0x9c, 0x45, 0x70, 0xa9, 0xdf, 0x06, 0xb5, 0x6c, + 0x1a, 0xc3, 0xf6, 0x2f, 0x59, 0x80, 0x44, 0x9d, 0xeb, 0x32, + 0x07, 0xde, 0xa8, 0x71, 0xc2, 0x1b, 0x6d, 0xb4, 0x81, 0x58, + 0x2e, 0xf7, 0x55, 0x8c, 0xfa, 0x23, 0x16, 0xcf, 0xb9, 0x60, + 0xd3, 0x0a, 0x7c, 0xa5, 0x90, 0x49, 0x3f, 0xe6, 0x66, 0xbf, + 0xc9, 0x10, 0x25, 0xfc, 0x8a, 0x53, 0xe0, 0x39, 0x4f, 0x96, + 0xa3, 0x7a, 0x0c, 0xd5, 0x77, 0xae, 0xd8, 0x01, 0x34, 0xed, + 0x9b, 0x42, 0xf1, 0x28, 0x5e, 0x87, 0xb2, 0x6b, 0x1d, 0xc4, + 0x88, 0x51, 0x27, 0xfe, 0xcb, 0x12, 0x64, 0xbd, 0x0e, 0xd7, + 0xa1, 0x78, 0x4d, 0x94, 0xe2, 0x3b, 0x99, 0x40, 0x36, 0xef, + 0xda, 0x03, 0x75, 0xac, 0x1f, 0xc6, 0xb0, 0x69, 0x5c, 0x85, + 0xf3, 0x2a, 0xaa, 0x73, 0x05, 0xdc, 0xe9, 0x30, 0x46, 0x9f, + 0x2c, 0xf5, 0x83, 0x5a, 0x6f, 0xb6, 0xc0, 0x19, 0xbb, 0x62, + 0x14, 0xcd, 0xf8, 0x21, 0x57, 0x8e, 0x3d, 0xe4, 0x92, 0x4b, + 0x7e, 0xa7, 0xd1, 0x08, 0xcc, 0x15, 0x63, 0xba, 0x8f, 0x56, + 0x20, 0xf9, 0x4a, 0x93, 0xe5, 0x3c, 0x09, 0xd0, 0xa6, 0x7f, + 0xdd, 0x04, 0x72, 0xab, 0x9e, 0x47, 0x31, 0xe8, 0x5b, 0x82, + 0xf4, 0x2d, 0x18, 0xc1, 0xb7, 0x6e, 0xee, 0x37, 0x41, 0x98, + 0xad, 0x74, 0x02, 0xdb, 0x68, 0xb1, 0xc7, 0x1e, 0x2b, 0xf2, + 0x84, 0x5d, 0xff, 0x26, 0x50, 0x89, 0xbc, 0x65, 0x13, 0xca, + 0x79, 0xa0, 0xd6, 0x0f, 0x3a, 0xe3, 0x95, 0x4c, 0x00, 0xda, + 0xa9, 0x73, 0x4f, 0x95, 0xe6, 0x3c, 0x9e, 0x44, 0x37, 0xed, + 0xd1, 0x0b, 0x78, 0xa2, 0x21, 0xfb, 0x88, 0x52, 0x6e, 0xb4, + 0xc7, 0x1d, 0xbf, 0x65, 0x16, 0xcc, 0xf0, 0x2a, 0x59, 0x83, + 0x42, 0x98, 0xeb, 0x31, 0x0d, 0xd7, 0xa4, 0x7e, 0xdc, 0x06, + 0x75, 0xaf, 0x93, 0x49, 0x3a, 0xe0, 0x63, 0xb9, 0xca, 0x10, + 0x2c, 0xf6, 0x85, 0x5f, 0xfd, 0x27, 0x54, 0x8e, 0xb2, 0x68, + 0x1b, 0xc1, 0x84, 0x5e, 0x2d, 0xf7, 0xcb, 0x11, 0x62, 0xb8, + 0x1a, 0xc0, 0xb3, 0x69, 0x55, 0x8f, 0xfc, 0x26, 0xa5, 0x7f, + 0x0c, 0xd6, 0xea, 0x30, 0x43, 0x99, 0x3b, 0xe1, 0x92, 0x48, + 0x74, 0xae, 0xdd, 0x07, 0xc6, 0x1c, 0x6f, 0xb5, 0x89, 0x53, + 0x20, 0xfa, 0x58, 0x82, 0xf1, 0x2b, 0x17, 0xcd, 0xbe, 0x64, + 0xe7, 0x3d, 0x4e, 0x94, 0xa8, 0x72, 0x01, 0xdb, 0x79, 0xa3, + 0xd0, 0x0a, 0x36, 0xec, 0x9f, 0x45, 0x15, 0xcf, 0xbc, 0x66, + 0x5a, 0x80, 0xf3, 0x29, 0x8b, 0x51, 0x22, 0xf8, 0xc4, 0x1e, + 0x6d, 0xb7, 0x34, 0xee, 0x9d, 0x47, 0x7b, 0xa1, 0xd2, 0x08, + 0xaa, 0x70, 0x03, 0xd9, 0xe5, 0x3f, 0x4c, 0x96, 0x57, 0x8d, + 0xfe, 0x24, 0x18, 0xc2, 0xb1, 0x6b, 0xc9, 0x13, 0x60, 0xba, + 0x86, 0x5c, 0x2f, 0xf5, 0x76, 0xac, 0xdf, 0x05, 0x39, 0xe3, + 0x90, 0x4a, 0xe8, 0x32, 0x41, 0x9b, 0xa7, 0x7d, 0x0e, 0xd4, + 0x91, 0x4b, 0x38, 0xe2, 0xde, 0x04, 0x77, 0xad, 0x0f, 0xd5, + 0xa6, 0x7c, 0x40, 0x9a, 0xe9, 0x33, 0xb0, 0x6a, 0x19, 0xc3, + 0xff, 0x25, 0x56, 0x8c, 0x2e, 0xf4, 0x87, 0x5d, 0x61, 0xbb, + 0xc8, 0x12, 0xd3, 0x09, 0x7a, 0xa0, 0x9c, 0x46, 0x35, 0xef, + 0x4d, 0x97, 0xe4, 0x3e, 0x02, 0xd8, 0xab, 0x71, 0xf2, 0x28, + 0x5b, 0x81, 0xbd, 0x67, 0x14, 0xce, 0x6c, 0xb6, 0xc5, 0x1f, + 0x23, 0xf9, 0x8a, 0x50, 0x00, 0xdb, 0xab, 0x70, 0x4b, 0x90, + 0xe0, 0x3b, 0x96, 0x4d, 0x3d, 0xe6, 0xdd, 0x06, 0x76, 0xad, + 0x31, 0xea, 0x9a, 0x41, 0x7a, 0xa1, 0xd1, 0x0a, 0xa7, 0x7c, + 0x0c, 0xd7, 0xec, 0x37, 0x47, 0x9c, 0x62, 0xb9, 0xc9, 0x12, + 0x29, 0xf2, 0x82, 0x59, 0xf4, 0x2f, 0x5f, 0x84, 0xbf, 0x64, + 0x14, 0xcf, 0x53, 0x88, 0xf8, 0x23, 0x18, 0xc3, 0xb3, 0x68, + 0xc5, 0x1e, 0x6e, 0xb5, 0x8e, 0x55, 0x25, 0xfe, 0xc4, 0x1f, + 0x6f, 0xb4, 0x8f, 0x54, 0x24, 0xff, 0x52, 0x89, 0xf9, 0x22, + 0x19, 0xc2, 0xb2, 0x69, 0xf5, 0x2e, 0x5e, 0x85, 0xbe, 0x65, + 0x15, 0xce, 0x63, 0xb8, 0xc8, 0x13, 0x28, 0xf3, 0x83, 0x58, + 0xa6, 0x7d, 0x0d, 0xd6, 0xed, 0x36, 0x46, 0x9d, 0x30, 0xeb, + 0x9b, 0x40, 0x7b, 0xa0, 0xd0, 0x0b, 0x97, 0x4c, 0x3c, 0xe7, + 0xdc, 0x07, 0x77, 0xac, 0x01, 0xda, 0xaa, 0x71, 0x4a, 0x91, + 0xe1, 0x3a, 0x95, 0x4e, 0x3e, 0xe5, 0xde, 0x05, 0x75, 0xae, + 0x03, 0xd8, 0xa8, 0x73, 0x48, 0x93, 0xe3, 0x38, 0xa4, 0x7f, + 0x0f, 0xd4, 0xef, 0x34, 0x44, 0x9f, 0x32, 0xe9, 0x99, 0x42, + 0x79, 0xa2, 0xd2, 0x09, 0xf7, 0x2c, 0x5c, 0x87, 0xbc, 0x67, + 0x17, 0xcc, 0x61, 0xba, 0xca, 0x11, 0x2a, 0xf1, 0x81, 0x5a, + 0xc6, 0x1d, 0x6d, 0xb6, 0x8d, 0x56, 0x26, 0xfd, 0x50, 0x8b, + 0xfb, 0x20, 0x1b, 0xc0, 0xb0, 0x6b, 0x51, 0x8a, 0xfa, 0x21, + 0x1a, 0xc1, 0xb1, 0x6a, 0xc7, 0x1c, 0x6c, 0xb7, 0x8c, 0x57, + 0x27, 0xfc, 0x60, 0xbb, 0xcb, 0x10, 0x2b, 0xf0, 0x80, 0x5b, + 0xf6, 0x2d, 0x5d, 0x86, 0xbd, 0x66, 0x16, 0xcd, 0x33, 0xe8, + 0x98, 0x43, 0x78, 0xa3, 0xd3, 0x08, 0xa5, 0x7e, 0x0e, 0xd5, + 0xee, 0x35, 0x45, 0x9e, 0x02, 0xd9, 0xa9, 0x72, 0x49, 0x92, + 0xe2, 0x39, 0x94, 0x4f, 0x3f, 0xe4, 0xdf, 0x04, 0x74, 0xaf, + 0x00, 0xdc, 0xa5, 0x79, 0x57, 0x8b, 0xf2, 0x2e, 0xae, 0x72, + 0x0b, 0xd7, 0xf9, 0x25, 0x5c, 0x80, 0x41, 0x9d, 0xe4, 0x38, + 0x16, 0xca, 0xb3, 0x6f, 0xef, 0x33, 0x4a, 0x96, 0xb8, 0x64, + 0x1d, 0xc1, 0x82, 0x5e, 0x27, 0xfb, 0xd5, 0x09, 0x70, 0xac, + 0x2c, 0xf0, 0x89, 0x55, 0x7b, 0xa7, 0xde, 0x02, 0xc3, 0x1f, + 0x66, 0xba, 0x94, 0x48, 0x31, 0xed, 0x6d, 0xb1, 0xc8, 0x14, + 0x3a, 0xe6, 0x9f, 0x43, 0x19, 0xc5, 0xbc, 0x60, 0x4e, 0x92, + 0xeb, 0x37, 0xb7, 0x6b, 0x12, 0xce, 0xe0, 0x3c, 0x45, 0x99, + 0x58, 0x84, 0xfd, 0x21, 0x0f, 0xd3, 0xaa, 0x76, 0xf6, 0x2a, + 0x53, 0x8f, 0xa1, 0x7d, 0x04, 0xd8, 0x9b, 0x47, 0x3e, 0xe2, + 0xcc, 0x10, 0x69, 0xb5, 0x35, 0xe9, 0x90, 0x4c, 0x62, 0xbe, + 0xc7, 0x1b, 0xda, 0x06, 0x7f, 0xa3, 0x8d, 0x51, 0x28, 0xf4, + 0x74, 0xa8, 0xd1, 0x0d, 0x23, 0xff, 0x86, 0x5a, 0x32, 0xee, + 0x97, 0x4b, 0x65, 0xb9, 0xc0, 0x1c, 0x9c, 0x40, 0x39, 0xe5, + 0xcb, 0x17, 0x6e, 0xb2, 0x73, 0xaf, 0xd6, 0x0a, 0x24, 0xf8, + 0x81, 0x5d, 0xdd, 0x01, 0x78, 0xa4, 0x8a, 0x56, 0x2f, 0xf3, + 0xb0, 0x6c, 0x15, 0xc9, 0xe7, 0x3b, 0x42, 0x9e, 0x1e, 0xc2, + 0xbb, 0x67, 0x49, 0x95, 0xec, 0x30, 0xf1, 0x2d, 0x54, 0x88, + 0xa6, 0x7a, 0x03, 0xdf, 0x5f, 0x83, 0xfa, 0x26, 0x08, 0xd4, + 0xad, 0x71, 0x2b, 0xf7, 0x8e, 0x52, 0x7c, 0xa0, 0xd9, 0x05, + 0x85, 0x59, 0x20, 0xfc, 0xd2, 0x0e, 0x77, 0xab, 0x6a, 0xb6, + 0xcf, 0x13, 0x3d, 0xe1, 0x98, 0x44, 0xc4, 0x18, 0x61, 0xbd, + 0x93, 0x4f, 0x36, 0xea, 0xa9, 0x75, 0x0c, 0xd0, 0xfe, 0x22, + 0x5b, 0x87, 0x07, 0xdb, 0xa2, 0x7e, 0x50, 0x8c, 0xf5, 0x29, + 0xe8, 0x34, 0x4d, 0x91, 0xbf, 0x63, 0x1a, 0xc6, 0x46, 0x9a, + 0xe3, 0x3f, 0x11, 0xcd, 0xb4, 0x68, 0x00, 0xdd, 0xa7, 0x7a, + 0x53, 0x8e, 0xf4, 0x29, 0xa6, 0x7b, 0x01, 0xdc, 0xf5, 0x28, + 0x52, 0x8f, 0x51, 0x8c, 0xf6, 0x2b, 0x02, 0xdf, 0xa5, 0x78, + 0xf7, 0x2a, 0x50, 0x8d, 0xa4, 0x79, 0x03, 0xde, 0xa2, 0x7f, + 0x05, 0xd8, 0xf1, 0x2c, 0x56, 0x8b, 0x04, 0xd9, 0xa3, 0x7e, + 0x57, 0x8a, 0xf0, 0x2d, 0xf3, 0x2e, 0x54, 0x89, 0xa0, 0x7d, + 0x07, 0xda, 0x55, 0x88, 0xf2, 0x2f, 0x06, 0xdb, 0xa1, 0x7c, + 0x59, 0x84, 0xfe, 0x23, 0x0a, 0xd7, 0xad, 0x70, 0xff, 0x22, + 0x58, 0x85, 0xac, 0x71, 0x0b, 0xd6, 0x08, 0xd5, 0xaf, 0x72, + 0x5b, 0x86, 0xfc, 0x21, 0xae, 0x73, 0x09, 0xd4, 0xfd, 0x20, + 0x5a, 0x87, 0xfb, 0x26, 0x5c, 0x81, 0xa8, 0x75, 0x0f, 0xd2, + 0x5d, 0x80, 0xfa, 0x27, 0x0e, 0xd3, 0xa9, 0x74, 0xaa, 0x77, + 0x0d, 0xd0, 0xf9, 0x24, 0x5e, 0x83, 0x0c, 0xd1, 0xab, 0x76, + 0x5f, 0x82, 0xf8, 0x25, 0xb2, 0x6f, 0x15, 0xc8, 0xe1, 0x3c, + 0x46, 0x9b, 0x14, 0xc9, 0xb3, 0x6e, 0x47, 0x9a, 0xe0, 0x3d, + 0xe3, 0x3e, 0x44, 0x99, 0xb0, 0x6d, 0x17, 0xca, 0x45, 0x98, + 0xe2, 0x3f, 0x16, 0xcb, 0xb1, 0x6c, 0x10, 0xcd, 0xb7, 0x6a, + 0x43, 0x9e, 0xe4, 0x39, 0xb6, 0x6b, 0x11, 0xcc, 0xe5, 0x38, + 0x42, 0x9f, 0x41, 0x9c, 0xe6, 0x3b, 0x12, 0xcf, 0xb5, 0x68, + 0xe7, 0x3a, 0x40, 0x9d, 0xb4, 0x69, 0x13, 0xce, 0xeb, 0x36, + 0x4c, 0x91, 0xb8, 0x65, 0x1f, 0xc2, 0x4d, 0x90, 0xea, 0x37, + 0x1e, 0xc3, 0xb9, 0x64, 0xba, 0x67, 0x1d, 0xc0, 0xe9, 0x34, + 0x4e, 0x93, 0x1c, 0xc1, 0xbb, 0x66, 0x4f, 0x92, 0xe8, 0x35, + 0x49, 0x94, 0xee, 0x33, 0x1a, 0xc7, 0xbd, 0x60, 0xef, 0x32, + 0x48, 0x95, 0xbc, 0x61, 0x1b, 0xc6, 0x18, 0xc5, 0xbf, 0x62, + 0x4b, 0x96, 0xec, 0x31, 0xbe, 0x63, 0x19, 0xc4, 0xed, 0x30, + 0x4a, 0x97, 0x00, 0xde, 0xa1, 0x7f, 0x5f, 0x81, 0xfe, 0x20, + 0xbe, 0x60, 0x1f, 0xc1, 0xe1, 0x3f, 0x40, 0x9e, 0x61, 0xbf, + 0xc0, 0x1e, 0x3e, 0xe0, 0x9f, 0x41, 0xdf, 0x01, 0x7e, 0xa0, + 0x80, 0x5e, 0x21, 0xff, 0xc2, 0x1c, 0x63, 0xbd, 0x9d, 0x43, + 0x3c, 0xe2, 0x7c, 0xa2, 0xdd, 0x03, 0x23, 0xfd, 0x82, 0x5c, + 0xa3, 0x7d, 0x02, 0xdc, 0xfc, 0x22, 0x5d, 0x83, 0x1d, 0xc3, + 0xbc, 0x62, 0x42, 0x9c, 0xe3, 0x3d, 0x99, 0x47, 0x38, 0xe6, + 0xc6, 0x18, 0x67, 0xb9, 0x27, 0xf9, 0x86, 0x58, 0x78, 0xa6, + 0xd9, 0x07, 0xf8, 0x26, 0x59, 0x87, 0xa7, 0x79, 0x06, 0xd8, + 0x46, 0x98, 0xe7, 0x39, 0x19, 0xc7, 0xb8, 0x66, 0x5b, 0x85, + 0xfa, 0x24, 0x04, 0xda, 0xa5, 0x7b, 0xe5, 0x3b, 0x44, 0x9a, + 0xba, 0x64, 0x1b, 0xc5, 0x3a, 0xe4, 0x9b, 0x45, 0x65, 0xbb, + 0xc4, 0x1a, 0x84, 0x5a, 0x25, 0xfb, 0xdb, 0x05, 0x7a, 0xa4, + 0x2f, 0xf1, 0x8e, 0x50, 0x70, 0xae, 0xd1, 0x0f, 0x91, 0x4f, + 0x30, 0xee, 0xce, 0x10, 0x6f, 0xb1, 0x4e, 0x90, 0xef, 0x31, + 0x11, 0xcf, 0xb0, 0x6e, 0xf0, 0x2e, 0x51, 0x8f, 0xaf, 0x71, + 0x0e, 0xd0, 0xed, 0x33, 0x4c, 0x92, 0xb2, 0x6c, 0x13, 0xcd, + 0x53, 0x8d, 0xf2, 0x2c, 0x0c, 0xd2, 0xad, 0x73, 0x8c, 0x52, + 0x2d, 0xf3, 0xd3, 0x0d, 0x72, 0xac, 0x32, 0xec, 0x93, 0x4d, + 0x6d, 0xb3, 0xcc, 0x12, 0xb6, 0x68, 0x17, 0xc9, 0xe9, 0x37, + 0x48, 0x96, 0x08, 0xd6, 0xa9, 0x77, 0x57, 0x89, 0xf6, 0x28, + 0xd7, 0x09, 0x76, 0xa8, 0x88, 0x56, 0x29, 0xf7, 0x69, 0xb7, + 0xc8, 0x16, 0x36, 0xe8, 0x97, 0x49, 0x74, 0xaa, 0xd5, 0x0b, + 0x2b, 0xf5, 0x8a, 0x54, 0xca, 0x14, 0x6b, 0xb5, 0x95, 0x4b, + 0x34, 0xea, 0x15, 0xcb, 0xb4, 0x6a, 0x4a, 0x94, 0xeb, 0x35, + 0xab, 0x75, 0x0a, 0xd4, 0xf4, 0x2a, 0x55, 0x8b, 0x00, 0xdf, + 0xa3, 0x7c, 0x5b, 0x84, 0xf8, 0x27, 0xb6, 0x69, 0x15, 0xca, + 0xed, 0x32, 0x4e, 0x91, 0x71, 0xae, 0xd2, 0x0d, 0x2a, 0xf5, + 0x89, 0x56, 0xc7, 0x18, 0x64, 0xbb, 0x9c, 0x43, 0x3f, 0xe0, + 0xe2, 0x3d, 0x41, 0x9e, 0xb9, 0x66, 0x1a, 0xc5, 0x54, 0x8b, + 0xf7, 0x28, 0x0f, 0xd0, 0xac, 0x73, 0x93, 0x4c, 0x30, 0xef, + 0xc8, 0x17, 0x6b, 0xb4, 0x25, 0xfa, 0x86, 0x59, 0x7e, 0xa1, + 0xdd, 0x02, 0xd9, 0x06, 0x7a, 0xa5, 0x82, 0x5d, 0x21, 0xfe, + 0x6f, 0xb0, 0xcc, 0x13, 0x34, 0xeb, 0x97, 0x48, 0xa8, 0x77, + 0x0b, 0xd4, 0xf3, 0x2c, 0x50, 0x8f, 0x1e, 0xc1, 0xbd, 0x62, + 0x45, 0x9a, 0xe6, 0x39, 0x3b, 0xe4, 0x98, 0x47, 0x60, 0xbf, + 0xc3, 0x1c, 0x8d, 0x52, 0x2e, 0xf1, 0xd6, 0x09, 0x75, 0xaa, + 0x4a, 0x95, 0xe9, 0x36, 0x11, 0xce, 0xb2, 0x6d, 0xfc, 0x23, + 0x5f, 0x80, 0xa7, 0x78, 0x04, 0xdb, 0xaf, 0x70, 0x0c, 0xd3, + 0xf4, 0x2b, 0x57, 0x88, 0x19, 0xc6, 0xba, 0x65, 0x42, 0x9d, + 0xe1, 0x3e, 0xde, 0x01, 0x7d, 0xa2, 0x85, 0x5a, 0x26, 0xf9, + 0x68, 0xb7, 0xcb, 0x14, 0x33, 0xec, 0x90, 0x4f, 0x4d, 0x92, + 0xee, 0x31, 0x16, 0xc9, 0xb5, 0x6a, 0xfb, 0x24, 0x58, 0x87, + 0xa0, 0x7f, 0x03, 0xdc, 0x3c, 0xe3, 0x9f, 0x40, 0x67, 0xb8, + 0xc4, 0x1b, 0x8a, 0x55, 0x29, 0xf6, 0xd1, 0x0e, 0x72, 0xad, + 0x76, 0xa9, 0xd5, 0x0a, 0x2d, 0xf2, 0x8e, 0x51, 0xc0, 0x1f, + 0x63, 0xbc, 0x9b, 0x44, 0x38, 0xe7, 0x07, 0xd8, 0xa4, 0x7b, + 0x5c, 0x83, 0xff, 0x20, 0xb1, 0x6e, 0x12, 0xcd, 0xea, 0x35, + 0x49, 0x96, 0x94, 0x4b, 0x37, 0xe8, 0xcf, 0x10, 0x6c, 0xb3, + 0x22, 0xfd, 0x81, 0x5e, 0x79, 0xa6, 0xda, 0x05, 0xe5, 0x3a, + 0x46, 0x99, 0xbe, 0x61, 0x1d, 0xc2, 0x53, 0x8c, 0xf0, 0x2f, + 0x08, 0xd7, 0xab, 0x74, 0x00, 0xe0, 0xdd, 0x3d, 0xa7, 0x47, + 0x7a, 0x9a, 0x53, 0xb3, 0x8e, 0x6e, 0xf4, 0x14, 0x29, 0xc9, + 0xa6, 0x46, 0x7b, 0x9b, 0x01, 0xe1, 0xdc, 0x3c, 0xf5, 0x15, + 0x28, 0xc8, 0x52, 0xb2, 0x8f, 0x6f, 0x51, 0xb1, 0x8c, 0x6c, + 0xf6, 0x16, 0x2b, 0xcb, 0x02, 0xe2, 0xdf, 0x3f, 0xa5, 0x45, + 0x78, 0x98, 0xf7, 0x17, 0x2a, 0xca, 0x50, 0xb0, 0x8d, 0x6d, + 0xa4, 0x44, 0x79, 0x99, 0x03, 0xe3, 0xde, 0x3e, 0xa2, 0x42, + 0x7f, 0x9f, 0x05, 0xe5, 0xd8, 0x38, 0xf1, 0x11, 0x2c, 0xcc, + 0x56, 0xb6, 0x8b, 0x6b, 0x04, 0xe4, 0xd9, 0x39, 0xa3, 0x43, + 0x7e, 0x9e, 0x57, 0xb7, 0x8a, 0x6a, 0xf0, 0x10, 0x2d, 0xcd, + 0xf3, 0x13, 0x2e, 0xce, 0x54, 0xb4, 0x89, 0x69, 0xa0, 0x40, + 0x7d, 0x9d, 0x07, 0xe7, 0xda, 0x3a, 0x55, 0xb5, 0x88, 0x68, + 0xf2, 0x12, 0x2f, 0xcf, 0x06, 0xe6, 0xdb, 0x3b, 0xa1, 0x41, + 0x7c, 0x9c, 0x59, 0xb9, 0x84, 0x64, 0xfe, 0x1e, 0x23, 0xc3, + 0x0a, 0xea, 0xd7, 0x37, 0xad, 0x4d, 0x70, 0x90, 0xff, 0x1f, + 0x22, 0xc2, 0x58, 0xb8, 0x85, 0x65, 0xac, 0x4c, 0x71, 0x91, + 0x0b, 0xeb, 0xd6, 0x36, 0x08, 0xe8, 0xd5, 0x35, 0xaf, 0x4f, + 0x72, 0x92, 0x5b, 0xbb, 0x86, 0x66, 0xfc, 0x1c, 0x21, 0xc1, + 0xae, 0x4e, 0x73, 0x93, 0x09, 0xe9, 0xd4, 0x34, 0xfd, 0x1d, + 0x20, 0xc0, 0x5a, 0xba, 0x87, 0x67, 0xfb, 0x1b, 0x26, 0xc6, + 0x5c, 0xbc, 0x81, 0x61, 0xa8, 0x48, 0x75, 0x95, 0x0f, 0xef, + 0xd2, 0x32, 0x5d, 0xbd, 0x80, 0x60, 0xfa, 0x1a, 0x27, 0xc7, + 0x0e, 0xee, 0xd3, 0x33, 0xa9, 0x49, 0x74, 0x94, 0xaa, 0x4a, + 0x77, 0x97, 0x0d, 0xed, 0xd0, 0x30, 0xf9, 0x19, 0x24, 0xc4, + 0x5e, 0xbe, 0x83, 0x63, 0x0c, 0xec, 0xd1, 0x31, 0xab, 0x4b, + 0x76, 0x96, 0x5f, 0xbf, 0x82, 0x62, 0xf8, 0x18, 0x25, 0xc5, + 0x00, 0xe1, 0xdf, 0x3e, 0xa3, 0x42, 0x7c, 0x9d, 0x5b, 0xba, + 0x84, 0x65, 0xf8, 0x19, 0x27, 0xc6, 0xb6, 0x57, 0x69, 0x88, + 0x15, 0xf4, 0xca, 0x2b, 0xed, 0x0c, 0x32, 0xd3, 0x4e, 0xaf, + 0x91, 0x70, 0x71, 0x90, 0xae, 0x4f, 0xd2, 0x33, 0x0d, 0xec, + 0x2a, 0xcb, 0xf5, 0x14, 0x89, 0x68, 0x56, 0xb7, 0xc7, 0x26, + 0x18, 0xf9, 0x64, 0x85, 0xbb, 0x5a, 0x9c, 0x7d, 0x43, 0xa2, + 0x3f, 0xde, 0xe0, 0x01, 0xe2, 0x03, 0x3d, 0xdc, 0x41, 0xa0, + 0x9e, 0x7f, 0xb9, 0x58, 0x66, 0x87, 0x1a, 0xfb, 0xc5, 0x24, + 0x54, 0xb5, 0x8b, 0x6a, 0xf7, 0x16, 0x28, 0xc9, 0x0f, 0xee, + 0xd0, 0x31, 0xac, 0x4d, 0x73, 0x92, 0x93, 0x72, 0x4c, 0xad, + 0x30, 0xd1, 0xef, 0x0e, 0xc8, 0x29, 0x17, 0xf6, 0x6b, 0x8a, + 0xb4, 0x55, 0x25, 0xc4, 0xfa, 0x1b, 0x86, 0x67, 0x59, 0xb8, + 0x7e, 0x9f, 0xa1, 0x40, 0xdd, 0x3c, 0x02, 0xe3, 0xd9, 0x38, + 0x06, 0xe7, 0x7a, 0x9b, 0xa5, 0x44, 0x82, 0x63, 0x5d, 0xbc, + 0x21, 0xc0, 0xfe, 0x1f, 0x6f, 0x8e, 0xb0, 0x51, 0xcc, 0x2d, + 0x13, 0xf2, 0x34, 0xd5, 0xeb, 0x0a, 0x97, 0x76, 0x48, 0xa9, + 0xa8, 0x49, 0x77, 0x96, 0x0b, 0xea, 0xd4, 0x35, 0xf3, 0x12, + 0x2c, 0xcd, 0x50, 0xb1, 0x8f, 0x6e, 0x1e, 0xff, 0xc1, 0x20, + 0xbd, 0x5c, 0x62, 0x83, 0x45, 0xa4, 0x9a, 0x7b, 0xe6, 0x07, + 0x39, 0xd8, 0x3b, 0xda, 0xe4, 0x05, 0x98, 0x79, 0x47, 0xa6, + 0x60, 0x81, 0xbf, 0x5e, 0xc3, 0x22, 0x1c, 0xfd, 0x8d, 0x6c, + 0x52, 0xb3, 0x2e, 0xcf, 0xf1, 0x10, 0xd6, 0x37, 0x09, 0xe8, + 0x75, 0x94, 0xaa, 0x4b, 0x4a, 0xab, 0x95, 0x74, 0xe9, 0x08, + 0x36, 0xd7, 0x11, 0xf0, 0xce, 0x2f, 0xb2, 0x53, 0x6d, 0x8c, + 0xfc, 0x1d, 0x23, 0xc2, 0x5f, 0xbe, 0x80, 0x61, 0xa7, 0x46, + 0x78, 0x99, 0x04, 0xe5, 0xdb, 0x3a, 0x00, 0xe2, 0xd9, 0x3b, + 0xaf, 0x4d, 0x76, 0x94, 0x43, 0xa1, 0x9a, 0x78, 0xec, 0x0e, + 0x35, 0xd7, 0x86, 0x64, 0x5f, 0xbd, 0x29, 0xcb, 0xf0, 0x12, + 0xc5, 0x27, 0x1c, 0xfe, 0x6a, 0x88, 0xb3, 0x51, 0x11, 0xf3, + 0xc8, 0x2a, 0xbe, 0x5c, 0x67, 0x85, 0x52, 0xb0, 0x8b, 0x69, + 0xfd, 0x1f, 0x24, 0xc6, 0x97, 0x75, 0x4e, 0xac, 0x38, 0xda, + 0xe1, 0x03, 0xd4, 0x36, 0x0d, 0xef, 0x7b, 0x99, 0xa2, 0x40, + 0x22, 0xc0, 0xfb, 0x19, 0x8d, 0x6f, 0x54, 0xb6, 0x61, 0x83, + 0xb8, 0x5a, 0xce, 0x2c, 0x17, 0xf5, 0xa4, 0x46, 0x7d, 0x9f, + 0x0b, 0xe9, 0xd2, 0x30, 0xe7, 0x05, 0x3e, 0xdc, 0x48, 0xaa, + 0x91, 0x73, 0x33, 0xd1, 0xea, 0x08, 0x9c, 0x7e, 0x45, 0xa7, + 0x70, 0x92, 0xa9, 0x4b, 0xdf, 0x3d, 0x06, 0xe4, 0xb5, 0x57, + 0x6c, 0x8e, 0x1a, 0xf8, 0xc3, 0x21, 0xf6, 0x14, 0x2f, 0xcd, + 0x59, 0xbb, 0x80, 0x62, 0x44, 0xa6, 0x9d, 0x7f, 0xeb, 0x09, + 0x32, 0xd0, 0x07, 0xe5, 0xde, 0x3c, 0xa8, 0x4a, 0x71, 0x93, + 0xc2, 0x20, 0x1b, 0xf9, 0x6d, 0x8f, 0xb4, 0x56, 0x81, 0x63, + 0x58, 0xba, 0x2e, 0xcc, 0xf7, 0x15, 0x55, 0xb7, 0x8c, 0x6e, + 0xfa, 0x18, 0x23, 0xc1, 0x16, 0xf4, 0xcf, 0x2d, 0xb9, 0x5b, + 0x60, 0x82, 0xd3, 0x31, 0x0a, 0xe8, 0x7c, 0x9e, 0xa5, 0x47, + 0x90, 0x72, 0x49, 0xab, 0x3f, 0xdd, 0xe6, 0x04, 0x66, 0x84, + 0xbf, 0x5d, 0xc9, 0x2b, 0x10, 0xf2, 0x25, 0xc7, 0xfc, 0x1e, + 0x8a, 0x68, 0x53, 0xb1, 0xe0, 0x02, 0x39, 0xdb, 0x4f, 0xad, + 0x96, 0x74, 0xa3, 0x41, 0x7a, 0x98, 0x0c, 0xee, 0xd5, 0x37, + 0x77, 0x95, 0xae, 0x4c, 0xd8, 0x3a, 0x01, 0xe3, 0x34, 0xd6, + 0xed, 0x0f, 0x9b, 0x79, 0x42, 0xa0, 0xf1, 0x13, 0x28, 0xca, + 0x5e, 0xbc, 0x87, 0x65, 0xb2, 0x50, 0x6b, 0x89, 0x1d, 0xff, + 0xc4, 0x26, 0x00, 0xe3, 0xdb, 0x38, 0xab, 0x48, 0x70, 0x93, + 0x4b, 0xa8, 0x90, 0x73, 0xe0, 0x03, 0x3b, 0xd8, 0x96, 0x75, + 0x4d, 0xae, 0x3d, 0xde, 0xe6, 0x05, 0xdd, 0x3e, 0x06, 0xe5, + 0x76, 0x95, 0xad, 0x4e, 0x31, 0xd2, 0xea, 0x09, 0x9a, 0x79, + 0x41, 0xa2, 0x7a, 0x99, 0xa1, 0x42, 0xd1, 0x32, 0x0a, 0xe9, + 0xa7, 0x44, 0x7c, 0x9f, 0x0c, 0xef, 0xd7, 0x34, 0xec, 0x0f, + 0x37, 0xd4, 0x47, 0xa4, 0x9c, 0x7f, 0x62, 0x81, 0xb9, 0x5a, + 0xc9, 0x2a, 0x12, 0xf1, 0x29, 0xca, 0xf2, 0x11, 0x82, 0x61, + 0x59, 0xba, 0xf4, 0x17, 0x2f, 0xcc, 0x5f, 0xbc, 0x84, 0x67, + 0xbf, 0x5c, 0x64, 0x87, 0x14, 0xf7, 0xcf, 0x2c, 0x53, 0xb0, + 0x88, 0x6b, 0xf8, 0x1b, 0x23, 0xc0, 0x18, 0xfb, 0xc3, 0x20, + 0xb3, 0x50, 0x68, 0x8b, 0xc5, 0x26, 0x1e, 0xfd, 0x6e, 0x8d, + 0xb5, 0x56, 0x8e, 0x6d, 0x55, 0xb6, 0x25, 0xc6, 0xfe, 0x1d, + 0xc4, 0x27, 0x1f, 0xfc, 0x6f, 0x8c, 0xb4, 0x57, 0x8f, 0x6c, + 0x54, 0xb7, 0x24, 0xc7, 0xff, 0x1c, 0x52, 0xb1, 0x89, 0x6a, + 0xf9, 0x1a, 0x22, 0xc1, 0x19, 0xfa, 0xc2, 0x21, 0xb2, 0x51, + 0x69, 0x8a, 0xf5, 0x16, 0x2e, 0xcd, 0x5e, 0xbd, 0x85, 0x66, + 0xbe, 0x5d, 0x65, 0x86, 0x15, 0xf6, 0xce, 0x2d, 0x63, 0x80, + 0xb8, 0x5b, 0xc8, 0x2b, 0x13, 0xf0, 0x28, 0xcb, 0xf3, 0x10, + 0x83, 0x60, 0x58, 0xbb, 0xa6, 0x45, 0x7d, 0x9e, 0x0d, 0xee, + 0xd6, 0x35, 0xed, 0x0e, 0x36, 0xd5, 0x46, 0xa5, 0x9d, 0x7e, + 0x30, 0xd3, 0xeb, 0x08, 0x9b, 0x78, 0x40, 0xa3, 0x7b, 0x98, + 0xa0, 0x43, 0xd0, 0x33, 0x0b, 0xe8, 0x97, 0x74, 0x4c, 0xaf, + 0x3c, 0xdf, 0xe7, 0x04, 0xdc, 0x3f, 0x07, 0xe4, 0x77, 0x94, + 0xac, 0x4f, 0x01, 0xe2, 0xda, 0x39, 0xaa, 0x49, 0x71, 0x92, + 0x4a, 0xa9, 0x91, 0x72, 0xe1, 0x02, 0x3a, 0xd9, 0x00, 0xe4, + 0xd5, 0x31, 0xb7, 0x53, 0x62, 0x86, 0x73, 0x97, 0xa6, 0x42, + 0xc4, 0x20, 0x11, 0xf5, 0xe6, 0x02, 0x33, 0xd7, 0x51, 0xb5, + 0x84, 0x60, 0x95, 0x71, 0x40, 0xa4, 0x22, 0xc6, 0xf7, 0x13, + 0xd1, 0x35, 0x04, 0xe0, 0x66, 0x82, 0xb3, 0x57, 0xa2, 0x46, + 0x77, 0x93, 0x15, 0xf1, 0xc0, 0x24, 0x37, 0xd3, 0xe2, 0x06, + 0x80, 0x64, 0x55, 0xb1, 0x44, 0xa0, 0x91, 0x75, 0xf3, 0x17, + 0x26, 0xc2, 0xbf, 0x5b, 0x6a, 0x8e, 0x08, 0xec, 0xdd, 0x39, + 0xcc, 0x28, 0x19, 0xfd, 0x7b, 0x9f, 0xae, 0x4a, 0x59, 0xbd, + 0x8c, 0x68, 0xee, 0x0a, 0x3b, 0xdf, 0x2a, 0xce, 0xff, 0x1b, + 0x9d, 0x79, 0x48, 0xac, 0x6e, 0x8a, 0xbb, 0x5f, 0xd9, 0x3d, + 0x0c, 0xe8, 0x1d, 0xf9, 0xc8, 0x2c, 0xaa, 0x4e, 0x7f, 0x9b, + 0x88, 0x6c, 0x5d, 0xb9, 0x3f, 0xdb, 0xea, 0x0e, 0xfb, 0x1f, + 0x2e, 0xca, 0x4c, 0xa8, 0x99, 0x7d, 0x63, 0x87, 0xb6, 0x52, + 0xd4, 0x30, 0x01, 0xe5, 0x10, 0xf4, 0xc5, 0x21, 0xa7, 0x43, + 0x72, 0x96, 0x85, 0x61, 0x50, 0xb4, 0x32, 0xd6, 0xe7, 0x03, + 0xf6, 0x12, 0x23, 0xc7, 0x41, 0xa5, 0x94, 0x70, 0xb2, 0x56, + 0x67, 0x83, 0x05, 0xe1, 0xd0, 0x34, 0xc1, 0x25, 0x14, 0xf0, + 0x76, 0x92, 0xa3, 0x47, 0x54, 0xb0, 0x81, 0x65, 0xe3, 0x07, + 0x36, 0xd2, 0x27, 0xc3, 0xf2, 0x16, 0x90, 0x74, 0x45, 0xa1, + 0xdc, 0x38, 0x09, 0xed, 0x6b, 0x8f, 0xbe, 0x5a, 0xaf, 0x4b, + 0x7a, 0x9e, 0x18, 0xfc, 0xcd, 0x29, 0x3a, 0xde, 0xef, 0x0b, + 0x8d, 0x69, 0x58, 0xbc, 0x49, 0xad, 0x9c, 0x78, 0xfe, 0x1a, + 0x2b, 0xcf, 0x0d, 0xe9, 0xd8, 0x3c, 0xba, 0x5e, 0x6f, 0x8b, + 0x7e, 0x9a, 0xab, 0x4f, 0xc9, 0x2d, 0x1c, 0xf8, 0xeb, 0x0f, + 0x3e, 0xda, 0x5c, 0xb8, 0x89, 0x6d, 0x98, 0x7c, 0x4d, 0xa9, + 0x2f, 0xcb, 0xfa, 0x1e, 0x00, 0xe5, 0xd7, 0x32, 0xb3, 0x56, + 0x64, 0x81, 0x7b, 0x9e, 0xac, 0x49, 0xc8, 0x2d, 0x1f, 0xfa, + 0xf6, 0x13, 0x21, 0xc4, 0x45, 0xa0, 0x92, 0x77, 0x8d, 0x68, + 0x5a, 0xbf, 0x3e, 0xdb, 0xe9, 0x0c, 0xf1, 0x14, 0x26, 0xc3, + 0x42, 0xa7, 0x95, 0x70, 0x8a, 0x6f, 0x5d, 0xb8, 0x39, 0xdc, + 0xee, 0x0b, 0x07, 0xe2, 0xd0, 0x35, 0xb4, 0x51, 0x63, 0x86, + 0x7c, 0x99, 0xab, 0x4e, 0xcf, 0x2a, 0x18, 0xfd, 0xff, 0x1a, + 0x28, 0xcd, 0x4c, 0xa9, 0x9b, 0x7e, 0x84, 0x61, 0x53, 0xb6, + 0x37, 0xd2, 0xe0, 0x05, 0x09, 0xec, 0xde, 0x3b, 0xba, 0x5f, + 0x6d, 0x88, 0x72, 0x97, 0xa5, 0x40, 0xc1, 0x24, 0x16, 0xf3, + 0x0e, 0xeb, 0xd9, 0x3c, 0xbd, 0x58, 0x6a, 0x8f, 0x75, 0x90, + 0xa2, 0x47, 0xc6, 0x23, 0x11, 0xf4, 0xf8, 0x1d, 0x2f, 0xca, + 0x4b, 0xae, 0x9c, 0x79, 0x83, 0x66, 0x54, 0xb1, 0x30, 0xd5, + 0xe7, 0x02, 0xe3, 0x06, 0x34, 0xd1, 0x50, 0xb5, 0x87, 0x62, + 0x98, 0x7d, 0x4f, 0xaa, 0x2b, 0xce, 0xfc, 0x19, 0x15, 0xf0, + 0xc2, 0x27, 0xa6, 0x43, 0x71, 0x94, 0x6e, 0x8b, 0xb9, 0x5c, + 0xdd, 0x38, 0x0a, 0xef, 0x12, 0xf7, 0xc5, 0x20, 0xa1, 0x44, + 0x76, 0x93, 0x69, 0x8c, 0xbe, 0x5b, 0xda, 0x3f, 0x0d, 0xe8, + 0xe4, 0x01, 0x33, 0xd6, 0x57, 0xb2, 0x80, 0x65, 0x9f, 0x7a, + 0x48, 0xad, 0x2c, 0xc9, 0xfb, 0x1e, 0x1c, 0xf9, 0xcb, 0x2e, + 0xaf, 0x4a, 0x78, 0x9d, 0x67, 0x82, 0xb0, 0x55, 0xd4, 0x31, + 0x03, 0xe6, 0xea, 0x0f, 0x3d, 0xd8, 0x59, 0xbc, 0x8e, 0x6b, + 0x91, 0x74, 0x46, 0xa3, 0x22, 0xc7, 0xf5, 0x10, 0xed, 0x08, + 0x3a, 0xdf, 0x5e, 0xbb, 0x89, 0x6c, 0x96, 0x73, 0x41, 0xa4, + 0x25, 0xc0, 0xf2, 0x17, 0x1b, 0xfe, 0xcc, 0x29, 0xa8, 0x4d, + 0x7f, 0x9a, 0x60, 0x85, 0xb7, 0x52, 0xd3, 0x36, 0x04, 0xe1, + 0x00, 0xe6, 0xd1, 0x37, 0xbf, 0x59, 0x6e, 0x88, 0x63, 0x85, + 0xb2, 0x54, 0xdc, 0x3a, 0x0d, 0xeb, 0xc6, 0x20, 0x17, 0xf1, + 0x79, 0x9f, 0xa8, 0x4e, 0xa5, 0x43, 0x74, 0x92, 0x1a, 0xfc, + 0xcb, 0x2d, 0x91, 0x77, 0x40, 0xa6, 0x2e, 0xc8, 0xff, 0x19, + 0xf2, 0x14, 0x23, 0xc5, 0x4d, 0xab, 0x9c, 0x7a, 0x57, 0xb1, + 0x86, 0x60, 0xe8, 0x0e, 0x39, 0xdf, 0x34, 0xd2, 0xe5, 0x03, + 0x8b, 0x6d, 0x5a, 0xbc, 0x3f, 0xd9, 0xee, 0x08, 0x80, 0x66, + 0x51, 0xb7, 0x5c, 0xba, 0x8d, 0x6b, 0xe3, 0x05, 0x32, 0xd4, + 0xf9, 0x1f, 0x28, 0xce, 0x46, 0xa0, 0x97, 0x71, 0x9a, 0x7c, + 0x4b, 0xad, 0x25, 0xc3, 0xf4, 0x12, 0xae, 0x48, 0x7f, 0x99, + 0x11, 0xf7, 0xc0, 0x26, 0xcd, 0x2b, 0x1c, 0xfa, 0x72, 0x94, + 0xa3, 0x45, 0x68, 0x8e, 0xb9, 0x5f, 0xd7, 0x31, 0x06, 0xe0, + 0x0b, 0xed, 0xda, 0x3c, 0xb4, 0x52, 0x65, 0x83, 0x7e, 0x98, + 0xaf, 0x49, 0xc1, 0x27, 0x10, 0xf6, 0x1d, 0xfb, 0xcc, 0x2a, + 0xa2, 0x44, 0x73, 0x95, 0xb8, 0x5e, 0x69, 0x8f, 0x07, 0xe1, + 0xd6, 0x30, 0xdb, 0x3d, 0x0a, 0xec, 0x64, 0x82, 0xb5, 0x53, + 0xef, 0x09, 0x3e, 0xd8, 0x50, 0xb6, 0x81, 0x67, 0x8c, 0x6a, + 0x5d, 0xbb, 0x33, 0xd5, 0xe2, 0x04, 0x29, 0xcf, 0xf8, 0x1e, + 0x96, 0x70, 0x47, 0xa1, 0x4a, 0xac, 0x9b, 0x7d, 0xf5, 0x13, + 0x24, 0xc2, 0x41, 0xa7, 0x90, 0x76, 0xfe, 0x18, 0x2f, 0xc9, + 0x22, 0xc4, 0xf3, 0x15, 0x9d, 0x7b, 0x4c, 0xaa, 0x87, 0x61, + 0x56, 0xb0, 0x38, 0xde, 0xe9, 0x0f, 0xe4, 0x02, 0x35, 0xd3, + 0x5b, 0xbd, 0x8a, 0x6c, 0xd0, 0x36, 0x01, 0xe7, 0x6f, 0x89, + 0xbe, 0x58, 0xb3, 0x55, 0x62, 0x84, 0x0c, 0xea, 0xdd, 0x3b, + 0x16, 0xf0, 0xc7, 0x21, 0xa9, 0x4f, 0x78, 0x9e, 0x75, 0x93, + 0xa4, 0x42, 0xca, 0x2c, 0x1b, 0xfd, 0x00, 0xe7, 0xd3, 0x34, + 0xbb, 0x5c, 0x68, 0x8f, 0x6b, 0x8c, 0xb8, 0x5f, 0xd0, 0x37, + 0x03, 0xe4, 0xd6, 0x31, 0x05, 0xe2, 0x6d, 0x8a, 0xbe, 0x59, + 0xbd, 0x5a, 0x6e, 0x89, 0x06, 0xe1, 0xd5, 0x32, 0xb1, 0x56, + 0x62, 0x85, 0x0a, 0xed, 0xd9, 0x3e, 0xda, 0x3d, 0x09, 0xee, + 0x61, 0x86, 0xb2, 0x55, 0x67, 0x80, 0xb4, 0x53, 0xdc, 0x3b, + 0x0f, 0xe8, 0x0c, 0xeb, 0xdf, 0x38, 0xb7, 0x50, 0x64, 0x83, + 0x7f, 0x98, 0xac, 0x4b, 0xc4, 0x23, 0x17, 0xf0, 0x14, 0xf3, + 0xc7, 0x20, 0xaf, 0x48, 0x7c, 0x9b, 0xa9, 0x4e, 0x7a, 0x9d, + 0x12, 0xf5, 0xc1, 0x26, 0xc2, 0x25, 0x11, 0xf6, 0x79, 0x9e, + 0xaa, 0x4d, 0xce, 0x29, 0x1d, 0xfa, 0x75, 0x92, 0xa6, 0x41, + 0xa5, 0x42, 0x76, 0x91, 0x1e, 0xf9, 0xcd, 0x2a, 0x18, 0xff, + 0xcb, 0x2c, 0xa3, 0x44, 0x70, 0x97, 0x73, 0x94, 0xa0, 0x47, + 0xc8, 0x2f, 0x1b, 0xfc, 0xfe, 0x19, 0x2d, 0xca, 0x45, 0xa2, + 0x96, 0x71, 0x95, 0x72, 0x46, 0xa1, 0x2e, 0xc9, 0xfd, 0x1a, + 0x28, 0xcf, 0xfb, 0x1c, 0x93, 0x74, 0x40, 0xa7, 0x43, 0xa4, + 0x90, 0x77, 0xf8, 0x1f, 0x2b, 0xcc, 0x4f, 0xa8, 0x9c, 0x7b, + 0xf4, 0x13, 0x27, 0xc0, 0x24, 0xc3, 0xf7, 0x10, 0x9f, 0x78, + 0x4c, 0xab, 0x99, 0x7e, 0x4a, 0xad, 0x22, 0xc5, 0xf1, 0x16, + 0xf2, 0x15, 0x21, 0xc6, 0x49, 0xae, 0x9a, 0x7d, 0x81, 0x66, + 0x52, 0xb5, 0x3a, 0xdd, 0xe9, 0x0e, 0xea, 0x0d, 0x39, 0xde, + 0x51, 0xb6, 0x82, 0x65, 0x57, 0xb0, 0x84, 0x63, 0xec, 0x0b, + 0x3f, 0xd8, 0x3c, 0xdb, 0xef, 0x08, 0x87, 0x60, 0x54, 0xb3, + 0x30, 0xd7, 0xe3, 0x04, 0x8b, 0x6c, 0x58, 0xbf, 0x5b, 0xbc, + 0x88, 0x6f, 0xe0, 0x07, 0x33, 0xd4, 0xe6, 0x01, 0x35, 0xd2, + 0x5d, 0xba, 0x8e, 0x69, 0x8d, 0x6a, 0x5e, 0xb9, 0x36, 0xd1, + 0xe5, 0x02, 0x00, 0xe8, 0xcd, 0x25, 0x87, 0x6f, 0x4a, 0xa2, + 0x13, 0xfb, 0xde, 0x36, 0x94, 0x7c, 0x59, 0xb1, 0x26, 0xce, + 0xeb, 0x03, 0xa1, 0x49, 0x6c, 0x84, 0x35, 0xdd, 0xf8, 0x10, + 0xb2, 0x5a, 0x7f, 0x97, 0x4c, 0xa4, 0x81, 0x69, 0xcb, 0x23, + 0x06, 0xee, 0x5f, 0xb7, 0x92, 0x7a, 0xd8, 0x30, 0x15, 0xfd, + 0x6a, 0x82, 0xa7, 0x4f, 0xed, 0x05, 0x20, 0xc8, 0x79, 0x91, + 0xb4, 0x5c, 0xfe, 0x16, 0x33, 0xdb, 0x98, 0x70, 0x55, 0xbd, + 0x1f, 0xf7, 0xd2, 0x3a, 0x8b, 0x63, 0x46, 0xae, 0x0c, 0xe4, + 0xc1, 0x29, 0xbe, 0x56, 0x73, 0x9b, 0x39, 0xd1, 0xf4, 0x1c, + 0xad, 0x45, 0x60, 0x88, 0x2a, 0xc2, 0xe7, 0x0f, 0xd4, 0x3c, + 0x19, 0xf1, 0x53, 0xbb, 0x9e, 0x76, 0xc7, 0x2f, 0x0a, 0xe2, + 0x40, 0xa8, 0x8d, 0x65, 0xf2, 0x1a, 0x3f, 0xd7, 0x75, 0x9d, + 0xb8, 0x50, 0xe1, 0x09, 0x2c, 0xc4, 0x66, 0x8e, 0xab, 0x43, + 0x2d, 0xc5, 0xe0, 0x08, 0xaa, 0x42, 0x67, 0x8f, 0x3e, 0xd6, + 0xf3, 0x1b, 0xb9, 0x51, 0x74, 0x9c, 0x0b, 0xe3, 0xc6, 0x2e, + 0x8c, 0x64, 0x41, 0xa9, 0x18, 0xf0, 0xd5, 0x3d, 0x9f, 0x77, + 0x52, 0xba, 0x61, 0x89, 0xac, 0x44, 0xe6, 0x0e, 0x2b, 0xc3, + 0x72, 0x9a, 0xbf, 0x57, 0xf5, 0x1d, 0x38, 0xd0, 0x47, 0xaf, + 0x8a, 0x62, 0xc0, 0x28, 0x0d, 0xe5, 0x54, 0xbc, 0x99, 0x71, + 0xd3, 0x3b, 0x1e, 0xf6, 0xb5, 0x5d, 0x78, 0x90, 0x32, 0xda, + 0xff, 0x17, 0xa6, 0x4e, 0x6b, 0x83, 0x21, 0xc9, 0xec, 0x04, + 0x93, 0x7b, 0x5e, 0xb6, 0x14, 0xfc, 0xd9, 0x31, 0x80, 0x68, + 0x4d, 0xa5, 0x07, 0xef, 0xca, 0x22, 0xf9, 0x11, 0x34, 0xdc, + 0x7e, 0x96, 0xb3, 0x5b, 0xea, 0x02, 0x27, 0xcf, 0x6d, 0x85, + 0xa0, 0x48, 0xdf, 0x37, 0x12, 0xfa, 0x58, 0xb0, 0x95, 0x7d, + 0xcc, 0x24, 0x01, 0xe9, 0x4b, 0xa3, 0x86, 0x6e, 0x00, 0xe9, + 0xcf, 0x26, 0x83, 0x6a, 0x4c, 0xa5, 0x1b, 0xf2, 0xd4, 0x3d, + 0x98, 0x71, 0x57, 0xbe, 0x36, 0xdf, 0xf9, 0x10, 0xb5, 0x5c, + 0x7a, 0x93, 0x2d, 0xc4, 0xe2, 0x0b, 0xae, 0x47, 0x61, 0x88, + 0x6c, 0x85, 0xa3, 0x4a, 0xef, 0x06, 0x20, 0xc9, 0x77, 0x9e, + 0xb8, 0x51, 0xf4, 0x1d, 0x3b, 0xd2, 0x5a, 0xb3, 0x95, 0x7c, + 0xd9, 0x30, 0x16, 0xff, 0x41, 0xa8, 0x8e, 0x67, 0xc2, 0x2b, + 0x0d, 0xe4, 0xd8, 0x31, 0x17, 0xfe, 0x5b, 0xb2, 0x94, 0x7d, + 0xc3, 0x2a, 0x0c, 0xe5, 0x40, 0xa9, 0x8f, 0x66, 0xee, 0x07, + 0x21, 0xc8, 0x6d, 0x84, 0xa2, 0x4b, 0xf5, 0x1c, 0x3a, 0xd3, + 0x76, 0x9f, 0xb9, 0x50, 0xb4, 0x5d, 0x7b, 0x92, 0x37, 0xde, + 0xf8, 0x11, 0xaf, 0x46, 0x60, 0x89, 0x2c, 0xc5, 0xe3, 0x0a, + 0x82, 0x6b, 0x4d, 0xa4, 0x01, 0xe8, 0xce, 0x27, 0x99, 0x70, + 0x56, 0xbf, 0x1a, 0xf3, 0xd5, 0x3c, 0xad, 0x44, 0x62, 0x8b, + 0x2e, 0xc7, 0xe1, 0x08, 0xb6, 0x5f, 0x79, 0x90, 0x35, 0xdc, + 0xfa, 0x13, 0x9b, 0x72, 0x54, 0xbd, 0x18, 0xf1, 0xd7, 0x3e, + 0x80, 0x69, 0x4f, 0xa6, 0x03, 0xea, 0xcc, 0x25, 0xc1, 0x28, + 0x0e, 0xe7, 0x42, 0xab, 0x8d, 0x64, 0xda, 0x33, 0x15, 0xfc, + 0x59, 0xb0, 0x96, 0x7f, 0xf7, 0x1e, 0x38, 0xd1, 0x74, 0x9d, + 0xbb, 0x52, 0xec, 0x05, 0x23, 0xca, 0x6f, 0x86, 0xa0, 0x49, + 0x75, 0x9c, 0xba, 0x53, 0xf6, 0x1f, 0x39, 0xd0, 0x6e, 0x87, + 0xa1, 0x48, 0xed, 0x04, 0x22, 0xcb, 0x43, 0xaa, 0x8c, 0x65, + 0xc0, 0x29, 0x0f, 0xe6, 0x58, 0xb1, 0x97, 0x7e, 0xdb, 0x32, + 0x14, 0xfd, 0x19, 0xf0, 0xd6, 0x3f, 0x9a, 0x73, 0x55, 0xbc, + 0x02, 0xeb, 0xcd, 0x24, 0x81, 0x68, 0x4e, 0xa7, 0x2f, 0xc6, + 0xe0, 0x09, 0xac, 0x45, 0x63, 0x8a, 0x34, 0xdd, 0xfb, 0x12, + 0xb7, 0x5e, 0x78, 0x91, 0x00, 0xea, 0xc9, 0x23, 0x8f, 0x65, + 0x46, 0xac, 0x03, 0xe9, 0xca, 0x20, 0x8c, 0x66, 0x45, 0xaf, + 0x06, 0xec, 0xcf, 0x25, 0x89, 0x63, 0x40, 0xaa, 0x05, 0xef, + 0xcc, 0x26, 0x8a, 0x60, 0x43, 0xa9, 0x0c, 0xe6, 0xc5, 0x2f, + 0x83, 0x69, 0x4a, 0xa0, 0x0f, 0xe5, 0xc6, 0x2c, 0x80, 0x6a, + 0x49, 0xa3, 0x0a, 0xe0, 0xc3, 0x29, 0x85, 0x6f, 0x4c, 0xa6, + 0x09, 0xe3, 0xc0, 0x2a, 0x86, 0x6c, 0x4f, 0xa5, 0x18, 0xf2, + 0xd1, 0x3b, 0x97, 0x7d, 0x5e, 0xb4, 0x1b, 0xf1, 0xd2, 0x38, + 0x94, 0x7e, 0x5d, 0xb7, 0x1e, 0xf4, 0xd7, 0x3d, 0x91, 0x7b, + 0x58, 0xb2, 0x1d, 0xf7, 0xd4, 0x3e, 0x92, 0x78, 0x5b, 0xb1, + 0x14, 0xfe, 0xdd, 0x37, 0x9b, 0x71, 0x52, 0xb8, 0x17, 0xfd, + 0xde, 0x34, 0x98, 0x72, 0x51, 0xbb, 0x12, 0xf8, 0xdb, 0x31, + 0x9d, 0x77, 0x54, 0xbe, 0x11, 0xfb, 0xd8, 0x32, 0x9e, 0x74, + 0x57, 0xbd, 0x30, 0xda, 0xf9, 0x13, 0xbf, 0x55, 0x76, 0x9c, + 0x33, 0xd9, 0xfa, 0x10, 0xbc, 0x56, 0x75, 0x9f, 0x36, 0xdc, + 0xff, 0x15, 0xb9, 0x53, 0x70, 0x9a, 0x35, 0xdf, 0xfc, 0x16, + 0xba, 0x50, 0x73, 0x99, 0x3c, 0xd6, 0xf5, 0x1f, 0xb3, 0x59, + 0x7a, 0x90, 0x3f, 0xd5, 0xf6, 0x1c, 0xb0, 0x5a, 0x79, 0x93, + 0x3a, 0xd0, 0xf3, 0x19, 0xb5, 0x5f, 0x7c, 0x96, 0x39, 0xd3, + 0xf0, 0x1a, 0xb6, 0x5c, 0x7f, 0x95, 0x28, 0xc2, 0xe1, 0x0b, + 0xa7, 0x4d, 0x6e, 0x84, 0x2b, 0xc1, 0xe2, 0x08, 0xa4, 0x4e, + 0x6d, 0x87, 0x2e, 0xc4, 0xe7, 0x0d, 0xa1, 0x4b, 0x68, 0x82, + 0x2d, 0xc7, 0xe4, 0x0e, 0xa2, 0x48, 0x6b, 0x81, 0x24, 0xce, + 0xed, 0x07, 0xab, 0x41, 0x62, 0x88, 0x27, 0xcd, 0xee, 0x04, + 0xa8, 0x42, 0x61, 0x8b, 0x22, 0xc8, 0xeb, 0x01, 0xad, 0x47, + 0x64, 0x8e, 0x21, 0xcb, 0xe8, 0x02, 0xae, 0x44, 0x67, 0x8d, + 0x00, 0xeb, 0xcb, 0x20, 0x8b, 0x60, 0x40, 0xab, 0x0b, 0xe0, + 0xc0, 0x2b, 0x80, 0x6b, 0x4b, 0xa0, 0x16, 0xfd, 0xdd, 0x36, + 0x9d, 0x76, 0x56, 0xbd, 0x1d, 0xf6, 0xd6, 0x3d, 0x96, 0x7d, + 0x5d, 0xb6, 0x2c, 0xc7, 0xe7, 0x0c, 0xa7, 0x4c, 0x6c, 0x87, + 0x27, 0xcc, 0xec, 0x07, 0xac, 0x47, 0x67, 0x8c, 0x3a, 0xd1, + 0xf1, 0x1a, 0xb1, 0x5a, 0x7a, 0x91, 0x31, 0xda, 0xfa, 0x11, + 0xba, 0x51, 0x71, 0x9a, 0x58, 0xb3, 0x93, 0x78, 0xd3, 0x38, + 0x18, 0xf3, 0x53, 0xb8, 0x98, 0x73, 0xd8, 0x33, 0x13, 0xf8, + 0x4e, 0xa5, 0x85, 0x6e, 0xc5, 0x2e, 0x0e, 0xe5, 0x45, 0xae, + 0x8e, 0x65, 0xce, 0x25, 0x05, 0xee, 0x74, 0x9f, 0xbf, 0x54, + 0xff, 0x14, 0x34, 0xdf, 0x7f, 0x94, 0xb4, 0x5f, 0xf4, 0x1f, + 0x3f, 0xd4, 0x62, 0x89, 0xa9, 0x42, 0xe9, 0x02, 0x22, 0xc9, + 0x69, 0x82, 0xa2, 0x49, 0xe2, 0x09, 0x29, 0xc2, 0xb0, 0x5b, + 0x7b, 0x90, 0x3b, 0xd0, 0xf0, 0x1b, 0xbb, 0x50, 0x70, 0x9b, + 0x30, 0xdb, 0xfb, 0x10, 0xa6, 0x4d, 0x6d, 0x86, 0x2d, 0xc6, + 0xe6, 0x0d, 0xad, 0x46, 0x66, 0x8d, 0x26, 0xcd, 0xed, 0x06, + 0x9c, 0x77, 0x57, 0xbc, 0x17, 0xfc, 0xdc, 0x37, 0x97, 0x7c, + 0x5c, 0xb7, 0x1c, 0xf7, 0xd7, 0x3c, 0x8a, 0x61, 0x41, 0xaa, + 0x01, 0xea, 0xca, 0x21, 0x81, 0x6a, 0x4a, 0xa1, 0x0a, 0xe1, + 0xc1, 0x2a, 0xe8, 0x03, 0x23, 0xc8, 0x63, 0x88, 0xa8, 0x43, + 0xe3, 0x08, 0x28, 0xc3, 0x68, 0x83, 0xa3, 0x48, 0xfe, 0x15, + 0x35, 0xde, 0x75, 0x9e, 0xbe, 0x55, 0xf5, 0x1e, 0x3e, 0xd5, + 0x7e, 0x95, 0xb5, 0x5e, 0xc4, 0x2f, 0x0f, 0xe4, 0x4f, 0xa4, + 0x84, 0x6f, 0xcf, 0x24, 0x04, 0xef, 0x44, 0xaf, 0x8f, 0x64, + 0xd2, 0x39, 0x19, 0xf2, 0x59, 0xb2, 0x92, 0x79, 0xd9, 0x32, + 0x12, 0xf9, 0x52, 0xb9, 0x99, 0x72, 0x00, 0xec, 0xc5, 0x29, + 0x97, 0x7b, 0x52, 0xbe, 0x33, 0xdf, 0xf6, 0x1a, 0xa4, 0x48, + 0x61, 0x8d, 0x66, 0x8a, 0xa3, 0x4f, 0xf1, 0x1d, 0x34, 0xd8, + 0x55, 0xb9, 0x90, 0x7c, 0xc2, 0x2e, 0x07, 0xeb, 0xcc, 0x20, + 0x09, 0xe5, 0x5b, 0xb7, 0x9e, 0x72, 0xff, 0x13, 0x3a, 0xd6, + 0x68, 0x84, 0xad, 0x41, 0xaa, 0x46, 0x6f, 0x83, 0x3d, 0xd1, + 0xf8, 0x14, 0x99, 0x75, 0x5c, 0xb0, 0x0e, 0xe2, 0xcb, 0x27, + 0x85, 0x69, 0x40, 0xac, 0x12, 0xfe, 0xd7, 0x3b, 0xb6, 0x5a, + 0x73, 0x9f, 0x21, 0xcd, 0xe4, 0x08, 0xe3, 0x0f, 0x26, 0xca, + 0x74, 0x98, 0xb1, 0x5d, 0xd0, 0x3c, 0x15, 0xf9, 0x47, 0xab, + 0x82, 0x6e, 0x49, 0xa5, 0x8c, 0x60, 0xde, 0x32, 0x1b, 0xf7, + 0x7a, 0x96, 0xbf, 0x53, 0xed, 0x01, 0x28, 0xc4, 0x2f, 0xc3, + 0xea, 0x06, 0xb8, 0x54, 0x7d, 0x91, 0x1c, 0xf0, 0xd9, 0x35, + 0x8b, 0x67, 0x4e, 0xa2, 0x17, 0xfb, 0xd2, 0x3e, 0x80, 0x6c, + 0x45, 0xa9, 0x24, 0xc8, 0xe1, 0x0d, 0xb3, 0x5f, 0x76, 0x9a, + 0x71, 0x9d, 0xb4, 0x58, 0xe6, 0x0a, 0x23, 0xcf, 0x42, 0xae, + 0x87, 0x6b, 0xd5, 0x39, 0x10, 0xfc, 0xdb, 0x37, 0x1e, 0xf2, + 0x4c, 0xa0, 0x89, 0x65, 0xe8, 0x04, 0x2d, 0xc1, 0x7f, 0x93, + 0xba, 0x56, 0xbd, 0x51, 0x78, 0x94, 0x2a, 0xc6, 0xef, 0x03, + 0x8e, 0x62, 0x4b, 0xa7, 0x19, 0xf5, 0xdc, 0x30, 0x92, 0x7e, + 0x57, 0xbb, 0x05, 0xe9, 0xc0, 0x2c, 0xa1, 0x4d, 0x64, 0x88, + 0x36, 0xda, 0xf3, 0x1f, 0xf4, 0x18, 0x31, 0xdd, 0x63, 0x8f, + 0xa6, 0x4a, 0xc7, 0x2b, 0x02, 0xee, 0x50, 0xbc, 0x95, 0x79, + 0x5e, 0xb2, 0x9b, 0x77, 0xc9, 0x25, 0x0c, 0xe0, 0x6d, 0x81, + 0xa8, 0x44, 0xfa, 0x16, 0x3f, 0xd3, 0x38, 0xd4, 0xfd, 0x11, + 0xaf, 0x43, 0x6a, 0x86, 0x0b, 0xe7, 0xce, 0x22, 0x9c, 0x70, + 0x59, 0xb5, 0x00, 0xed, 0xc7, 0x2a, 0x93, 0x7e, 0x54, 0xb9, + 0x3b, 0xd6, 0xfc, 0x11, 0xa8, 0x45, 0x6f, 0x82, 0x76, 0x9b, + 0xb1, 0x5c, 0xe5, 0x08, 0x22, 0xcf, 0x4d, 0xa0, 0x8a, 0x67, + 0xde, 0x33, 0x19, 0xf4, 0xec, 0x01, 0x2b, 0xc6, 0x7f, 0x92, + 0xb8, 0x55, 0xd7, 0x3a, 0x10, 0xfd, 0x44, 0xa9, 0x83, 0x6e, + 0x9a, 0x77, 0x5d, 0xb0, 0x09, 0xe4, 0xce, 0x23, 0xa1, 0x4c, + 0x66, 0x8b, 0x32, 0xdf, 0xf5, 0x18, 0xc5, 0x28, 0x02, 0xef, + 0x56, 0xbb, 0x91, 0x7c, 0xfe, 0x13, 0x39, 0xd4, 0x6d, 0x80, + 0xaa, 0x47, 0xb3, 0x5e, 0x74, 0x99, 0x20, 0xcd, 0xe7, 0x0a, + 0x88, 0x65, 0x4f, 0xa2, 0x1b, 0xf6, 0xdc, 0x31, 0x29, 0xc4, + 0xee, 0x03, 0xba, 0x57, 0x7d, 0x90, 0x12, 0xff, 0xd5, 0x38, + 0x81, 0x6c, 0x46, 0xab, 0x5f, 0xb2, 0x98, 0x75, 0xcc, 0x21, + 0x0b, 0xe6, 0x64, 0x89, 0xa3, 0x4e, 0xf7, 0x1a, 0x30, 0xdd, + 0x97, 0x7a, 0x50, 0xbd, 0x04, 0xe9, 0xc3, 0x2e, 0xac, 0x41, + 0x6b, 0x86, 0x3f, 0xd2, 0xf8, 0x15, 0xe1, 0x0c, 0x26, 0xcb, + 0x72, 0x9f, 0xb5, 0x58, 0xda, 0x37, 0x1d, 0xf0, 0x49, 0xa4, + 0x8e, 0x63, 0x7b, 0x96, 0xbc, 0x51, 0xe8, 0x05, 0x2f, 0xc2, + 0x40, 0xad, 0x87, 0x6a, 0xd3, 0x3e, 0x14, 0xf9, 0x0d, 0xe0, + 0xca, 0x27, 0x9e, 0x73, 0x59, 0xb4, 0x36, 0xdb, 0xf1, 0x1c, + 0xa5, 0x48, 0x62, 0x8f, 0x52, 0xbf, 0x95, 0x78, 0xc1, 0x2c, + 0x06, 0xeb, 0x69, 0x84, 0xae, 0x43, 0xfa, 0x17, 0x3d, 0xd0, + 0x24, 0xc9, 0xe3, 0x0e, 0xb7, 0x5a, 0x70, 0x9d, 0x1f, 0xf2, + 0xd8, 0x35, 0x8c, 0x61, 0x4b, 0xa6, 0xbe, 0x53, 0x79, 0x94, + 0x2d, 0xc0, 0xea, 0x07, 0x85, 0x68, 0x42, 0xaf, 0x16, 0xfb, + 0xd1, 0x3c, 0xc8, 0x25, 0x0f, 0xe2, 0x5b, 0xb6, 0x9c, 0x71, + 0xf3, 0x1e, 0x34, 0xd9, 0x60, 0x8d, 0xa7, 0x4a, 0x00, 0xee, + 0xc1, 0x2f, 0x9f, 0x71, 0x5e, 0xb0, 0x23, 0xcd, 0xe2, 0x0c, + 0xbc, 0x52, 0x7d, 0x93, 0x46, 0xa8, 0x87, 0x69, 0xd9, 0x37, + 0x18, 0xf6, 0x65, 0x8b, 0xa4, 0x4a, 0xfa, 0x14, 0x3b, 0xd5, + 0x8c, 0x62, 0x4d, 0xa3, 0x13, 0xfd, 0xd2, 0x3c, 0xaf, 0x41, + 0x6e, 0x80, 0x30, 0xde, 0xf1, 0x1f, 0xca, 0x24, 0x0b, 0xe5, + 0x55, 0xbb, 0x94, 0x7a, 0xe9, 0x07, 0x28, 0xc6, 0x76, 0x98, + 0xb7, 0x59, 0x05, 0xeb, 0xc4, 0x2a, 0x9a, 0x74, 0x5b, 0xb5, + 0x26, 0xc8, 0xe7, 0x09, 0xb9, 0x57, 0x78, 0x96, 0x43, 0xad, + 0x82, 0x6c, 0xdc, 0x32, 0x1d, 0xf3, 0x60, 0x8e, 0xa1, 0x4f, + 0xff, 0x11, 0x3e, 0xd0, 0x89, 0x67, 0x48, 0xa6, 0x16, 0xf8, + 0xd7, 0x39, 0xaa, 0x44, 0x6b, 0x85, 0x35, 0xdb, 0xf4, 0x1a, + 0xcf, 0x21, 0x0e, 0xe0, 0x50, 0xbe, 0x91, 0x7f, 0xec, 0x02, + 0x2d, 0xc3, 0x73, 0x9d, 0xb2, 0x5c, 0x0a, 0xe4, 0xcb, 0x25, + 0x95, 0x7b, 0x54, 0xba, 0x29, 0xc7, 0xe8, 0x06, 0xb6, 0x58, + 0x77, 0x99, 0x4c, 0xa2, 0x8d, 0x63, 0xd3, 0x3d, 0x12, 0xfc, + 0x6f, 0x81, 0xae, 0x40, 0xf0, 0x1e, 0x31, 0xdf, 0x86, 0x68, + 0x47, 0xa9, 0x19, 0xf7, 0xd8, 0x36, 0xa5, 0x4b, 0x64, 0x8a, + 0x3a, 0xd4, 0xfb, 0x15, 0xc0, 0x2e, 0x01, 0xef, 0x5f, 0xb1, + 0x9e, 0x70, 0xe3, 0x0d, 0x22, 0xcc, 0x7c, 0x92, 0xbd, 0x53, + 0x0f, 0xe1, 0xce, 0x20, 0x90, 0x7e, 0x51, 0xbf, 0x2c, 0xc2, + 0xed, 0x03, 0xb3, 0x5d, 0x72, 0x9c, 0x49, 0xa7, 0x88, 0x66, + 0xd6, 0x38, 0x17, 0xf9, 0x6a, 0x84, 0xab, 0x45, 0xf5, 0x1b, + 0x34, 0xda, 0x83, 0x6d, 0x42, 0xac, 0x1c, 0xf2, 0xdd, 0x33, + 0xa0, 0x4e, 0x61, 0x8f, 0x3f, 0xd1, 0xfe, 0x10, 0xc5, 0x2b, + 0x04, 0xea, 0x5a, 0xb4, 0x9b, 0x75, 0xe6, 0x08, 0x27, 0xc9, + 0x79, 0x97, 0xb8, 0x56, 0x00, 0xef, 0xc3, 0x2c, 0x9b, 0x74, + 0x58, 0xb7, 0x2b, 0xc4, 0xe8, 0x07, 0xb0, 0x5f, 0x73, 0x9c, + 0x56, 0xb9, 0x95, 0x7a, 0xcd, 0x22, 0x0e, 0xe1, 0x7d, 0x92, + 0xbe, 0x51, 0xe6, 0x09, 0x25, 0xca, 0xac, 0x43, 0x6f, 0x80, + 0x37, 0xd8, 0xf4, 0x1b, 0x87, 0x68, 0x44, 0xab, 0x1c, 0xf3, + 0xdf, 0x30, 0xfa, 0x15, 0x39, 0xd6, 0x61, 0x8e, 0xa2, 0x4d, + 0xd1, 0x3e, 0x12, 0xfd, 0x4a, 0xa5, 0x89, 0x66, 0x45, 0xaa, + 0x86, 0x69, 0xde, 0x31, 0x1d, 0xf2, 0x6e, 0x81, 0xad, 0x42, + 0xf5, 0x1a, 0x36, 0xd9, 0x13, 0xfc, 0xd0, 0x3f, 0x88, 0x67, + 0x4b, 0xa4, 0x38, 0xd7, 0xfb, 0x14, 0xa3, 0x4c, 0x60, 0x8f, + 0xe9, 0x06, 0x2a, 0xc5, 0x72, 0x9d, 0xb1, 0x5e, 0xc2, 0x2d, + 0x01, 0xee, 0x59, 0xb6, 0x9a, 0x75, 0xbf, 0x50, 0x7c, 0x93, + 0x24, 0xcb, 0xe7, 0x08, 0x94, 0x7b, 0x57, 0xb8, 0x0f, 0xe0, + 0xcc, 0x23, 0x8a, 0x65, 0x49, 0xa6, 0x11, 0xfe, 0xd2, 0x3d, + 0xa1, 0x4e, 0x62, 0x8d, 0x3a, 0xd5, 0xf9, 0x16, 0xdc, 0x33, + 0x1f, 0xf0, 0x47, 0xa8, 0x84, 0x6b, 0xf7, 0x18, 0x34, 0xdb, + 0x6c, 0x83, 0xaf, 0x40, 0x26, 0xc9, 0xe5, 0x0a, 0xbd, 0x52, + 0x7e, 0x91, 0x0d, 0xe2, 0xce, 0x21, 0x96, 0x79, 0x55, 0xba, + 0x70, 0x9f, 0xb3, 0x5c, 0xeb, 0x04, 0x28, 0xc7, 0x5b, 0xb4, + 0x98, 0x77, 0xc0, 0x2f, 0x03, 0xec, 0xcf, 0x20, 0x0c, 0xe3, + 0x54, 0xbb, 0x97, 0x78, 0xe4, 0x0b, 0x27, 0xc8, 0x7f, 0x90, + 0xbc, 0x53, 0x99, 0x76, 0x5a, 0xb5, 0x02, 0xed, 0xc1, 0x2e, + 0xb2, 0x5d, 0x71, 0x9e, 0x29, 0xc6, 0xea, 0x05, 0x63, 0x8c, + 0xa0, 0x4f, 0xf8, 0x17, 0x3b, 0xd4, 0x48, 0xa7, 0x8b, 0x64, + 0xd3, 0x3c, 0x10, 0xff, 0x35, 0xda, 0xf6, 0x19, 0xae, 0x41, + 0x6d, 0x82, 0x1e, 0xf1, 0xdd, 0x32, 0x85, 0x6a, 0x46, 0xa9, + 0x00, 0xf0, 0xfd, 0x0d, 0xe7, 0x17, 0x1a, 0xea, 0xd3, 0x23, + 0x2e, 0xde, 0x34, 0xc4, 0xc9, 0x39, 0xbb, 0x4b, 0x46, 0xb6, + 0x5c, 0xac, 0xa1, 0x51, 0x68, 0x98, 0x95, 0x65, 0x8f, 0x7f, + 0x72, 0x82, 0x6b, 0x9b, 0x96, 0x66, 0x8c, 0x7c, 0x71, 0x81, + 0xb8, 0x48, 0x45, 0xb5, 0x5f, 0xaf, 0xa2, 0x52, 0xd0, 0x20, + 0x2d, 0xdd, 0x37, 0xc7, 0xca, 0x3a, 0x03, 0xf3, 0xfe, 0x0e, + 0xe4, 0x14, 0x19, 0xe9, 0xd6, 0x26, 0x2b, 0xdb, 0x31, 0xc1, + 0xcc, 0x3c, 0x05, 0xf5, 0xf8, 0x08, 0xe2, 0x12, 0x1f, 0xef, + 0x6d, 0x9d, 0x90, 0x60, 0x8a, 0x7a, 0x77, 0x87, 0xbe, 0x4e, + 0x43, 0xb3, 0x59, 0xa9, 0xa4, 0x54, 0xbd, 0x4d, 0x40, 0xb0, + 0x5a, 0xaa, 0xa7, 0x57, 0x6e, 0x9e, 0x93, 0x63, 0x89, 0x79, + 0x74, 0x84, 0x06, 0xf6, 0xfb, 0x0b, 0xe1, 0x11, 0x1c, 0xec, + 0xd5, 0x25, 0x28, 0xd8, 0x32, 0xc2, 0xcf, 0x3f, 0xb1, 0x41, + 0x4c, 0xbc, 0x56, 0xa6, 0xab, 0x5b, 0x62, 0x92, 0x9f, 0x6f, + 0x85, 0x75, 0x78, 0x88, 0x0a, 0xfa, 0xf7, 0x07, 0xed, 0x1d, + 0x10, 0xe0, 0xd9, 0x29, 0x24, 0xd4, 0x3e, 0xce, 0xc3, 0x33, + 0xda, 0x2a, 0x27, 0xd7, 0x3d, 0xcd, 0xc0, 0x30, 0x09, 0xf9, + 0xf4, 0x04, 0xee, 0x1e, 0x13, 0xe3, 0x61, 0x91, 0x9c, 0x6c, + 0x86, 0x76, 0x7b, 0x8b, 0xb2, 0x42, 0x4f, 0xbf, 0x55, 0xa5, + 0xa8, 0x58, 0x67, 0x97, 0x9a, 0x6a, 0x80, 0x70, 0x7d, 0x8d, + 0xb4, 0x44, 0x49, 0xb9, 0x53, 0xa3, 0xae, 0x5e, 0xdc, 0x2c, + 0x21, 0xd1, 0x3b, 0xcb, 0xc6, 0x36, 0x0f, 0xff, 0xf2, 0x02, + 0xe8, 0x18, 0x15, 0xe5, 0x0c, 0xfc, 0xf1, 0x01, 0xeb, 0x1b, + 0x16, 0xe6, 0xdf, 0x2f, 0x22, 0xd2, 0x38, 0xc8, 0xc5, 0x35, + 0xb7, 0x47, 0x4a, 0xba, 0x50, 0xa0, 0xad, 0x5d, 0x64, 0x94, + 0x99, 0x69, 0x83, 0x73, 0x7e, 0x8e, 0x00, 0xf1, 0xff, 0x0e, + 0xe3, 0x12, 0x1c, 0xed, 0xdb, 0x2a, 0x24, 0xd5, 0x38, 0xc9, + 0xc7, 0x36, 0xab, 0x5a, 0x54, 0xa5, 0x48, 0xb9, 0xb7, 0x46, + 0x70, 0x81, 0x8f, 0x7e, 0x93, 0x62, 0x6c, 0x9d, 0x4b, 0xba, + 0xb4, 0x45, 0xa8, 0x59, 0x57, 0xa6, 0x90, 0x61, 0x6f, 0x9e, + 0x73, 0x82, 0x8c, 0x7d, 0xe0, 0x11, 0x1f, 0xee, 0x03, 0xf2, + 0xfc, 0x0d, 0x3b, 0xca, 0xc4, 0x35, 0xd8, 0x29, 0x27, 0xd6, + 0x96, 0x67, 0x69, 0x98, 0x75, 0x84, 0x8a, 0x7b, 0x4d, 0xbc, + 0xb2, 0x43, 0xae, 0x5f, 0x51, 0xa0, 0x3d, 0xcc, 0xc2, 0x33, + 0xde, 0x2f, 0x21, 0xd0, 0xe6, 0x17, 0x19, 0xe8, 0x05, 0xf4, + 0xfa, 0x0b, 0xdd, 0x2c, 0x22, 0xd3, 0x3e, 0xcf, 0xc1, 0x30, + 0x06, 0xf7, 0xf9, 0x08, 0xe5, 0x14, 0x1a, 0xeb, 0x76, 0x87, + 0x89, 0x78, 0x95, 0x64, 0x6a, 0x9b, 0xad, 0x5c, 0x52, 0xa3, + 0x4e, 0xbf, 0xb1, 0x40, 0x31, 0xc0, 0xce, 0x3f, 0xd2, 0x23, + 0x2d, 0xdc, 0xea, 0x1b, 0x15, 0xe4, 0x09, 0xf8, 0xf6, 0x07, + 0x9a, 0x6b, 0x65, 0x94, 0x79, 0x88, 0x86, 0x77, 0x41, 0xb0, + 0xbe, 0x4f, 0xa2, 0x53, 0x5d, 0xac, 0x7a, 0x8b, 0x85, 0x74, + 0x99, 0x68, 0x66, 0x97, 0xa1, 0x50, 0x5e, 0xaf, 0x42, 0xb3, + 0xbd, 0x4c, 0xd1, 0x20, 0x2e, 0xdf, 0x32, 0xc3, 0xcd, 0x3c, + 0x0a, 0xfb, 0xf5, 0x04, 0xe9, 0x18, 0x16, 0xe7, 0xa7, 0x56, + 0x58, 0xa9, 0x44, 0xb5, 0xbb, 0x4a, 0x7c, 0x8d, 0x83, 0x72, + 0x9f, 0x6e, 0x60, 0x91, 0x0c, 0xfd, 0xf3, 0x02, 0xef, 0x1e, + 0x10, 0xe1, 0xd7, 0x26, 0x28, 0xd9, 0x34, 0xc5, 0xcb, 0x3a, + 0xec, 0x1d, 0x13, 0xe2, 0x0f, 0xfe, 0xf0, 0x01, 0x37, 0xc6, + 0xc8, 0x39, 0xd4, 0x25, 0x2b, 0xda, 0x47, 0xb6, 0xb8, 0x49, + 0xa4, 0x55, 0x5b, 0xaa, 0x9c, 0x6d, 0x63, 0x92, 0x7f, 0x8e, + 0x80, 0x71, 0x00, 0xf2, 0xf9, 0x0b, 0xef, 0x1d, 0x16, 0xe4, + 0xc3, 0x31, 0x3a, 0xc8, 0x2c, 0xde, 0xd5, 0x27, 0x9b, 0x69, + 0x62, 0x90, 0x74, 0x86, 0x8d, 0x7f, 0x58, 0xaa, 0xa1, 0x53, + 0xb7, 0x45, 0x4e, 0xbc, 0x2b, 0xd9, 0xd2, 0x20, 0xc4, 0x36, + 0x3d, 0xcf, 0xe8, 0x1a, 0x11, 0xe3, 0x07, 0xf5, 0xfe, 0x0c, + 0xb0, 0x42, 0x49, 0xbb, 0x5f, 0xad, 0xa6, 0x54, 0x73, 0x81, + 0x8a, 0x78, 0x9c, 0x6e, 0x65, 0x97, 0x56, 0xa4, 0xaf, 0x5d, + 0xb9, 0x4b, 0x40, 0xb2, 0x95, 0x67, 0x6c, 0x9e, 0x7a, 0x88, + 0x83, 0x71, 0xcd, 0x3f, 0x34, 0xc6, 0x22, 0xd0, 0xdb, 0x29, + 0x0e, 0xfc, 0xf7, 0x05, 0xe1, 0x13, 0x18, 0xea, 0x7d, 0x8f, + 0x84, 0x76, 0x92, 0x60, 0x6b, 0x99, 0xbe, 0x4c, 0x47, 0xb5, + 0x51, 0xa3, 0xa8, 0x5a, 0xe6, 0x14, 0x1f, 0xed, 0x09, 0xfb, + 0xf0, 0x02, 0x25, 0xd7, 0xdc, 0x2e, 0xca, 0x38, 0x33, 0xc1, + 0xac, 0x5e, 0x55, 0xa7, 0x43, 0xb1, 0xba, 0x48, 0x6f, 0x9d, + 0x96, 0x64, 0x80, 0x72, 0x79, 0x8b, 0x37, 0xc5, 0xce, 0x3c, + 0xd8, 0x2a, 0x21, 0xd3, 0xf4, 0x06, 0x0d, 0xff, 0x1b, 0xe9, + 0xe2, 0x10, 0x87, 0x75, 0x7e, 0x8c, 0x68, 0x9a, 0x91, 0x63, + 0x44, 0xb6, 0xbd, 0x4f, 0xab, 0x59, 0x52, 0xa0, 0x1c, 0xee, + 0xe5, 0x17, 0xf3, 0x01, 0x0a, 0xf8, 0xdf, 0x2d, 0x26, 0xd4, + 0x30, 0xc2, 0xc9, 0x3b, 0xfa, 0x08, 0x03, 0xf1, 0x15, 0xe7, + 0xec, 0x1e, 0x39, 0xcb, 0xc0, 0x32, 0xd6, 0x24, 0x2f, 0xdd, + 0x61, 0x93, 0x98, 0x6a, 0x8e, 0x7c, 0x77, 0x85, 0xa2, 0x50, + 0x5b, 0xa9, 0x4d, 0xbf, 0xb4, 0x46, 0xd1, 0x23, 0x28, 0xda, + 0x3e, 0xcc, 0xc7, 0x35, 0x12, 0xe0, 0xeb, 0x19, 0xfd, 0x0f, + 0x04, 0xf6, 0x4a, 0xb8, 0xb3, 0x41, 0xa5, 0x57, 0x5c, 0xae, + 0x89, 0x7b, 0x70, 0x82, 0x66, 0x94, 0x9f, 0x6d, 0x00, 0xf3, + 0xfb, 0x08, 0xeb, 0x18, 0x10, 0xe3, 0xcb, 0x38, 0x30, 0xc3, + 0x20, 0xd3, 0xdb, 0x28, 0x8b, 0x78, 0x70, 0x83, 0x60, 0x93, + 0x9b, 0x68, 0x40, 0xb3, 0xbb, 0x48, 0xab, 0x58, 0x50, 0xa3, + 0x0b, 0xf8, 0xf0, 0x03, 0xe0, 0x13, 0x1b, 0xe8, 0xc0, 0x33, + 0x3b, 0xc8, 0x2b, 0xd8, 0xd0, 0x23, 0x80, 0x73, 0x7b, 0x88, + 0x6b, 0x98, 0x90, 0x63, 0x4b, 0xb8, 0xb0, 0x43, 0xa0, 0x53, + 0x5b, 0xa8, 0x16, 0xe5, 0xed, 0x1e, 0xfd, 0x0e, 0x06, 0xf5, + 0xdd, 0x2e, 0x26, 0xd5, 0x36, 0xc5, 0xcd, 0x3e, 0x9d, 0x6e, + 0x66, 0x95, 0x76, 0x85, 0x8d, 0x7e, 0x56, 0xa5, 0xad, 0x5e, + 0xbd, 0x4e, 0x46, 0xb5, 0x1d, 0xee, 0xe6, 0x15, 0xf6, 0x05, + 0x0d, 0xfe, 0xd6, 0x25, 0x2d, 0xde, 0x3d, 0xce, 0xc6, 0x35, + 0x96, 0x65, 0x6d, 0x9e, 0x7d, 0x8e, 0x86, 0x75, 0x5d, 0xae, + 0xa6, 0x55, 0xb6, 0x45, 0x4d, 0xbe, 0x2c, 0xdf, 0xd7, 0x24, + 0xc7, 0x34, 0x3c, 0xcf, 0xe7, 0x14, 0x1c, 0xef, 0x0c, 0xff, + 0xf7, 0x04, 0xa7, 0x54, 0x5c, 0xaf, 0x4c, 0xbf, 0xb7, 0x44, + 0x6c, 0x9f, 0x97, 0x64, 0x87, 0x74, 0x7c, 0x8f, 0x27, 0xd4, + 0xdc, 0x2f, 0xcc, 0x3f, 0x37, 0xc4, 0xec, 0x1f, 0x17, 0xe4, + 0x07, 0xf4, 0xfc, 0x0f, 0xac, 0x5f, 0x57, 0xa4, 0x47, 0xb4, + 0xbc, 0x4f, 0x67, 0x94, 0x9c, 0x6f, 0x8c, 0x7f, 0x77, 0x84, + 0x3a, 0xc9, 0xc1, 0x32, 0xd1, 0x22, 0x2a, 0xd9, 0xf1, 0x02, + 0x0a, 0xf9, 0x1a, 0xe9, 0xe1, 0x12, 0xb1, 0x42, 0x4a, 0xb9, + 0x5a, 0xa9, 0xa1, 0x52, 0x7a, 0x89, 0x81, 0x72, 0x91, 0x62, + 0x6a, 0x99, 0x31, 0xc2, 0xca, 0x39, 0xda, 0x29, 0x21, 0xd2, + 0xfa, 0x09, 0x01, 0xf2, 0x11, 0xe2, 0xea, 0x19, 0xba, 0x49, + 0x41, 0xb2, 0x51, 0xa2, 0xaa, 0x59, 0x71, 0x82, 0x8a, 0x79, + 0x9a, 0x69, 0x61, 0x92, 0x00, 0xf4, 0xf5, 0x01, 0xf7, 0x03, + 0x02, 0xf6, 0xf3, 0x07, 0x06, 0xf2, 0x04, 0xf0, 0xf1, 0x05, + 0xfb, 0x0f, 0x0e, 0xfa, 0x0c, 0xf8, 0xf9, 0x0d, 0x08, 0xfc, + 0xfd, 0x09, 0xff, 0x0b, 0x0a, 0xfe, 0xeb, 0x1f, 0x1e, 0xea, + 0x1c, 0xe8, 0xe9, 0x1d, 0x18, 0xec, 0xed, 0x19, 0xef, 0x1b, + 0x1a, 0xee, 0x10, 0xe4, 0xe5, 0x11, 0xe7, 0x13, 0x12, 0xe6, + 0xe3, 0x17, 0x16, 0xe2, 0x14, 0xe0, 0xe1, 0x15, 0xcb, 0x3f, + 0x3e, 0xca, 0x3c, 0xc8, 0xc9, 0x3d, 0x38, 0xcc, 0xcd, 0x39, + 0xcf, 0x3b, 0x3a, 0xce, 0x30, 0xc4, 0xc5, 0x31, 0xc7, 0x33, + 0x32, 0xc6, 0xc3, 0x37, 0x36, 0xc2, 0x34, 0xc0, 0xc1, 0x35, + 0x20, 0xd4, 0xd5, 0x21, 0xd7, 0x23, 0x22, 0xd6, 0xd3, 0x27, + 0x26, 0xd2, 0x24, 0xd0, 0xd1, 0x25, 0xdb, 0x2f, 0x2e, 0xda, + 0x2c, 0xd8, 0xd9, 0x2d, 0x28, 0xdc, 0xdd, 0x29, 0xdf, 0x2b, + 0x2a, 0xde, 0x8b, 0x7f, 0x7e, 0x8a, 0x7c, 0x88, 0x89, 0x7d, + 0x78, 0x8c, 0x8d, 0x79, 0x8f, 0x7b, 0x7a, 0x8e, 0x70, 0x84, + 0x85, 0x71, 0x87, 0x73, 0x72, 0x86, 0x83, 0x77, 0x76, 0x82, + 0x74, 0x80, 0x81, 0x75, 0x60, 0x94, 0x95, 0x61, 0x97, 0x63, + 0x62, 0x96, 0x93, 0x67, 0x66, 0x92, 0x64, 0x90, 0x91, 0x65, + 0x9b, 0x6f, 0x6e, 0x9a, 0x6c, 0x98, 0x99, 0x6d, 0x68, 0x9c, + 0x9d, 0x69, 0x9f, 0x6b, 0x6a, 0x9e, 0x40, 0xb4, 0xb5, 0x41, + 0xb7, 0x43, 0x42, 0xb6, 0xb3, 0x47, 0x46, 0xb2, 0x44, 0xb0, + 0xb1, 0x45, 0xbb, 0x4f, 0x4e, 0xba, 0x4c, 0xb8, 0xb9, 0x4d, + 0x48, 0xbc, 0xbd, 0x49, 0xbf, 0x4b, 0x4a, 0xbe, 0xab, 0x5f, + 0x5e, 0xaa, 0x5c, 0xa8, 0xa9, 0x5d, 0x58, 0xac, 0xad, 0x59, + 0xaf, 0x5b, 0x5a, 0xae, 0x50, 0xa4, 0xa5, 0x51, 0xa7, 0x53, + 0x52, 0xa6, 0xa3, 0x57, 0x56, 0xa2, 0x54, 0xa0, 0xa1, 0x55, + 0x00, 0xf5, 0xf7, 0x02, 0xf3, 0x06, 0x04, 0xf1, 0xfb, 0x0e, + 0x0c, 0xf9, 0x08, 0xfd, 0xff, 0x0a, 0xeb, 0x1e, 0x1c, 0xe9, + 0x18, 0xed, 0xef, 0x1a, 0x10, 0xe5, 0xe7, 0x12, 0xe3, 0x16, + 0x14, 0xe1, 0xcb, 0x3e, 0x3c, 0xc9, 0x38, 0xcd, 0xcf, 0x3a, + 0x30, 0xc5, 0xc7, 0x32, 0xc3, 0x36, 0x34, 0xc1, 0x20, 0xd5, + 0xd7, 0x22, 0xd3, 0x26, 0x24, 0xd1, 0xdb, 0x2e, 0x2c, 0xd9, + 0x28, 0xdd, 0xdf, 0x2a, 0x8b, 0x7e, 0x7c, 0x89, 0x78, 0x8d, + 0x8f, 0x7a, 0x70, 0x85, 0x87, 0x72, 0x83, 0x76, 0x74, 0x81, + 0x60, 0x95, 0x97, 0x62, 0x93, 0x66, 0x64, 0x91, 0x9b, 0x6e, + 0x6c, 0x99, 0x68, 0x9d, 0x9f, 0x6a, 0x40, 0xb5, 0xb7, 0x42, + 0xb3, 0x46, 0x44, 0xb1, 0xbb, 0x4e, 0x4c, 0xb9, 0x48, 0xbd, + 0xbf, 0x4a, 0xab, 0x5e, 0x5c, 0xa9, 0x58, 0xad, 0xaf, 0x5a, + 0x50, 0xa5, 0xa7, 0x52, 0xa3, 0x56, 0x54, 0xa1, 0x0b, 0xfe, + 0xfc, 0x09, 0xf8, 0x0d, 0x0f, 0xfa, 0xf0, 0x05, 0x07, 0xf2, + 0x03, 0xf6, 0xf4, 0x01, 0xe0, 0x15, 0x17, 0xe2, 0x13, 0xe6, + 0xe4, 0x11, 0x1b, 0xee, 0xec, 0x19, 0xe8, 0x1d, 0x1f, 0xea, + 0xc0, 0x35, 0x37, 0xc2, 0x33, 0xc6, 0xc4, 0x31, 0x3b, 0xce, + 0xcc, 0x39, 0xc8, 0x3d, 0x3f, 0xca, 0x2b, 0xde, 0xdc, 0x29, + 0xd8, 0x2d, 0x2f, 0xda, 0xd0, 0x25, 0x27, 0xd2, 0x23, 0xd6, + 0xd4, 0x21, 0x80, 0x75, 0x77, 0x82, 0x73, 0x86, 0x84, 0x71, + 0x7b, 0x8e, 0x8c, 0x79, 0x88, 0x7d, 0x7f, 0x8a, 0x6b, 0x9e, + 0x9c, 0x69, 0x98, 0x6d, 0x6f, 0x9a, 0x90, 0x65, 0x67, 0x92, + 0x63, 0x96, 0x94, 0x61, 0x4b, 0xbe, 0xbc, 0x49, 0xb8, 0x4d, + 0x4f, 0xba, 0xb0, 0x45, 0x47, 0xb2, 0x43, 0xb6, 0xb4, 0x41, + 0xa0, 0x55, 0x57, 0xa2, 0x53, 0xa6, 0xa4, 0x51, 0x5b, 0xae, + 0xac, 0x59, 0xa8, 0x5d, 0x5f, 0xaa, 0x00, 0xf6, 0xf1, 0x07, + 0xff, 0x09, 0x0e, 0xf8, 0xe3, 0x15, 0x12, 0xe4, 0x1c, 0xea, + 0xed, 0x1b, 0xdb, 0x2d, 0x2a, 0xdc, 0x24, 0xd2, 0xd5, 0x23, + 0x38, 0xce, 0xc9, 0x3f, 0xc7, 0x31, 0x36, 0xc0, 0xab, 0x5d, + 0x5a, 0xac, 0x54, 0xa2, 0xa5, 0x53, 0x48, 0xbe, 0xb9, 0x4f, + 0xb7, 0x41, 0x46, 0xb0, 0x70, 0x86, 0x81, 0x77, 0x8f, 0x79, + 0x7e, 0x88, 0x93, 0x65, 0x62, 0x94, 0x6c, 0x9a, 0x9d, 0x6b, + 0x4b, 0xbd, 0xba, 0x4c, 0xb4, 0x42, 0x45, 0xb3, 0xa8, 0x5e, + 0x59, 0xaf, 0x57, 0xa1, 0xa6, 0x50, 0x90, 0x66, 0x61, 0x97, + 0x6f, 0x99, 0x9e, 0x68, 0x73, 0x85, 0x82, 0x74, 0x8c, 0x7a, + 0x7d, 0x8b, 0xe0, 0x16, 0x11, 0xe7, 0x1f, 0xe9, 0xee, 0x18, + 0x03, 0xf5, 0xf2, 0x04, 0xfc, 0x0a, 0x0d, 0xfb, 0x3b, 0xcd, + 0xca, 0x3c, 0xc4, 0x32, 0x35, 0xc3, 0xd8, 0x2e, 0x29, 0xdf, + 0x27, 0xd1, 0xd6, 0x20, 0x96, 0x60, 0x67, 0x91, 0x69, 0x9f, + 0x98, 0x6e, 0x75, 0x83, 0x84, 0x72, 0x8a, 0x7c, 0x7b, 0x8d, + 0x4d, 0xbb, 0xbc, 0x4a, 0xb2, 0x44, 0x43, 0xb5, 0xae, 0x58, + 0x5f, 0xa9, 0x51, 0xa7, 0xa0, 0x56, 0x3d, 0xcb, 0xcc, 0x3a, + 0xc2, 0x34, 0x33, 0xc5, 0xde, 0x28, 0x2f, 0xd9, 0x21, 0xd7, + 0xd0, 0x26, 0xe6, 0x10, 0x17, 0xe1, 0x19, 0xef, 0xe8, 0x1e, + 0x05, 0xf3, 0xf4, 0x02, 0xfa, 0x0c, 0x0b, 0xfd, 0xdd, 0x2b, + 0x2c, 0xda, 0x22, 0xd4, 0xd3, 0x25, 0x3e, 0xc8, 0xcf, 0x39, + 0xc1, 0x37, 0x30, 0xc6, 0x06, 0xf0, 0xf7, 0x01, 0xf9, 0x0f, + 0x08, 0xfe, 0xe5, 0x13, 0x14, 0xe2, 0x1a, 0xec, 0xeb, 0x1d, + 0x76, 0x80, 0x87, 0x71, 0x89, 0x7f, 0x78, 0x8e, 0x95, 0x63, + 0x64, 0x92, 0x6a, 0x9c, 0x9b, 0x6d, 0xad, 0x5b, 0x5c, 0xaa, + 0x52, 0xa4, 0xa3, 0x55, 0x4e, 0xb8, 0xbf, 0x49, 0xb1, 0x47, + 0x40, 0xb6, 0x00, 0xf7, 0xf3, 0x04, 0xfb, 0x0c, 0x08, 0xff, + 0xeb, 0x1c, 0x18, 0xef, 0x10, 0xe7, 0xe3, 0x14, 0xcb, 0x3c, + 0x38, 0xcf, 0x30, 0xc7, 0xc3, 0x34, 0x20, 0xd7, 0xd3, 0x24, + 0xdb, 0x2c, 0x28, 0xdf, 0x8b, 0x7c, 0x78, 0x8f, 0x70, 0x87, + 0x83, 0x74, 0x60, 0x97, 0x93, 0x64, 0x9b, 0x6c, 0x68, 0x9f, + 0x40, 0xb7, 0xb3, 0x44, 0xbb, 0x4c, 0x48, 0xbf, 0xab, 0x5c, + 0x58, 0xaf, 0x50, 0xa7, 0xa3, 0x54, 0x0b, 0xfc, 0xf8, 0x0f, + 0xf0, 0x07, 0x03, 0xf4, 0xe0, 0x17, 0x13, 0xe4, 0x1b, 0xec, + 0xe8, 0x1f, 0xc0, 0x37, 0x33, 0xc4, 0x3b, 0xcc, 0xc8, 0x3f, + 0x2b, 0xdc, 0xd8, 0x2f, 0xd0, 0x27, 0x23, 0xd4, 0x80, 0x77, + 0x73, 0x84, 0x7b, 0x8c, 0x88, 0x7f, 0x6b, 0x9c, 0x98, 0x6f, + 0x90, 0x67, 0x63, 0x94, 0x4b, 0xbc, 0xb8, 0x4f, 0xb0, 0x47, + 0x43, 0xb4, 0xa0, 0x57, 0x53, 0xa4, 0x5b, 0xac, 0xa8, 0x5f, + 0x16, 0xe1, 0xe5, 0x12, 0xed, 0x1a, 0x1e, 0xe9, 0xfd, 0x0a, + 0x0e, 0xf9, 0x06, 0xf1, 0xf5, 0x02, 0xdd, 0x2a, 0x2e, 0xd9, + 0x26, 0xd1, 0xd5, 0x22, 0x36, 0xc1, 0xc5, 0x32, 0xcd, 0x3a, + 0x3e, 0xc9, 0x9d, 0x6a, 0x6e, 0x99, 0x66, 0x91, 0x95, 0x62, + 0x76, 0x81, 0x85, 0x72, 0x8d, 0x7a, 0x7e, 0x89, 0x56, 0xa1, + 0xa5, 0x52, 0xad, 0x5a, 0x5e, 0xa9, 0xbd, 0x4a, 0x4e, 0xb9, + 0x46, 0xb1, 0xb5, 0x42, 0x1d, 0xea, 0xee, 0x19, 0xe6, 0x11, + 0x15, 0xe2, 0xf6, 0x01, 0x05, 0xf2, 0x0d, 0xfa, 0xfe, 0x09, + 0xd6, 0x21, 0x25, 0xd2, 0x2d, 0xda, 0xde, 0x29, 0x3d, 0xca, + 0xce, 0x39, 0xc6, 0x31, 0x35, 0xc2, 0x96, 0x61, 0x65, 0x92, + 0x6d, 0x9a, 0x9e, 0x69, 0x7d, 0x8a, 0x8e, 0x79, 0x86, 0x71, + 0x75, 0x82, 0x5d, 0xaa, 0xae, 0x59, 0xa6, 0x51, 0x55, 0xa2, + 0xb6, 0x41, 0x45, 0xb2, 0x4d, 0xba, 0xbe, 0x49, 0x00, 0xf8, + 0xed, 0x15, 0xc7, 0x3f, 0x2a, 0xd2, 0x93, 0x6b, 0x7e, 0x86, + 0x54, 0xac, 0xb9, 0x41, 0x3b, 0xc3, 0xd6, 0x2e, 0xfc, 0x04, + 0x11, 0xe9, 0xa8, 0x50, 0x45, 0xbd, 0x6f, 0x97, 0x82, 0x7a, + 0x76, 0x8e, 0x9b, 0x63, 0xb1, 0x49, 0x5c, 0xa4, 0xe5, 0x1d, + 0x08, 0xf0, 0x22, 0xda, 0xcf, 0x37, 0x4d, 0xb5, 0xa0, 0x58, + 0x8a, 0x72, 0x67, 0x9f, 0xde, 0x26, 0x33, 0xcb, 0x19, 0xe1, + 0xf4, 0x0c, 0xec, 0x14, 0x01, 0xf9, 0x2b, 0xd3, 0xc6, 0x3e, + 0x7f, 0x87, 0x92, 0x6a, 0xb8, 0x40, 0x55, 0xad, 0xd7, 0x2f, + 0x3a, 0xc2, 0x10, 0xe8, 0xfd, 0x05, 0x44, 0xbc, 0xa9, 0x51, + 0x83, 0x7b, 0x6e, 0x96, 0x9a, 0x62, 0x77, 0x8f, 0x5d, 0xa5, + 0xb0, 0x48, 0x09, 0xf1, 0xe4, 0x1c, 0xce, 0x36, 0x23, 0xdb, + 0xa1, 0x59, 0x4c, 0xb4, 0x66, 0x9e, 0x8b, 0x73, 0x32, 0xca, + 0xdf, 0x27, 0xf5, 0x0d, 0x18, 0xe0, 0xc5, 0x3d, 0x28, 0xd0, + 0x02, 0xfa, 0xef, 0x17, 0x56, 0xae, 0xbb, 0x43, 0x91, 0x69, + 0x7c, 0x84, 0xfe, 0x06, 0x13, 0xeb, 0x39, 0xc1, 0xd4, 0x2c, + 0x6d, 0x95, 0x80, 0x78, 0xaa, 0x52, 0x47, 0xbf, 0xb3, 0x4b, + 0x5e, 0xa6, 0x74, 0x8c, 0x99, 0x61, 0x20, 0xd8, 0xcd, 0x35, + 0xe7, 0x1f, 0x0a, 0xf2, 0x88, 0x70, 0x65, 0x9d, 0x4f, 0xb7, + 0xa2, 0x5a, 0x1b, 0xe3, 0xf6, 0x0e, 0xdc, 0x24, 0x31, 0xc9, + 0x29, 0xd1, 0xc4, 0x3c, 0xee, 0x16, 0x03, 0xfb, 0xba, 0x42, + 0x57, 0xaf, 0x7d, 0x85, 0x90, 0x68, 0x12, 0xea, 0xff, 0x07, + 0xd5, 0x2d, 0x38, 0xc0, 0x81, 0x79, 0x6c, 0x94, 0x46, 0xbe, + 0xab, 0x53, 0x5f, 0xa7, 0xb2, 0x4a, 0x98, 0x60, 0x75, 0x8d, + 0xcc, 0x34, 0x21, 0xd9, 0x0b, 0xf3, 0xe6, 0x1e, 0x64, 0x9c, + 0x89, 0x71, 0xa3, 0x5b, 0x4e, 0xb6, 0xf7, 0x0f, 0x1a, 0xe2, + 0x30, 0xc8, 0xdd, 0x25, 0x00, 0xf9, 0xef, 0x16, 0xc3, 0x3a, + 0x2c, 0xd5, 0x9b, 0x62, 0x74, 0x8d, 0x58, 0xa1, 0xb7, 0x4e, + 0x2b, 0xd2, 0xc4, 0x3d, 0xe8, 0x11, 0x07, 0xfe, 0xb0, 0x49, + 0x5f, 0xa6, 0x73, 0x8a, 0x9c, 0x65, 0x56, 0xaf, 0xb9, 0x40, + 0x95, 0x6c, 0x7a, 0x83, 0xcd, 0x34, 0x22, 0xdb, 0x0e, 0xf7, + 0xe1, 0x18, 0x7d, 0x84, 0x92, 0x6b, 0xbe, 0x47, 0x51, 0xa8, + 0xe6, 0x1f, 0x09, 0xf0, 0x25, 0xdc, 0xca, 0x33, 0xac, 0x55, + 0x43, 0xba, 0x6f, 0x96, 0x80, 0x79, 0x37, 0xce, 0xd8, 0x21, + 0xf4, 0x0d, 0x1b, 0xe2, 0x87, 0x7e, 0x68, 0x91, 0x44, 0xbd, + 0xab, 0x52, 0x1c, 0xe5, 0xf3, 0x0a, 0xdf, 0x26, 0x30, 0xc9, + 0xfa, 0x03, 0x15, 0xec, 0x39, 0xc0, 0xd6, 0x2f, 0x61, 0x98, + 0x8e, 0x77, 0xa2, 0x5b, 0x4d, 0xb4, 0xd1, 0x28, 0x3e, 0xc7, + 0x12, 0xeb, 0xfd, 0x04, 0x4a, 0xb3, 0xa5, 0x5c, 0x89, 0x70, + 0x66, 0x9f, 0x45, 0xbc, 0xaa, 0x53, 0x86, 0x7f, 0x69, 0x90, + 0xde, 0x27, 0x31, 0xc8, 0x1d, 0xe4, 0xf2, 0x0b, 0x6e, 0x97, + 0x81, 0x78, 0xad, 0x54, 0x42, 0xbb, 0xf5, 0x0c, 0x1a, 0xe3, + 0x36, 0xcf, 0xd9, 0x20, 0x13, 0xea, 0xfc, 0x05, 0xd0, 0x29, + 0x3f, 0xc6, 0x88, 0x71, 0x67, 0x9e, 0x4b, 0xb2, 0xa4, 0x5d, + 0x38, 0xc1, 0xd7, 0x2e, 0xfb, 0x02, 0x14, 0xed, 0xa3, 0x5a, + 0x4c, 0xb5, 0x60, 0x99, 0x8f, 0x76, 0xe9, 0x10, 0x06, 0xff, + 0x2a, 0xd3, 0xc5, 0x3c, 0x72, 0x8b, 0x9d, 0x64, 0xb1, 0x48, + 0x5e, 0xa7, 0xc2, 0x3b, 0x2d, 0xd4, 0x01, 0xf8, 0xee, 0x17, + 0x59, 0xa0, 0xb6, 0x4f, 0x9a, 0x63, 0x75, 0x8c, 0xbf, 0x46, + 0x50, 0xa9, 0x7c, 0x85, 0x93, 0x6a, 0x24, 0xdd, 0xcb, 0x32, + 0xe7, 0x1e, 0x08, 0xf1, 0x94, 0x6d, 0x7b, 0x82, 0x57, 0xae, + 0xb8, 0x41, 0x0f, 0xf6, 0xe0, 0x19, 0xcc, 0x35, 0x23, 0xda, + 0x00, 0xfa, 0xe9, 0x13, 0xcf, 0x35, 0x26, 0xdc, 0x83, 0x79, + 0x6a, 0x90, 0x4c, 0xb6, 0xa5, 0x5f, 0x1b, 0xe1, 0xf2, 0x08, + 0xd4, 0x2e, 0x3d, 0xc7, 0x98, 0x62, 0x71, 0x8b, 0x57, 0xad, + 0xbe, 0x44, 0x36, 0xcc, 0xdf, 0x25, 0xf9, 0x03, 0x10, 0xea, + 0xb5, 0x4f, 0x5c, 0xa6, 0x7a, 0x80, 0x93, 0x69, 0x2d, 0xd7, + 0xc4, 0x3e, 0xe2, 0x18, 0x0b, 0xf1, 0xae, 0x54, 0x47, 0xbd, + 0x61, 0x9b, 0x88, 0x72, 0x6c, 0x96, 0x85, 0x7f, 0xa3, 0x59, + 0x4a, 0xb0, 0xef, 0x15, 0x06, 0xfc, 0x20, 0xda, 0xc9, 0x33, + 0x77, 0x8d, 0x9e, 0x64, 0xb8, 0x42, 0x51, 0xab, 0xf4, 0x0e, + 0x1d, 0xe7, 0x3b, 0xc1, 0xd2, 0x28, 0x5a, 0xa0, 0xb3, 0x49, + 0x95, 0x6f, 0x7c, 0x86, 0xd9, 0x23, 0x30, 0xca, 0x16, 0xec, + 0xff, 0x05, 0x41, 0xbb, 0xa8, 0x52, 0x8e, 0x74, 0x67, 0x9d, + 0xc2, 0x38, 0x2b, 0xd1, 0x0d, 0xf7, 0xe4, 0x1e, 0xd8, 0x22, + 0x31, 0xcb, 0x17, 0xed, 0xfe, 0x04, 0x5b, 0xa1, 0xb2, 0x48, + 0x94, 0x6e, 0x7d, 0x87, 0xc3, 0x39, 0x2a, 0xd0, 0x0c, 0xf6, + 0xe5, 0x1f, 0x40, 0xba, 0xa9, 0x53, 0x8f, 0x75, 0x66, 0x9c, + 0xee, 0x14, 0x07, 0xfd, 0x21, 0xdb, 0xc8, 0x32, 0x6d, 0x97, + 0x84, 0x7e, 0xa2, 0x58, 0x4b, 0xb1, 0xf5, 0x0f, 0x1c, 0xe6, + 0x3a, 0xc0, 0xd3, 0x29, 0x76, 0x8c, 0x9f, 0x65, 0xb9, 0x43, + 0x50, 0xaa, 0xb4, 0x4e, 0x5d, 0xa7, 0x7b, 0x81, 0x92, 0x68, + 0x37, 0xcd, 0xde, 0x24, 0xf8, 0x02, 0x11, 0xeb, 0xaf, 0x55, + 0x46, 0xbc, 0x60, 0x9a, 0x89, 0x73, 0x2c, 0xd6, 0xc5, 0x3f, + 0xe3, 0x19, 0x0a, 0xf0, 0x82, 0x78, 0x6b, 0x91, 0x4d, 0xb7, + 0xa4, 0x5e, 0x01, 0xfb, 0xe8, 0x12, 0xce, 0x34, 0x27, 0xdd, + 0x99, 0x63, 0x70, 0x8a, 0x56, 0xac, 0xbf, 0x45, 0x1a, 0xe0, + 0xf3, 0x09, 0xd5, 0x2f, 0x3c, 0xc6, 0x00, 0xfb, 0xeb, 0x10, + 0xcb, 0x30, 0x20, 0xdb, 0x8b, 0x70, 0x60, 0x9b, 0x40, 0xbb, + 0xab, 0x50, 0x0b, 0xf0, 0xe0, 0x1b, 0xc0, 0x3b, 0x2b, 0xd0, + 0x80, 0x7b, 0x6b, 0x90, 0x4b, 0xb0, 0xa0, 0x5b, 0x16, 0xed, + 0xfd, 0x06, 0xdd, 0x26, 0x36, 0xcd, 0x9d, 0x66, 0x76, 0x8d, + 0x56, 0xad, 0xbd, 0x46, 0x1d, 0xe6, 0xf6, 0x0d, 0xd6, 0x2d, + 0x3d, 0xc6, 0x96, 0x6d, 0x7d, 0x86, 0x5d, 0xa6, 0xb6, 0x4d, + 0x2c, 0xd7, 0xc7, 0x3c, 0xe7, 0x1c, 0x0c, 0xf7, 0xa7, 0x5c, + 0x4c, 0xb7, 0x6c, 0x97, 0x87, 0x7c, 0x27, 0xdc, 0xcc, 0x37, + 0xec, 0x17, 0x07, 0xfc, 0xac, 0x57, 0x47, 0xbc, 0x67, 0x9c, + 0x8c, 0x77, 0x3a, 0xc1, 0xd1, 0x2a, 0xf1, 0x0a, 0x1a, 0xe1, + 0xb1, 0x4a, 0x5a, 0xa1, 0x7a, 0x81, 0x91, 0x6a, 0x31, 0xca, + 0xda, 0x21, 0xfa, 0x01, 0x11, 0xea, 0xba, 0x41, 0x51, 0xaa, + 0x71, 0x8a, 0x9a, 0x61, 0x58, 0xa3, 0xb3, 0x48, 0x93, 0x68, + 0x78, 0x83, 0xd3, 0x28, 0x38, 0xc3, 0x18, 0xe3, 0xf3, 0x08, + 0x53, 0xa8, 0xb8, 0x43, 0x98, 0x63, 0x73, 0x88, 0xd8, 0x23, + 0x33, 0xc8, 0x13, 0xe8, 0xf8, 0x03, 0x4e, 0xb5, 0xa5, 0x5e, + 0x85, 0x7e, 0x6e, 0x95, 0xc5, 0x3e, 0x2e, 0xd5, 0x0e, 0xf5, + 0xe5, 0x1e, 0x45, 0xbe, 0xae, 0x55, 0x8e, 0x75, 0x65, 0x9e, + 0xce, 0x35, 0x25, 0xde, 0x05, 0xfe, 0xee, 0x15, 0x74, 0x8f, + 0x9f, 0x64, 0xbf, 0x44, 0x54, 0xaf, 0xff, 0x04, 0x14, 0xef, + 0x34, 0xcf, 0xdf, 0x24, 0x7f, 0x84, 0x94, 0x6f, 0xb4, 0x4f, + 0x5f, 0xa4, 0xf4, 0x0f, 0x1f, 0xe4, 0x3f, 0xc4, 0xd4, 0x2f, + 0x62, 0x99, 0x89, 0x72, 0xa9, 0x52, 0x42, 0xb9, 0xe9, 0x12, + 0x02, 0xf9, 0x22, 0xd9, 0xc9, 0x32, 0x69, 0x92, 0x82, 0x79, + 0xa2, 0x59, 0x49, 0xb2, 0xe2, 0x19, 0x09, 0xf2, 0x29, 0xd2, + 0xc2, 0x39, 0x00, 0xfc, 0xe5, 0x19, 0xd7, 0x2b, 0x32, 0xce, + 0xb3, 0x4f, 0x56, 0xaa, 0x64, 0x98, 0x81, 0x7d, 0x7b, 0x87, + 0x9e, 0x62, 0xac, 0x50, 0x49, 0xb5, 0xc8, 0x34, 0x2d, 0xd1, + 0x1f, 0xe3, 0xfa, 0x06, 0xf6, 0x0a, 0x13, 0xef, 0x21, 0xdd, + 0xc4, 0x38, 0x45, 0xb9, 0xa0, 0x5c, 0x92, 0x6e, 0x77, 0x8b, + 0x8d, 0x71, 0x68, 0x94, 0x5a, 0xa6, 0xbf, 0x43, 0x3e, 0xc2, + 0xdb, 0x27, 0xe9, 0x15, 0x0c, 0xf0, 0xf1, 0x0d, 0x14, 0xe8, + 0x26, 0xda, 0xc3, 0x3f, 0x42, 0xbe, 0xa7, 0x5b, 0x95, 0x69, + 0x70, 0x8c, 0x8a, 0x76, 0x6f, 0x93, 0x5d, 0xa1, 0xb8, 0x44, + 0x39, 0xc5, 0xdc, 0x20, 0xee, 0x12, 0x0b, 0xf7, 0x07, 0xfb, + 0xe2, 0x1e, 0xd0, 0x2c, 0x35, 0xc9, 0xb4, 0x48, 0x51, 0xad, + 0x63, 0x9f, 0x86, 0x7a, 0x7c, 0x80, 0x99, 0x65, 0xab, 0x57, + 0x4e, 0xb2, 0xcf, 0x33, 0x2a, 0xd6, 0x18, 0xe4, 0xfd, 0x01, + 0xff, 0x03, 0x1a, 0xe6, 0x28, 0xd4, 0xcd, 0x31, 0x4c, 0xb0, + 0xa9, 0x55, 0x9b, 0x67, 0x7e, 0x82, 0x84, 0x78, 0x61, 0x9d, + 0x53, 0xaf, 0xb6, 0x4a, 0x37, 0xcb, 0xd2, 0x2e, 0xe0, 0x1c, + 0x05, 0xf9, 0x09, 0xf5, 0xec, 0x10, 0xde, 0x22, 0x3b, 0xc7, + 0xba, 0x46, 0x5f, 0xa3, 0x6d, 0x91, 0x88, 0x74, 0x72, 0x8e, + 0x97, 0x6b, 0xa5, 0x59, 0x40, 0xbc, 0xc1, 0x3d, 0x24, 0xd8, + 0x16, 0xea, 0xf3, 0x0f, 0x0e, 0xf2, 0xeb, 0x17, 0xd9, 0x25, + 0x3c, 0xc0, 0xbd, 0x41, 0x58, 0xa4, 0x6a, 0x96, 0x8f, 0x73, + 0x75, 0x89, 0x90, 0x6c, 0xa2, 0x5e, 0x47, 0xbb, 0xc6, 0x3a, + 0x23, 0xdf, 0x11, 0xed, 0xf4, 0x08, 0xf8, 0x04, 0x1d, 0xe1, + 0x2f, 0xd3, 0xca, 0x36, 0x4b, 0xb7, 0xae, 0x52, 0x9c, 0x60, + 0x79, 0x85, 0x83, 0x7f, 0x66, 0x9a, 0x54, 0xa8, 0xb1, 0x4d, + 0x30, 0xcc, 0xd5, 0x29, 0xe7, 0x1b, 0x02, 0xfe, 0x00, 0xfd, + 0xe7, 0x1a, 0xd3, 0x2e, 0x34, 0xc9, 0xbb, 0x46, 0x5c, 0xa1, + 0x68, 0x95, 0x8f, 0x72, 0x6b, 0x96, 0x8c, 0x71, 0xb8, 0x45, + 0x5f, 0xa2, 0xd0, 0x2d, 0x37, 0xca, 0x03, 0xfe, 0xe4, 0x19, + 0xd6, 0x2b, 0x31, 0xcc, 0x05, 0xf8, 0xe2, 0x1f, 0x6d, 0x90, + 0x8a, 0x77, 0xbe, 0x43, 0x59, 0xa4, 0xbd, 0x40, 0x5a, 0xa7, + 0x6e, 0x93, 0x89, 0x74, 0x06, 0xfb, 0xe1, 0x1c, 0xd5, 0x28, + 0x32, 0xcf, 0xb1, 0x4c, 0x56, 0xab, 0x62, 0x9f, 0x85, 0x78, + 0x0a, 0xf7, 0xed, 0x10, 0xd9, 0x24, 0x3e, 0xc3, 0xda, 0x27, + 0x3d, 0xc0, 0x09, 0xf4, 0xee, 0x13, 0x61, 0x9c, 0x86, 0x7b, + 0xb2, 0x4f, 0x55, 0xa8, 0x67, 0x9a, 0x80, 0x7d, 0xb4, 0x49, + 0x53, 0xae, 0xdc, 0x21, 0x3b, 0xc6, 0x0f, 0xf2, 0xe8, 0x15, + 0x0c, 0xf1, 0xeb, 0x16, 0xdf, 0x22, 0x38, 0xc5, 0xb7, 0x4a, + 0x50, 0xad, 0x64, 0x99, 0x83, 0x7e, 0x7f, 0x82, 0x98, 0x65, + 0xac, 0x51, 0x4b, 0xb6, 0xc4, 0x39, 0x23, 0xde, 0x17, 0xea, + 0xf0, 0x0d, 0x14, 0xe9, 0xf3, 0x0e, 0xc7, 0x3a, 0x20, 0xdd, + 0xaf, 0x52, 0x48, 0xb5, 0x7c, 0x81, 0x9b, 0x66, 0xa9, 0x54, + 0x4e, 0xb3, 0x7a, 0x87, 0x9d, 0x60, 0x12, 0xef, 0xf5, 0x08, + 0xc1, 0x3c, 0x26, 0xdb, 0xc2, 0x3f, 0x25, 0xd8, 0x11, 0xec, + 0xf6, 0x0b, 0x79, 0x84, 0x9e, 0x63, 0xaa, 0x57, 0x4d, 0xb0, + 0xce, 0x33, 0x29, 0xd4, 0x1d, 0xe0, 0xfa, 0x07, 0x75, 0x88, + 0x92, 0x6f, 0xa6, 0x5b, 0x41, 0xbc, 0xa5, 0x58, 0x42, 0xbf, + 0x76, 0x8b, 0x91, 0x6c, 0x1e, 0xe3, 0xf9, 0x04, 0xcd, 0x30, + 0x2a, 0xd7, 0x18, 0xe5, 0xff, 0x02, 0xcb, 0x36, 0x2c, 0xd1, + 0xa3, 0x5e, 0x44, 0xb9, 0x70, 0x8d, 0x97, 0x6a, 0x73, 0x8e, + 0x94, 0x69, 0xa0, 0x5d, 0x47, 0xba, 0xc8, 0x35, 0x2f, 0xd2, + 0x1b, 0xe6, 0xfc, 0x01, 0x00, 0xfe, 0xe1, 0x1f, 0xdf, 0x21, + 0x3e, 0xc0, 0xa3, 0x5d, 0x42, 0xbc, 0x7c, 0x82, 0x9d, 0x63, + 0x5b, 0xa5, 0xba, 0x44, 0x84, 0x7a, 0x65, 0x9b, 0xf8, 0x06, + 0x19, 0xe7, 0x27, 0xd9, 0xc6, 0x38, 0xb6, 0x48, 0x57, 0xa9, + 0x69, 0x97, 0x88, 0x76, 0x15, 0xeb, 0xf4, 0x0a, 0xca, 0x34, + 0x2b, 0xd5, 0xed, 0x13, 0x0c, 0xf2, 0x32, 0xcc, 0xd3, 0x2d, + 0x4e, 0xb0, 0xaf, 0x51, 0x91, 0x6f, 0x70, 0x8e, 0x71, 0x8f, + 0x90, 0x6e, 0xae, 0x50, 0x4f, 0xb1, 0xd2, 0x2c, 0x33, 0xcd, + 0x0d, 0xf3, 0xec, 0x12, 0x2a, 0xd4, 0xcb, 0x35, 0xf5, 0x0b, + 0x14, 0xea, 0x89, 0x77, 0x68, 0x96, 0x56, 0xa8, 0xb7, 0x49, + 0xc7, 0x39, 0x26, 0xd8, 0x18, 0xe6, 0xf9, 0x07, 0x64, 0x9a, + 0x85, 0x7b, 0xbb, 0x45, 0x5a, 0xa4, 0x9c, 0x62, 0x7d, 0x83, + 0x43, 0xbd, 0xa2, 0x5c, 0x3f, 0xc1, 0xde, 0x20, 0xe0, 0x1e, + 0x01, 0xff, 0xe2, 0x1c, 0x03, 0xfd, 0x3d, 0xc3, 0xdc, 0x22, + 0x41, 0xbf, 0xa0, 0x5e, 0x9e, 0x60, 0x7f, 0x81, 0xb9, 0x47, + 0x58, 0xa6, 0x66, 0x98, 0x87, 0x79, 0x1a, 0xe4, 0xfb, 0x05, + 0xc5, 0x3b, 0x24, 0xda, 0x54, 0xaa, 0xb5, 0x4b, 0x8b, 0x75, + 0x6a, 0x94, 0xf7, 0x09, 0x16, 0xe8, 0x28, 0xd6, 0xc9, 0x37, + 0x0f, 0xf1, 0xee, 0x10, 0xd0, 0x2e, 0x31, 0xcf, 0xac, 0x52, + 0x4d, 0xb3, 0x73, 0x8d, 0x92, 0x6c, 0x93, 0x6d, 0x72, 0x8c, + 0x4c, 0xb2, 0xad, 0x53, 0x30, 0xce, 0xd1, 0x2f, 0xef, 0x11, + 0x0e, 0xf0, 0xc8, 0x36, 0x29, 0xd7, 0x17, 0xe9, 0xf6, 0x08, + 0x6b, 0x95, 0x8a, 0x74, 0xb4, 0x4a, 0x55, 0xab, 0x25, 0xdb, + 0xc4, 0x3a, 0xfa, 0x04, 0x1b, 0xe5, 0x86, 0x78, 0x67, 0x99, + 0x59, 0xa7, 0xb8, 0x46, 0x7e, 0x80, 0x9f, 0x61, 0xa1, 0x5f, + 0x40, 0xbe, 0xdd, 0x23, 0x3c, 0xc2, 0x02, 0xfc, 0xe3, 0x1d, + 0x00, 0xff, 0xe3, 0x1c, 0xdb, 0x24, 0x38, 0xc7, 0xab, 0x54, + 0x48, 0xb7, 0x70, 0x8f, 0x93, 0x6c, 0x4b, 0xb4, 0xa8, 0x57, + 0x90, 0x6f, 0x73, 0x8c, 0xe0, 0x1f, 0x03, 0xfc, 0x3b, 0xc4, + 0xd8, 0x27, 0x96, 0x69, 0x75, 0x8a, 0x4d, 0xb2, 0xae, 0x51, + 0x3d, 0xc2, 0xde, 0x21, 0xe6, 0x19, 0x05, 0xfa, 0xdd, 0x22, + 0x3e, 0xc1, 0x06, 0xf9, 0xe5, 0x1a, 0x76, 0x89, 0x95, 0x6a, + 0xad, 0x52, 0x4e, 0xb1, 0x31, 0xce, 0xd2, 0x2d, 0xea, 0x15, + 0x09, 0xf6, 0x9a, 0x65, 0x79, 0x86, 0x41, 0xbe, 0xa2, 0x5d, + 0x7a, 0x85, 0x99, 0x66, 0xa1, 0x5e, 0x42, 0xbd, 0xd1, 0x2e, + 0x32, 0xcd, 0x0a, 0xf5, 0xe9, 0x16, 0xa7, 0x58, 0x44, 0xbb, + 0x7c, 0x83, 0x9f, 0x60, 0x0c, 0xf3, 0xef, 0x10, 0xd7, 0x28, + 0x34, 0xcb, 0xec, 0x13, 0x0f, 0xf0, 0x37, 0xc8, 0xd4, 0x2b, + 0x47, 0xb8, 0xa4, 0x5b, 0x9c, 0x63, 0x7f, 0x80, 0x62, 0x9d, + 0x81, 0x7e, 0xb9, 0x46, 0x5a, 0xa5, 0xc9, 0x36, 0x2a, 0xd5, + 0x12, 0xed, 0xf1, 0x0e, 0x29, 0xd6, 0xca, 0x35, 0xf2, 0x0d, + 0x11, 0xee, 0x82, 0x7d, 0x61, 0x9e, 0x59, 0xa6, 0xba, 0x45, + 0xf4, 0x0b, 0x17, 0xe8, 0x2f, 0xd0, 0xcc, 0x33, 0x5f, 0xa0, + 0xbc, 0x43, 0x84, 0x7b, 0x67, 0x98, 0xbf, 0x40, 0x5c, 0xa3, + 0x64, 0x9b, 0x87, 0x78, 0x14, 0xeb, 0xf7, 0x08, 0xcf, 0x30, + 0x2c, 0xd3, 0x53, 0xac, 0xb0, 0x4f, 0x88, 0x77, 0x6b, 0x94, + 0xf8, 0x07, 0x1b, 0xe4, 0x23, 0xdc, 0xc0, 0x3f, 0x18, 0xe7, + 0xfb, 0x04, 0xc3, 0x3c, 0x20, 0xdf, 0xb3, 0x4c, 0x50, 0xaf, + 0x68, 0x97, 0x8b, 0x74, 0xc5, 0x3a, 0x26, 0xd9, 0x1e, 0xe1, + 0xfd, 0x02, 0x6e, 0x91, 0x8d, 0x72, 0xb5, 0x4a, 0x56, 0xa9, + 0x8e, 0x71, 0x6d, 0x92, 0x55, 0xaa, 0xb6, 0x49, 0x25, 0xda, + 0xc6, 0x39, 0xfe, 0x01, 0x1d, 0xe2 +}; + +unsigned char gf_inv_table_base[] = { + 0x00, 0x01, 0x8e, 0xf4, 0x47, 0xa7, 0x7a, 0xba, 0xad, 0x9d, + 0xdd, 0x98, 0x3d, 0xaa, 0x5d, 0x96, 0xd8, 0x72, 0xc0, 0x58, + 0xe0, 0x3e, 0x4c, 0x66, 0x90, 0xde, 0x55, 0x80, 0xa0, 0x83, + 0x4b, 0x2a, 0x6c, 0xed, 0x39, 0x51, 0x60, 0x56, 0x2c, 0x8a, + 0x70, 0xd0, 0x1f, 0x4a, 0x26, 0x8b, 0x33, 0x6e, 0x48, 0x89, + 0x6f, 0x2e, 0xa4, 0xc3, 0x40, 0x5e, 0x50, 0x22, 0xcf, 0xa9, + 0xab, 0x0c, 0x15, 0xe1, 0x36, 0x5f, 0xf8, 0xd5, 0x92, 0x4e, + 0xa6, 0x04, 0x30, 0x88, 0x2b, 0x1e, 0x16, 0x67, 0x45, 0x93, + 0x38, 0x23, 0x68, 0x8c, 0x81, 0x1a, 0x25, 0x61, 0x13, 0xc1, + 0xcb, 0x63, 0x97, 0x0e, 0x37, 0x41, 0x24, 0x57, 0xca, 0x5b, + 0xb9, 0xc4, 0x17, 0x4d, 0x52, 0x8d, 0xef, 0xb3, 0x20, 0xec, + 0x2f, 0x32, 0x28, 0xd1, 0x11, 0xd9, 0xe9, 0xfb, 0xda, 0x79, + 0xdb, 0x77, 0x06, 0xbb, 0x84, 0xcd, 0xfe, 0xfc, 0x1b, 0x54, + 0xa1, 0x1d, 0x7c, 0xcc, 0xe4, 0xb0, 0x49, 0x31, 0x27, 0x2d, + 0x53, 0x69, 0x02, 0xf5, 0x18, 0xdf, 0x44, 0x4f, 0x9b, 0xbc, + 0x0f, 0x5c, 0x0b, 0xdc, 0xbd, 0x94, 0xac, 0x09, 0xc7, 0xa2, + 0x1c, 0x82, 0x9f, 0xc6, 0x34, 0xc2, 0x46, 0x05, 0xce, 0x3b, + 0x0d, 0x3c, 0x9c, 0x08, 0xbe, 0xb7, 0x87, 0xe5, 0xee, 0x6b, + 0xeb, 0xf2, 0xbf, 0xaf, 0xc5, 0x64, 0x07, 0x7b, 0x95, 0x9a, + 0xae, 0xb6, 0x12, 0x59, 0xa5, 0x35, 0x65, 0xb8, 0xa3, 0x9e, + 0xd2, 0xf7, 0x62, 0x5a, 0x85, 0x7d, 0xa8, 0x3a, 0x29, 0x71, + 0xc8, 0xf6, 0xf9, 0x43, 0xd7, 0xd6, 0x10, 0x73, 0x76, 0x78, + 0x99, 0x0a, 0x19, 0x91, 0x14, 0x3f, 0xe6, 0xf0, 0x86, 0xb1, + 0xe2, 0xf1, 0xfa, 0x74, 0xf3, 0xb4, 0x6d, 0x21, 0xb2, 0x6a, + 0xe3, 0xe7, 0xb5, 0xea, 0x03, 0x8f, 0xd3, 0xc9, 0x42, 0xd4, + 0xe8, 0x75, 0x7f, 0xff, 0x7e, 0xfd +}; +#endif // GF_LARGE_TABLES + +#endif //_EC_BASE_H_ diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_code.h b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_code.h new file mode 100644 index 000000000..570944c37 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_code.h @@ -0,0 +1,933 @@ +/********************************************************************** + Copyright(c) 2011-2015 Intel Corporation All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**********************************************************************/ + + +#ifndef _ERASURE_CODE_H_ +#define _ERASURE_CODE_H_ + +/** + * @file erasure_code.h + * @brief Interface to functions supporting erasure code encode and decode. + * + * This file defines the interface to optimized functions used in erasure + * codes. Encode and decode of erasures in GF(2^8) are made by calculating the + * dot product of the symbols (bytes in GF(2^8)) across a set of buffers and a + * set of coefficients. Values for the coefficients are determined by the type + * of erasure code. Using a general dot product means that any sequence of + * coefficients may be used including erasure codes based on random + * coefficients. + * Multiple versions of dot product are supplied to calculate 1-6 output + * vectors in one pass. + * Base GF multiply and divide functions can be sped up by defining + * GF_LARGE_TABLES at the expense of memory size. + * + */ + +#include "gf_vect_mul.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Initialize tables for fast Erasure Code encode and decode. + * + * Generates the expanded tables needed for fast encode or decode for erasure + * codes on blocks of data. 32bytes is generated for each input coefficient. + * + * @param k The number of vector sources or rows in the generator matrix + * for coding. + * @param rows The number of output vectors to concurrently encode/decode. + * @param a Pointer to sets of arrays of input coefficients used to encode + * or decode data. + * @param gftbls Pointer to start of space for concatenated output tables + * generated from input coefficients. Must be of size 32*k*rows. + * @returns none + */ + +void ec_init_tables(int k, int rows, unsigned char* a, unsigned char* gftbls); + +/** + * @brief Generate or decode erasure codes on blocks of data, runs appropriate version. + * + * Given a list of source data blocks, generate one or multiple blocks of + * encoded data as specified by a matrix of GF(2^8) coefficients. When given a + * suitable set of coefficients, this function will perform the fast generation + * or decoding of Reed-Solomon type erasure codes. + * + * This function determines what instruction sets are enabled and + * selects the appropriate version at runtime. + * + * @param len Length of each block of data (vector) of source or dest data. + * @param k The number of vector sources or rows in the generator matrix + * for coding. + * @param rows The number of output vectors to concurrently encode/decode. + * @param gftbls Pointer to array of input tables generated from coding + * coefficients in ec_init_tables(). Must be of size 32*k*rows + * @param data Array of pointers to source input buffers. + * @param coding Array of pointers to coded output buffers. + * @returns none + */ + +void ec_encode_data(int len, int k, int rows, unsigned char *gftbls, unsigned char **data, + unsigned char **coding); + +/** + * @brief Generate or decode erasure codes on blocks of data. + * + * Arch specific version of ec_encode_data() with same parameters. + * @requires SSE4.1 + */ +void ec_encode_data_sse(int len, int k, int rows, unsigned char *gftbls, unsigned char **data, + unsigned char **coding); + +/** + * @brief Generate or decode erasure codes on blocks of data. + * + * Arch specific version of ec_encode_data() with same parameters. + * @requires AVX + */ +void ec_encode_data_avx(int len, int k, int rows, unsigned char *gftbls, unsigned char **data, + unsigned char **coding); + +/** + * @brief Generate or decode erasure codes on blocks of data. + * + * Arch specific version of ec_encode_data() with same parameters. + * @requires AVX2 + */ +void ec_encode_data_avx2(int len, int k, int rows, unsigned char *gftbls, unsigned char **data, + unsigned char **coding); + +/** + * @brief Generate or decode erasure codes on blocks of data, runs baseline version. + * + * Baseline version of ec_encode_data() with same parameters. + */ +void ec_encode_data_base(int len, int srcs, int dests, unsigned char *v, unsigned char **src, + unsigned char **dest); + +/** + * @brief Generate update for encode or decode of erasure codes from single source, runs appropriate version. + * + * Given one source data block, update one or multiple blocks of encoded data as + * specified by a matrix of GF(2^8) coefficients. When given a suitable set of + * coefficients, this function will perform the fast generation or decoding of + * Reed-Solomon type erasure codes from one input source at a time. + * + * This function determines what instruction sets are enabled and selects the + * appropriate version at runtime. + * + * @param len Length of each block of data (vector) of source or dest data. + * @param k The number of vector sources or rows in the generator matrix + * for coding. + * @param rows The number of output vectors to concurrently encode/decode. + * @param vec_i The vector index corresponding to the single input source. + * @param g_tbls Pointer to array of input tables generated from coding + * coefficients in ec_init_tables(). Must be of size 32*k*rows + * @param data Pointer to single input source used to update output parity. + * @param coding Array of pointers to coded output buffers. + * @returns none + */ +void ec_encode_data_update(int len, int k, int rows, int vec_i, unsigned char *g_tbls, + unsigned char *data, unsigned char **coding); + +/** + * @brief Generate update for encode or decode of erasure codes from single source. + * + * Arch specific version of ec_encode_data_update() with same parameters. + * @requires SSE4.1 + */ + +void ec_encode_data_update_sse(int len, int k, int rows, int vec_i, unsigned char *g_tbls, + unsigned char *data, unsigned char **coding); + +/** + * @brief Generate update for encode or decode of erasure codes from single source. + * + * Arch specific version of ec_encode_data_update() with same parameters. + * @requires AVX + */ + +void ec_encode_data_update_avx(int len, int k, int rows, int vec_i, unsigned char *g_tbls, + unsigned char *data, unsigned char **coding); + +/** + * @brief Generate update for encode or decode of erasure codes from single source. + * + * Arch specific version of ec_encode_data_update() with same parameters. + * @requires AVX2 + */ + +void ec_encode_data_update_avx2(int len, int k, int rows, int vec_i, unsigned char *g_tbls, + unsigned char *data, unsigned char **coding); + +/** + * @brief Generate update for encode or decode of erasure codes from single source. + * + * Baseline version of ec_encode_data_update(). + */ + +void ec_encode_data_update_base(int len, int k, int rows, int vec_i, unsigned char *v, + unsigned char *data, unsigned char **dest); + + +/** + * @brief GF(2^8) vector dot product. + * + * Does a GF(2^8) dot product across each byte of the input array and a constant + * set of coefficients to produce each byte of the output. Can be used for + * erasure coding encode and decode. Function requires pre-calculation of a + * 32*vlen byte constant array based on the input coefficients. + * @requires SSE4.1 + * + * @param len Length of each vector in bytes. Must be >= 16. + * @param vlen Number of vector sources. + * @param gftbls Pointer to 32*vlen byte array of pre-calculated constants based + * on the array of input coefficients. + * @param src Array of pointers to source inputs. + * @param dest Pointer to destination data array. + * @returns none + */ + +void gf_vect_dot_prod_sse(int len, int vlen, unsigned char *gftbls, + unsigned char **src, unsigned char *dest); + +/** + * @brief GF(2^8) vector dot product. + * + * Does a GF(2^8) dot product across each byte of the input array and a constant + * set of coefficients to produce each byte of the output. Can be used for + * erasure coding encode and decode. Function requires pre-calculation of a + * 32*vlen byte constant array based on the input coefficients. + * @requires AVX + * + * @param len Length of each vector in bytes. Must be >= 16. + * @param vlen Number of vector sources. + * @param gftbls Pointer to 32*vlen byte array of pre-calculated constants based + * on the array of input coefficients. + * @param src Array of pointers to source inputs. + * @param dest Pointer to destination data array. + * @returns none + */ + +void gf_vect_dot_prod_avx(int len, int vlen, unsigned char *gftbls, + unsigned char **src, unsigned char *dest); + +/** + * @brief GF(2^8) vector dot product. + * + * Does a GF(2^8) dot product across each byte of the input array and a constant + * set of coefficients to produce each byte of the output. Can be used for + * erasure coding encode and decode. Function requires pre-calculation of a + * 32*vlen byte constant array based on the input coefficients. + * @requires AVX2 + * + * @param len Length of each vector in bytes. Must be >= 32. + * @param vlen Number of vector sources. + * @param gftbls Pointer to 32*vlen byte array of pre-calculated constants based + * on the array of input coefficients. + * @param src Array of pointers to source inputs. + * @param dest Pointer to destination data array. + * @returns none + */ + +void gf_vect_dot_prod_avx2(int len, int vlen, unsigned char *gftbls, + unsigned char **src, unsigned char *dest); + +/** + * @brief GF(2^8) vector dot product with two outputs. + * + * Vector dot product optimized to calculate two ouputs at a time. Does two + * GF(2^8) dot products across each byte of the input array and two constant + * sets of coefficients to produce each byte of the outputs. Can be used for + * erasure coding encode and decode. Function requires pre-calculation of a + * 2*32*vlen byte constant array based on the two sets of input coefficients. + * @requires SSE4.1 + * + * @param len Length of each vector in bytes. Must be >= 16. + * @param vlen Number of vector sources. + * @param gftbls Pointer to 2*32*vlen byte array of pre-calculated constants + * based on the array of input coefficients. + * @param src Array of pointers to source inputs. + * @param dest Array of pointers to destination data buffers. + * @returns none + */ + +void gf_2vect_dot_prod_sse(int len, int vlen, unsigned char *gftbls, + unsigned char **src, unsigned char **dest); + +/** + * @brief GF(2^8) vector dot product with two outputs. + * + * Vector dot product optimized to calculate two ouputs at a time. Does two + * GF(2^8) dot products across each byte of the input array and two constant + * sets of coefficients to produce each byte of the outputs. Can be used for + * erasure coding encode and decode. Function requires pre-calculation of a + * 2*32*vlen byte constant array based on the two sets of input coefficients. + * @requires AVX + * + * @param len Length of each vector in bytes. Must be >= 16. + * @param vlen Number of vector sources. + * @param gftbls Pointer to 2*32*vlen byte array of pre-calculated constants + * based on the array of input coefficients. + * @param src Array of pointers to source inputs. + * @param dest Array of pointers to destination data buffers. + * @returns none + */ + +void gf_2vect_dot_prod_avx(int len, int vlen, unsigned char *gftbls, + unsigned char **src, unsigned char **dest); + +/** + * @brief GF(2^8) vector dot product with two outputs. + * + * Vector dot product optimized to calculate two ouputs at a time. Does two + * GF(2^8) dot products across each byte of the input array and two constant + * sets of coefficients to produce each byte of the outputs. Can be used for + * erasure coding encode and decode. Function requires pre-calculation of a + * 2*32*vlen byte constant array based on the two sets of input coefficients. + * @requires AVX2 + * + * @param len Length of each vector in bytes. Must be >= 32. + * @param vlen Number of vector sources. + * @param gftbls Pointer to 2*32*vlen byte array of pre-calculated constants + * based on the array of input coefficients. + * @param src Array of pointers to source inputs. + * @param dest Array of pointers to destination data buffers. + * @returns none + */ + +void gf_2vect_dot_prod_avx2(int len, int vlen, unsigned char *gftbls, + unsigned char **src, unsigned char **dest); + +/** + * @brief GF(2^8) vector dot product with three outputs. + * + * Vector dot product optimized to calculate three ouputs at a time. Does three + * GF(2^8) dot products across each byte of the input array and three constant + * sets of coefficients to produce each byte of the outputs. Can be used for + * erasure coding encode and decode. Function requires pre-calculation of a + * 3*32*vlen byte constant array based on the three sets of input coefficients. + * @requires SSE4.1 + * + * @param len Length of each vector in bytes. Must be >= 16. + * @param vlen Number of vector sources. + * @param gftbls Pointer to 3*32*vlen byte array of pre-calculated constants + * based on the array of input coefficients. + * @param src Array of pointers to source inputs. + * @param dest Array of pointers to destination data buffers. + * @returns none + */ + +void gf_3vect_dot_prod_sse(int len, int vlen, unsigned char *gftbls, + unsigned char **src, unsigned char **dest); + +/** + * @brief GF(2^8) vector dot product with three outputs. + * + * Vector dot product optimized to calculate three ouputs at a time. Does three + * GF(2^8) dot products across each byte of the input array and three constant + * sets of coefficients to produce each byte of the outputs. Can be used for + * erasure coding encode and decode. Function requires pre-calculation of a + * 3*32*vlen byte constant array based on the three sets of input coefficients. + * @requires AVX + * + * @param len Length of each vector in bytes. Must be >= 16. + * @param vlen Number of vector sources. + * @param gftbls Pointer to 3*32*vlen byte array of pre-calculated constants + * based on the array of input coefficients. + * @param src Array of pointers to source inputs. + * @param dest Array of pointers to destination data buffers. + * @returns none + */ + +void gf_3vect_dot_prod_avx(int len, int vlen, unsigned char *gftbls, + unsigned char **src, unsigned char **dest); + +/** + * @brief GF(2^8) vector dot product with three outputs. + * + * Vector dot product optimized to calculate three ouputs at a time. Does three + * GF(2^8) dot products across each byte of the input array and three constant + * sets of coefficients to produce each byte of the outputs. Can be used for + * erasure coding encode and decode. Function requires pre-calculation of a + * 3*32*vlen byte constant array based on the three sets of input coefficients. + * @requires AVX2 + * + * @param len Length of each vector in bytes. Must be >= 32. + * @param vlen Number of vector sources. + * @param gftbls Pointer to 3*32*vlen byte array of pre-calculated constants + * based on the array of input coefficients. + * @param src Array of pointers to source inputs. + * @param dest Array of pointers to destination data buffers. + * @returns none + */ + +void gf_3vect_dot_prod_avx2(int len, int vlen, unsigned char *gftbls, + unsigned char **src, unsigned char **dest); + +/** + * @brief GF(2^8) vector dot product with four outputs. + * + * Vector dot product optimized to calculate four ouputs at a time. Does four + * GF(2^8) dot products across each byte of the input array and four constant + * sets of coefficients to produce each byte of the outputs. Can be used for + * erasure coding encode and decode. Function requires pre-calculation of a + * 4*32*vlen byte constant array based on the four sets of input coefficients. + * @requires SSE4.1 + * + * @param len Length of each vector in bytes. Must be >= 16. + * @param vlen Number of vector sources. + * @param gftbls Pointer to 4*32*vlen byte array of pre-calculated constants + * based on the array of input coefficients. + * @param src Array of pointers to source inputs. + * @param dest Array of pointers to destination data buffers. + * @returns none + */ + +void gf_4vect_dot_prod_sse(int len, int vlen, unsigned char *gftbls, + unsigned char **src, unsigned char **dest); + +/** + * @brief GF(2^8) vector dot product with four outputs. + * + * Vector dot product optimized to calculate four ouputs at a time. Does four + * GF(2^8) dot products across each byte of the input array and four constant + * sets of coefficients to produce each byte of the outputs. Can be used for + * erasure coding encode and decode. Function requires pre-calculation of a + * 4*32*vlen byte constant array based on the four sets of input coefficients. + * @requires AVX + * + * @param len Length of each vector in bytes. Must be >= 16. + * @param vlen Number of vector sources. + * @param gftbls Pointer to 4*32*vlen byte array of pre-calculated constants + * based on the array of input coefficients. + * @param src Array of pointers to source inputs. + * @param dest Array of pointers to destination data buffers. + * @returns none + */ + +void gf_4vect_dot_prod_avx(int len, int vlen, unsigned char *gftbls, + unsigned char **src, unsigned char **dest); + +/** + * @brief GF(2^8) vector dot product with four outputs. + * + * Vector dot product optimized to calculate four ouputs at a time. Does four + * GF(2^8) dot products across each byte of the input array and four constant + * sets of coefficients to produce each byte of the outputs. Can be used for + * erasure coding encode and decode. Function requires pre-calculation of a + * 4*32*vlen byte constant array based on the four sets of input coefficients. + * @requires AVX2 + * + * @param len Length of each vector in bytes. Must be >= 32. + * @param vlen Number of vector sources. + * @param gftbls Pointer to 4*32*vlen byte array of pre-calculated constants + * based on the array of input coefficients. + * @param src Array of pointers to source inputs. + * @param dest Array of pointers to destination data buffers. + * @returns none + */ + +void gf_4vect_dot_prod_avx2(int len, int vlen, unsigned char *gftbls, + unsigned char **src, unsigned char **dest); + +/** + * @brief GF(2^8) vector dot product with five outputs. + * + * Vector dot product optimized to calculate five ouputs at a time. Does five + * GF(2^8) dot products across each byte of the input array and five constant + * sets of coefficients to produce each byte of the outputs. Can be used for + * erasure coding encode and decode. Function requires pre-calculation of a + * 5*32*vlen byte constant array based on the five sets of input coefficients. + * @requires SSE4.1 + * + * @param len Length of each vector in bytes. Must >= 16. + * @param vlen Number of vector sources. + * @param gftbls Pointer to 5*32*vlen byte array of pre-calculated constants + * based on the array of input coefficients. + * @param src Array of pointers to source inputs. + * @param dest Array of pointers to destination data buffers. + * @returns none + */ + +void gf_5vect_dot_prod_sse(int len, int vlen, unsigned char *gftbls, + unsigned char **src, unsigned char **dest); + +/** + * @brief GF(2^8) vector dot product with five outputs. + * + * Vector dot product optimized to calculate five ouputs at a time. Does five + * GF(2^8) dot products across each byte of the input array and five constant + * sets of coefficients to produce each byte of the outputs. Can be used for + * erasure coding encode and decode. Function requires pre-calculation of a + * 5*32*vlen byte constant array based on the five sets of input coefficients. + * @requires AVX + * + * @param len Length of each vector in bytes. Must >= 16. + * @param vlen Number of vector sources. + * @param gftbls Pointer to 5*32*vlen byte array of pre-calculated constants + * based on the array of input coefficients. + * @param src Array of pointers to source inputs. + * @param dest Array of pointers to destination data buffers. + * @returns none + */ + +void gf_5vect_dot_prod_avx(int len, int vlen, unsigned char *gftbls, + unsigned char **src, unsigned char **dest); + +/** + * @brief GF(2^8) vector dot product with five outputs. + * + * Vector dot product optimized to calculate five ouputs at a time. Does five + * GF(2^8) dot products across each byte of the input array and five constant + * sets of coefficients to produce each byte of the outputs. Can be used for + * erasure coding encode and decode. Function requires pre-calculation of a + * 5*32*vlen byte constant array based on the five sets of input coefficients. + * @requires AVX2 + * + * @param len Length of each vector in bytes. Must >= 32. + * @param vlen Number of vector sources. + * @param gftbls Pointer to 5*32*vlen byte array of pre-calculated constants + * based on the array of input coefficients. + * @param src Array of pointers to source inputs. + * @param dest Array of pointers to destination data buffers. + * @returns none + */ + +void gf_5vect_dot_prod_avx2(int len, int vlen, unsigned char *gftbls, + unsigned char **src, unsigned char **dest); + +/** + * @brief GF(2^8) vector dot product with six outputs. + * + * Vector dot product optimized to calculate six ouputs at a time. Does six + * GF(2^8) dot products across each byte of the input array and six constant + * sets of coefficients to produce each byte of the outputs. Can be used for + * erasure coding encode and decode. Function requires pre-calculation of a + * 6*32*vlen byte constant array based on the six sets of input coefficients. + * @requires SSE4.1 + * + * @param len Length of each vector in bytes. Must be >= 16. + * @param vlen Number of vector sources. + * @param gftbls Pointer to 6*32*vlen byte array of pre-calculated constants + * based on the array of input coefficients. + * @param src Array of pointers to source inputs. + * @param dest Array of pointers to destination data buffers. + * @returns none + */ + +void gf_6vect_dot_prod_sse(int len, int vlen, unsigned char *gftbls, + unsigned char **src, unsigned char **dest); + +/** + * @brief GF(2^8) vector dot product with six outputs. + * + * Vector dot product optimized to calculate six ouputs at a time. Does six + * GF(2^8) dot products across each byte of the input array and six constant + * sets of coefficients to produce each byte of the outputs. Can be used for + * erasure coding encode and decode. Function requires pre-calculation of a + * 6*32*vlen byte constant array based on the six sets of input coefficients. + * @requires AVX + * + * @param len Length of each vector in bytes. Must be >= 16. + * @param vlen Number of vector sources. + * @param gftbls Pointer to 6*32*vlen byte array of pre-calculated constants + * based on the array of input coefficients. + * @param src Array of pointers to source inputs. + * @param dest Array of pointers to destination data buffers. + * @returns none + */ + +void gf_6vect_dot_prod_avx(int len, int vlen, unsigned char *gftbls, + unsigned char **src, unsigned char **dest); + +/** + * @brief GF(2^8) vector dot product with six outputs. + * + * Vector dot product optimized to calculate six ouputs at a time. Does six + * GF(2^8) dot products across each byte of the input array and six constant + * sets of coefficients to produce each byte of the outputs. Can be used for + * erasure coding encode and decode. Function requires pre-calculation of a + * 6*32*vlen byte constant array based on the six sets of input coefficients. + * @requires AVX2 + * + * @param len Length of each vector in bytes. Must be >= 32. + * @param vlen Number of vector sources. + * @param gftbls Pointer to 6*32*vlen byte array of pre-calculated constants + * based on the array of input coefficients. + * @param src Array of pointers to source inputs. + * @param dest Array of pointers to destination data buffers. + * @returns none + */ + +void gf_6vect_dot_prod_avx2(int len, int vlen, unsigned char *gftbls, + unsigned char **src, unsigned char **dest); + +/** + * @brief GF(2^8) vector dot product, runs baseline version. + * + * Does a GF(2^8) dot product across each byte of the input array and a constant + * set of coefficients to produce each byte of the output. Can be used for + * erasure coding encode and decode. Function requires pre-calculation of a + * 32*vlen byte constant array based on the input coefficients. + * + * @param len Length of each vector in bytes. Must be >= 16. + * @param vlen Number of vector sources. + * @param gftbls Pointer to 32*vlen byte array of pre-calculated constants based + * on the array of input coefficients. Only elements 32*CONST*j + 1 + * of this array are used, where j = (0, 1, 2...) and CONST is the + * number of elements in the array of input coefficients. The + * elements used correspond to the original input coefficients. + * @param src Array of pointers to source inputs. + * @param dest Pointer to destination data array. + * @returns none + */ + +void gf_vect_dot_prod_base(int len, int vlen, unsigned char *gftbls, + unsigned char **src, unsigned char *dest); + +/** + * @brief GF(2^8) vector dot product, runs appropriate version. + * + * Does a GF(2^8) dot product across each byte of the input array and a constant + * set of coefficients to produce each byte of the output. Can be used for + * erasure coding encode and decode. Function requires pre-calculation of a + * 32*vlen byte constant array based on the input coefficients. + * + * This function determines what instruction sets are enabled and + * selects the appropriate version at runtime. + * + * @param len Length of each vector in bytes. Must be >= 32. + * @param vlen Number of vector sources. + * @param gftbls Pointer to 32*vlen byte array of pre-calculated constants based + * on the array of input coefficients. + * @param src Array of pointers to source inputs. + * @param dest Pointer to destination data array. + * @returns none + */ + +void gf_vect_dot_prod(int len, int vlen, unsigned char *gftbls, + unsigned char **src, unsigned char *dest); + + +/** + * @brief GF(2^8) vector multiply accumulate, runs appropriate version. + * + * Does a GF(2^8) multiply across each byte of input source with expanded + * constant and add to destination array. Can be used for erasure coding encode + * and decode update when only one source is available at a time. Function + * requires pre-calculation of a 32*vec byte constant array based on the input + * coefficients. + * + * This function determines what instruction sets are enabled and selects the + * appropriate version at runtime. + * + * @param len Length of each vector in bytes. Must be >= 32. + * @param vec The number of vector sources or rows in the generator matrix + * for coding. + * @param vec_i The vector index corresponding to the single input source. + * @param gftbls Pointer to array of input tables generated from coding + * coefficients in ec_init_tables(). Must be of size 32*vec. + * @param src Array of pointers to source inputs. + * @param dest Pointer to destination data array. + * @returns none + */ + +void gf_vect_mad(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, + unsigned char *dest); + +/** + * @brief GF(2^8) vector multiply accumulate, arch specific version. + * + * Arch specific version of gf_vect_mad() with same parameters. + * @requires SSE4.1 + */ + +void gf_vect_mad_sse(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, + unsigned char *dest); +/** + * @brief GF(2^8) vector multiply accumulate, arch specific version. + * + * Arch specific version of gf_vect_mad() with same parameters. + * @requires AVX + */ + +void gf_vect_mad_avx(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, + unsigned char *dest); + +/** + * @brief GF(2^8) vector multiply accumulate, arch specific version. + * + * Arch specific version of gf_vect_mad() with same parameters. + * @requires AVX2 + */ + +void gf_vect_mad_avx2(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, + unsigned char *dest); + +/** + * @brief GF(2^8) vector multiply accumulate, baseline version. + * + * Baseline version of gf_vect_mad() with same parameters. + */ + +void gf_vect_mad_base(int len, int vec, int vec_i, unsigned char *v, unsigned char *src, + unsigned char *dest); + +/** + * @brief GF(2^8) vector multiply with 2 accumulate. SSE version. + * + * Does a GF(2^8) multiply across each byte of input source with expanded + * constants and add to destination arrays. Can be used for erasure coding + * encode and decode update when only one source is available at a + * time. Function requires pre-calculation of a 32*vec byte constant array based + * on the input coefficients. + * @requires SSE4.1 + * + * @param len Length of each vector in bytes. Must be >= 32. + * @param vec The number of vector sources or rows in the generator matrix + * for coding. + * @param vec_i The vector index corresponding to the single input source. + * @param gftbls Pointer to array of input tables generated from coding + * coefficients in ec_init_tables(). Must be of size 32*vec. + * @param src Pointer to source input array. + * @param dest Array of pointers to destination input/outputs. + * @returns none + */ + +void gf_2vect_mad_sse(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, + unsigned char **dest); + +/** + * @brief GF(2^8) vector multiply with 2 accumulate. AVX version of gf_2vect_mad_sse(). + * @requires AVX + */ +void gf_2vect_mad_avx(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, + unsigned char **dest); +/** + * @brief GF(2^8) vector multiply with 2 accumulate. AVX2 version of gf_2vect_mad_sse(). + * @requires AVX2 + */ +void gf_2vect_mad_avx2(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, + unsigned char **dest); + +/** + * @brief GF(2^8) vector multiply with 3 accumulate. SSE version. + * + * Does a GF(2^8) multiply across each byte of input source with expanded + * constants and add to destination arrays. Can be used for erasure coding + * encode and decode update when only one source is available at a + * time. Function requires pre-calculation of a 32*vec byte constant array based + * on the input coefficients. + * @requires SSE4.1 + * + * @param len Length of each vector in bytes. Must be >= 32. + * @param vec The number of vector sources or rows in the generator matrix + * for coding. + * @param vec_i The vector index corresponding to the single input source. + * @param gftbls Pointer to array of input tables generated from coding + * coefficients in ec_init_tables(). Must be of size 32*vec. + * @param src Pointer to source input array. + * @param dest Array of pointers to destination input/outputs. + * @returns none + */ + +void gf_3vect_mad_sse(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, + unsigned char **dest); + +/** + * @brief GF(2^8) vector multiply with 3 accumulate. AVX version of gf_3vect_mad_sse(). + * @requires AVX + */ +void gf_3vect_mad_avx(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, + unsigned char **dest); + +/** + * @brief GF(2^8) vector multiply with 3 accumulate. AVX2 version of gf_3vect_mad_sse(). + * @requires AVX2 + */ +void gf_3vect_mad_avx2(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, + unsigned char **dest); + +/** + * @brief GF(2^8) vector multiply with 4 accumulate. SSE version. + * + * Does a GF(2^8) multiply across each byte of input source with expanded + * constants and add to destination arrays. Can be used for erasure coding + * encode and decode update when only one source is available at a + * time. Function requires pre-calculation of a 32*vec byte constant array based + * on the input coefficients. + * @requires SSE4.1 + * + * @param len Length of each vector in bytes. Must be >= 32. + * @param vec The number of vector sources or rows in the generator matrix + * for coding. + * @param vec_i The vector index corresponding to the single input source. + * @param gftbls Pointer to array of input tables generated from coding + * coefficients in ec_init_tables(). Must be of size 32*vec. + * @param src Pointer to source input array. + * @param dest Array of pointers to destination input/outputs. + * @returns none + */ + +void gf_4vect_mad_sse(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, + unsigned char **dest); + +/** + * @brief GF(2^8) vector multiply with 4 accumulate. AVX version of gf_4vect_mad_sse(). + * @requires AVX + */ +void gf_4vect_mad_avx(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, + unsigned char **dest); +/** + * @brief GF(2^8) vector multiply with 4 accumulate. AVX2 version of gf_4vect_mad_sse(). + * @requires AVX2 + */ +void gf_4vect_mad_avx2(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, + unsigned char **dest); + +/** + * @brief GF(2^8) vector multiply with 5 accumulate. SSE version. + * @requires SSE4.1 + */ +void gf_5vect_mad_sse(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, + unsigned char **dest); + +/** + * @brief GF(2^8) vector multiply with 5 accumulate. AVX version. + * @requires AVX + */ +void gf_5vect_mad_avx(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, + unsigned char **dest); +/** + * @brief GF(2^8) vector multiply with 5 accumulate. AVX2 version. + * @requires AVX2 + */ +void gf_5vect_mad_avx2(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, + unsigned char **dest); + +/** + * @brief GF(2^8) vector multiply with 6 accumulate. SSE version. + * @requires SSE4.1 + */ +void gf_6vect_mad_sse(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, + unsigned char **dest); +/** + * @brief GF(2^8) vector multiply with 6 accumulate. AVX version. + * @requires AVX + */ +void gf_6vect_mad_avx(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, + unsigned char **dest); + +/** + * @brief GF(2^8) vector multiply with 6 accumulate. AVX2 version. + * @requires AVX2 + */ +void gf_6vect_mad_avx2(int len, int vec, int vec_i, unsigned char *gftbls, unsigned char *src, + unsigned char **dest); + + +/********************************************************************** + * The remaining are lib support functions used in GF(2^8) operations. + */ + +/** + * @brief Single element GF(2^8) multiply. + * + * @param a Multiplicand a + * @param b Multiplicand b + * @returns Product of a and b in GF(2^8) + */ + +unsigned char gf_mul(unsigned char a, unsigned char b); + +/** + * @brief Single element GF(2^8) inverse. + * + * @param a Input element + * @returns Field element b such that a x b = {1} + */ + +unsigned char gf_inv(unsigned char a); + +/** + * @brief Generate a matrix of coefficients to be used for encoding. + * + * Vandermonde matrix example of encoding coefficients where high portion of + * matrix is identity matrix I and lower portion is constructed as 2^{i*(j-k+1)} + * i:{0,k-1} j:{k,m-1}. Commonly used method for choosing coefficients in + * erasure encoding but does not guarantee invertable for every sub matrix. For + * large k it is possible to find cases where the decode matrix chosen from + * sources and parity not in erasure are not invertable. Users may want to + * adjust for k > 5. + * + * @param a [mxk] array to hold coefficients + * @param m number of rows in matrix corresponding to srcs + parity. + * @param k number of columns in matrix corresponding to srcs. + * @returns none + */ + +void gf_gen_rs_matrix(unsigned char *a, int m, int k); + +/** + * @brief Generate a Cauchy matrix of coefficients to be used for encoding. + * + * Cauchy matrix example of encoding coefficients where high portion of matrix + * is identity matrix I and lower portion is constructed as 1/(i + j) | i != j, + * i:{0,k-1} j:{k,m-1}. Any sub-matrix of a Cauchy matrix should be invertable. + * + * @param a [mxk] array to hold coefficients + * @param m number of rows in matrix corresponding to srcs + parity. + * @param k number of columns in matrix corresponding to srcs. + * @returns none + */ + +void gf_gen_cauchy1_matrix(unsigned char *a, int m, int k); + +/** + * @brief Invert a matrix in GF(2^8) + * + * @param in input matrix + * @param out output matrix such that [in] x [out] = [I] - identity matrix + * @param n size of matrix [nxn] + * @returns 0 successful, other fail on singular input matrix + */ + +int gf_invert_matrix(unsigned char *in, unsigned char *out, const int n); + + +/*************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif //_ERASURE_CODE_H_ diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_highlevel_func.c b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_highlevel_func.c new file mode 100644 index 000000000..9b9c8dc0f --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_highlevel_func.c @@ -0,0 +1,267 @@ +/********************************************************************** + Copyright(c) 2011-2015 Intel Corporation All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**********************************************************************/ +#include +#include "ec_code.h" +#include "ec_types.h" + +void ec_init_tables(int k, int rows, unsigned char *a, unsigned char *g_tbls) +{ + int i, j; + + for (i = 0; i < rows; i++) { + for (j = 0; j < k; j++) { + gf_vect_mul_init(*a++, g_tbls); + g_tbls += 32; + } + } +} + +void ec_encode_data_sse(int len, int k, int rows, unsigned char *g_tbls, unsigned char **data, + unsigned char **coding) +{ + + if (len < 16) { + ec_encode_data_base(len, k, rows, g_tbls, data, coding); + return; + } + + while (rows >= 4) { + gf_4vect_dot_prod_sse(len, k, g_tbls, data, coding); + g_tbls += 4 * k * 32; + coding += 4; + rows -= 4; + } + switch (rows) { + case 3: + gf_3vect_dot_prod_sse(len, k, g_tbls, data, coding); + break; + case 2: + gf_2vect_dot_prod_sse(len, k, g_tbls, data, coding); + break; + case 1: + gf_vect_dot_prod_sse(len, k, g_tbls, data, *coding); + break; + case 0: + break; + } + +} + +void ec_encode_data_avx(int len, int k, int rows, unsigned char *g_tbls, unsigned char **data, + unsigned char **coding) +{ + if (len < 16) { + ec_encode_data_base(len, k, rows, g_tbls, data, coding); + return; + } + + while (rows >= 4) { + gf_4vect_dot_prod_avx(len, k, g_tbls, data, coding); + g_tbls += 4 * k * 32; + coding += 4; + rows -= 4; + } + switch (rows) { + case 3: + gf_3vect_dot_prod_avx(len, k, g_tbls, data, coding); + break; + case 2: + gf_2vect_dot_prod_avx(len, k, g_tbls, data, coding); + break; + case 1: + gf_vect_dot_prod_avx(len, k, g_tbls, data, *coding); + break; + case 0: + break; + } + +} + +void ec_encode_data_avx2(int len, int k, int rows, unsigned char *g_tbls, unsigned char **data, + unsigned char **coding) +{ + + if (len < 32) { + ec_encode_data_base(len, k, rows, g_tbls, data, coding); + return; + } + + while (rows >= 4) { + gf_4vect_dot_prod_avx2(len, k, g_tbls, data, coding); + g_tbls += 4 * k * 32; + coding += 4; + rows -= 4; + } + switch (rows) { + case 3: + gf_3vect_dot_prod_avx2(len, k, g_tbls, data, coding); + break; + case 2: + gf_2vect_dot_prod_avx2(len, k, g_tbls, data, coding); + break; + case 1: + gf_vect_dot_prod_avx2(len, k, g_tbls, data, *coding); + break; + case 0: + break; + } + +} + +#if __WORDSIZE == 64 || _WIN64 || __x86_64__ + +void ec_encode_data_update_sse(int len, int k, int rows, int vec_i, unsigned char *g_tbls, + unsigned char *data, unsigned char **coding) +{ + if (len < 16) { + ec_encode_data_update_base(len, k, rows, vec_i, g_tbls, data, coding); + return; + } + + while (rows > 6) { + gf_6vect_mad_sse(len, k, vec_i, g_tbls, data, coding); + g_tbls += 6 * k * 32; + coding += 6; + rows -= 6; + } + switch (rows) { + case 6: + gf_6vect_mad_sse(len, k, vec_i, g_tbls, data, coding); + break; + case 5: + gf_5vect_mad_sse(len, k, vec_i, g_tbls, data, coding); + break; + case 4: + gf_4vect_mad_sse(len, k, vec_i, g_tbls, data, coding); + break; + case 3: + gf_3vect_mad_sse(len, k, vec_i, g_tbls, data, coding); + break; + case 2: + gf_2vect_mad_sse(len, k, vec_i, g_tbls, data, coding); + break; + case 1: + gf_vect_mad_sse(len, k, vec_i, g_tbls, data, *coding); + break; + case 0: + break; + } + +} + +void ec_encode_data_update_avx(int len, int k, int rows, int vec_i, unsigned char *g_tbls, + unsigned char *data, unsigned char **coding) +{ + if (len < 16) { + ec_encode_data_update_base(len, k, rows, vec_i, g_tbls, data, coding); + return; + } + while (rows > 6) { + gf_6vect_mad_avx(len, k, vec_i, g_tbls, data, coding); + g_tbls += 6 * k * 32; + coding += 6; + rows -= 6; + } + switch (rows) { + case 6: + gf_6vect_mad_avx(len, k, vec_i, g_tbls, data, coding); + break; + case 5: + gf_5vect_mad_avx(len, k, vec_i, g_tbls, data, coding); + break; + case 4: + gf_4vect_mad_avx(len, k, vec_i, g_tbls, data, coding); + break; + case 3: + gf_3vect_mad_avx(len, k, vec_i, g_tbls, data, coding); + break; + case 2: + gf_2vect_mad_avx(len, k, vec_i, g_tbls, data, coding); + break; + case 1: + gf_vect_mad_avx(len, k, vec_i, g_tbls, data, *coding); + break; + case 0: + break; + } + +} + +void ec_encode_data_update_avx2(int len, int k, int rows, int vec_i, unsigned char *g_tbls, + unsigned char *data, unsigned char **coding) +{ + if (len < 32) { + ec_encode_data_update_base(len, k, rows, vec_i, g_tbls, data, coding); + return; + } + while (rows > 6) { + gf_6vect_mad_avx2(len, k, vec_i, g_tbls, data, coding); + g_tbls += 6 * k * 32; + coding += 6; + rows -= 6; + } + switch (rows) { + case 6: + gf_6vect_mad_avx2(len, k, vec_i, g_tbls, data, coding); + break; + case 5: + gf_5vect_mad_avx2(len, k, vec_i, g_tbls, data, coding); + break; + case 4: + gf_4vect_mad_avx2(len, k, vec_i, g_tbls, data, coding); + break; + case 3: + gf_3vect_mad_avx2(len, k, vec_i, g_tbls, data, coding); + break; + case 2: + gf_2vect_mad_avx2(len, k, vec_i, g_tbls, data, coding); + break; + case 1: + gf_vect_mad_avx2(len, k, vec_i, g_tbls, data, *coding); + break; + case 0: + break; + } + +} + +#endif //__WORDSIZE == 64 || _WIN64 || __x86_64__ + +struct slver { + UINT16 snum; + UINT8 ver; + UINT8 core; +}; + +// Version info +struct slver ec_init_tables_slver_00010068; +struct slver ec_init_tables_slver = { 0x0068, 0x01, 0x00 }; + +struct slver ec_encode_data_sse_slver_00020069; +struct slver ec_encode_data_sse_slver = { 0x0069, 0x02, 0x00 }; diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_isal-l.h b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_isal-l.h new file mode 100644 index 000000000..77be0812a --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_isal-l.h @@ -0,0 +1,41 @@ +/********************************************************************** + Copyright(c) 2011-2015 Intel Corporation All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**********************************************************************/ + +#ifndef _ISAL_H_ +#define _ISAL_H_ + +#define ISAL_MAJOR_VERSION 2 +#define ISAL_MINOR_VERSION 13 +#define ISAL_PATCH_VERSION 0 +#define ISAL_MAKE_VERSION(maj, min, patch) ((maj) * 0x10000 + (min) * 0x100 + (patch)) +#define ISAL_VERSION ISAL_MAKE_VERSION(ISAL_MAJOR_VERSION, ISAL_MINOR_VERSION, ISAL_PATCH_VERSION) + +#include "ec_code.h" +#include "gf_vect_mul.h" +#endif //_ISAL_H_ diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_minio_common.h b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_minio_common.h new file mode 100644 index 000000000..75f4cbc16 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_minio_common.h @@ -0,0 +1,39 @@ +/* + * Mini Object Storage, (C) 2014 Minio, 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. + */ + +#ifndef __COMMON_H__ +#define __COMMON_H__ + +#include + +int32_t minio_init_encoder (int technique, int k, int m, + unsigned char **encode_matrix, + unsigned char **encode_tbls); + +int32_t minio_init_decoder (int32_t *error_index, + int k, int n, int errs, + unsigned char *encoding_matrix, + unsigned char **decode_matrix, + unsigned char **decode_tbls, + uint32_t **decode_index); + +int32_t minio_get_source_target (int errs, int k, int m, + int32_t *error_index, + uint32_t *decode_index, + unsigned char **buffs, + unsigned char ***source, + unsigned char ***target); +#endif /* __COMMON_H__ */ diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_minio_decode.c b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_minio_decode.c new file mode 100644 index 000000000..a40967024 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_minio_decode.c @@ -0,0 +1,134 @@ +/* + * Minimalist Object Storage, (C) 2014 Minio, 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. + */ + +#include +#include +#include + +#include "ec_isal-l.h" +#include "ec_minio_common.h" + +static +int32_t _minio_src_index_in_error (int r, int32_t *error_index) +{ + int i; + for (i = 0; error_index[i] != -1; i++) { + if (error_index[i] == r) { + // true + return 1; + } + } + // false + return 0; +} + +// Separate out source data and target buffers +int32_t minio_get_source_target (int errs, int k, int m, + int32_t *error_index, + uint32_t *decode_index, + unsigned char **buffs, + unsigned char ***source, + unsigned char ***target) +{ + int i; + unsigned char *tmp_source[k]; + unsigned char *tmp_target[m]; + + if (k < 0 || m < 0) { + return -1; + } + + memset (tmp_source, 0, k); + memset (tmp_target, 0, m); + + for (i = 0; i < k; i++) { + tmp_source[i] = (unsigned char *) buffs[decode_index[i]]; + } + + for (i = 0; i < m; i++) { + if (i < errs) + tmp_target[i] = (unsigned char *) buffs[error_index[i]]; + } + + *source = tmp_source; + *target = tmp_target; + + return 0; +} + +/* + Generate decode matrix during the decoding phase +*/ + +int minio_init_decoder (int32_t *error_index, + int k, int n, int errs, + unsigned char *encode_matrix, + unsigned char **decode_matrix, + unsigned char **decode_tbls, + uint32_t **decode_index) +{ + int i, j, r, s, l, z; + unsigned char input_matrix[k * n]; + unsigned char inverse_matrix[k * n]; + unsigned char tmp_decode_matrix[k * n]; + unsigned char tmp_decode_tbls[k * n * 32]; + uint32_t tmp_decode_index[k]; + + for (i = 0, r = 0; i < k; i++, r++) { + while (_minio_src_index_in_error(r, error_index)) + r++; + for (j = 0; j < k; j++) { + input_matrix[k * i + j] = encode_matrix[k * r + j]; + } + tmp_decode_index[i] = r; + } + + // Not all vandermonde matrix can be inverted + if (gf_invert_matrix(input_matrix, inverse_matrix, k) < 0) { + return -1; + } + + for (l = 0; l < errs; l++) { + if (error_index[l] < k) { + // decoding matrix elements for data chunks + for (j = 0; j < k; j++) { + tmp_decode_matrix[k * l + j] = + inverse_matrix[k * + error_index[l] + j]; + } + } else { + int s = 0; + // decoding matrix element for coding chunks + for (i = 0; i < k; i++) { + s = 0; + for (j = 0; j < k; j++) { + s ^= gf_mul(inverse_matrix[j * k + i], + encode_matrix[k * + error_index[l] + j]); + } + tmp_decode_matrix[k * l + i] = s; + } + } + } + + ec_init_tables (k, errs, tmp_decode_matrix, tmp_decode_tbls); + + *decode_matrix = tmp_decode_matrix; + *decode_tbls = tmp_decode_tbls; + *decode_index = tmp_decode_index; + + return 0; +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_minio_encode.c b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_minio_encode.c new file mode 100644 index 000000000..8f90ef10a --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_minio_encode.c @@ -0,0 +1,59 @@ +/* + * Minimalist Object Storage, (C) 2014 Minio, 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. + */ + +#include +#include + +#include "ec_isal-l.h" +#include "ec_minio_common.h" + +/* + Generate encode matrix during the encoding phase +*/ + +int32_t minio_init_encoder (int technique, int k, int m, + unsigned char **encode_matrix, + unsigned char **encode_tbls) +{ + size_t encode_matrix_size; + size_t encode_tbls_size; + unsigned char *tmp_matrix; + unsigned char *tmp_tbls; + + tmp_matrix = (unsigned char *) malloc (k * (k + m)); + tmp_tbls = (unsigned char *) malloc (k * (k + m) * 32); + + if (technique == 0) { + /* + Commonly used method for choosing coefficients in erasure + encoding but does not guarantee invertable for every sub + matrix. For large k it is possible to find cases where the + decode matrix chosen from sources and parity not in erasure + are not invertable. Users may want to adjust for k > 5. + -- Intel + */ + gf_gen_rs_matrix (tmp_matrix, k + m, k); + } else if (technique == 1) { + gf_gen_cauchy1_matrix (tmp_matrix, k + m, k); + } + + ec_init_tables(k, m, &tmp_matrix[k * k], tmp_tbls); + + *encode_matrix = tmp_matrix; + *encode_tbls = tmp_tbls; + + return 0; +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_multibinary.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_multibinary.asm new file mode 100644 index 000000000..910fdca8a --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_multibinary.asm @@ -0,0 +1,462 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +%ifidn __OUTPUT_FORMAT__, elf64 + %define WRT_OPT wrt ..plt +%else + %define WRT_OPT +%endif + +%ifidn __OUTPUT_FORMAT__, macho64 + %define EC_ENCODE_DATA_SSE _ec_encode_data_sse + %define EC_ENCODE_DATA_AVX _ec_encode_data_avx + %define EC_ENCODE_DATA_AVX2 _ec_encode_data_avx2 + %define EC_ENCODE_DATA_BASE _ec_encode_data_base + %define EC_ENCODE_DATA _ec_encode_data + + %define EC_ENCODE_DATA_UPDATE_BASE _ec_encode_data_update_base + %define EC_ENCODE_DATA_UPDATE_SSE _ec_encode_data_update_sse + %define EC_ENCODE_DATA_UPDATE_AVX _ec_encode_data_update_avx + %define EC_ENCODE_DATA_UPDATE_AVX2 _ec_encode_data_update_avx2 + + %define GF_VECT_MAD_BASE _gf_vect_mad_base + %define GF_VECT_MAD_SSE _gf_vect_mad_sse + %define GF_VECT_MAD_AVX _gf_vect_mad_avx + %define GF_VECT_MAD_AVX2 _gf_vect_mad_avx2 + + %define GF_VECT_MUL_SSE _gf_vect_mul_sse + %define GF_VECT_MUL_AVX _gf_vect_mul_avx + %define GF_VECT_MUL_BASE _gf_vect_mul_base + %define GF_VECT_MUL _gf_vect_mul + + %define GF_VECT_DOT_PROD_SSE _gf_vect_dot_prod_sse + %define GF_VECT_DOT_PROD_AVX _gf_vect_dot_prod_avx + %define GF_VECT_DOT_PROD_AVX2 _gf_vect_dot_prod_avx2 + %define GF_VECT_DOT_PROD_BASE _gf_vect_dot_prod_base + %define GF_VECT_DOT_PROD _gf_vect_dot_prod + +%else + %define EC_ENCODE_DATA_SSE ec_encode_data_sse + %define EC_ENCODE_DATA_AVX ec_encode_data_avx + %define EC_ENCODE_DATA_AVX2 ec_encode_data_avx2 + %define EC_ENCODE_DATA_BASE ec_encode_data_base + %define EC_ENCODE_DATA ec_encode_data + + %define EC_ENCODE_DATA_UPDATE_BASE ec_encode_data_update_base + %define EC_ENCODE_DATA_UPDATE_SSE ec_encode_data_update_sse + %define EC_ENCODE_DATA_UPDATE_AVX ec_encode_data_update_avx + %define EC_ENCODE_DATA_UPDATE_AVX2 ec_encode_data_update_avx2 + + %define GF_VECT_MAD_BASE gf_vect_mad_base + %define GF_VECT_MAD_SSE gf_vect_mad_sse + %define GF_VECT_MAD_AVX gf_vect_mad_avx + %define GF_VECT_MAD_AVX2 gf_vect_mad_avx2 + + %define GF_VECT_MUL_SSE gf_vect_mul_sse + %define GF_VECT_MUL_AVX gf_vect_mul_avx + %define GF_VECT_MUL_BASE gf_vect_mul_base + %define GF_VECT_MUL gf_vect_mul + + %define GF_VECT_DOT_PROD_SSE gf_vect_dot_prod_sse + %define GF_VECT_DOT_PROD_AVX gf_vect_dot_prod_avx + %define GF_VECT_DOT_PROD_AVX2 gf_vect_dot_prod_avx2 + %define GF_VECT_DOT_PROD_BASE gf_vect_dot_prod_base + %define GF_VECT_DOT_PROD gf_vect_dot_prod + +%endif + +%include "ec_reg_sizes.asm" + +%ifidn __OUTPUT_FORMAT__, elf32 + +[bits 32] + + %define def_wrd dd + %define wrd_sz dword + %define arg1 esi + %define arg2 eax + %define arg3 ebx + %define arg4 ecx + %define arg5 edx + +%else + + default rel + [bits 64] + + %define def_wrd dq + %define wrd_sz qword + %define arg1 rsi + %define arg2 rax + %define arg3 rbx + %define arg4 rcx + %define arg5 rdx + + + extern EC_ENCODE_DATA_UPDATE_SSE + extern EC_ENCODE_DATA_UPDATE_AVX + extern EC_ENCODE_DATA_UPDATE_AVX2 + extern GF_VECT_MUL_SSE + extern GF_VECT_MUL_AVX + + extern GF_VECT_MAD_SSE + extern GF_VECT_MAD_AVX + extern GF_VECT_MAD_AVX2 +%endif + +extern GF_VECT_MUL_BASE +extern EC_ENCODE_DATA_BASE +extern EC_ENCODE_DATA_UPDATE_BASE +extern GF_VECT_DOT_PROD_BASE +extern GF_VECT_MAD_BASE + +extern GF_VECT_DOT_PROD_SSE +extern GF_VECT_DOT_PROD_AVX +extern GF_VECT_DOT_PROD_AVX2 +extern EC_ENCODE_DATA_SSE +extern EC_ENCODE_DATA_AVX +extern EC_ENCODE_DATA_AVX2 + + +section .data +;;; *_mbinit are initial values for *_dispatched; is updated on first call. +;;; Therefore, *_dispatch_init is only executed on first call. + +ec_encode_data_dispatched: + def_wrd ec_encode_data_mbinit + +gf_vect_mul_dispatched: + def_wrd gf_vect_mul_mbinit + +gf_vect_dot_prod_dispatched: + def_wrd gf_vect_dot_prod_mbinit + +ec_encode_data_update_dispatched: + def_wrd ec_encode_data_update_mbinit + +gf_vect_mad_dispatched: + def_wrd gf_vect_mad_mbinit + +section .text +;;;; +; ec_encode_data multibinary function +;;;; +global EC_ENCODE_DATA:function +ec_encode_data_mbinit: + call ec_encode_data_dispatch_init + +EC_ENCODE_DATA: + jmp wrd_sz [ec_encode_data_dispatched] + +ec_encode_data_dispatch_init: + push arg1 + push arg2 + push arg3 + push arg4 + push arg5 + lea arg1, [EC_ENCODE_DATA_BASE WRT_OPT] ; Default + + mov eax, 1 + cpuid + lea arg3, [EC_ENCODE_DATA_SSE WRT_OPT] + test ecx, FLAG_CPUID1_ECX_SSE4_1 + cmovne arg1, arg3 + + and ecx, (FLAG_CPUID1_ECX_AVX | FLAG_CPUID1_ECX_OSXSAVE) + cmp ecx, (FLAG_CPUID1_ECX_AVX | FLAG_CPUID1_ECX_OSXSAVE) + lea arg3, [EC_ENCODE_DATA_AVX WRT_OPT] + + jne _done_ec_encode_data_init + mov arg1, arg3 + + ;; Try for AVX2 + xor ecx, ecx + mov eax, 7 + cpuid + test ebx, FLAG_CPUID1_EBX_AVX2 + lea arg3, [EC_ENCODE_DATA_AVX2 WRT_OPT] + cmovne arg1, arg3 + ;; Does it have xmm and ymm support + xor ecx, ecx + xgetbv + and eax, FLAG_XGETBV_EAX_XMM_YMM + cmp eax, FLAG_XGETBV_EAX_XMM_YMM + je _done_ec_encode_data_init + lea arg1, [EC_ENCODE_DATA_SSE WRT_OPT] + +_done_ec_encode_data_init: + pop arg5 + pop arg4 + pop arg3 + pop arg2 + mov [ec_encode_data_dispatched], arg1 + pop arg1 + ret + +;;;; +; gf_vect_mul multibinary function +;;;; +global GF_VECT_MUL:function +gf_vect_mul_mbinit: + call gf_vect_mul_dispatch_init + +GF_VECT_MUL: + jmp wrd_sz [gf_vect_mul_dispatched] + +gf_vect_mul_dispatch_init: + push arg1 +%ifidn __OUTPUT_FORMAT__, elf32 ;; 32-bit check + lea arg1, [GF_VECT_MUL_BASE] +%else + push rax + push rbx + push rcx + push rdx + lea arg1, [GF_VECT_MUL_BASE WRT_OPT] ; Default + + mov eax, 1 + cpuid + test ecx, FLAG_CPUID1_ECX_SSE4_2 + lea rbx, [GF_VECT_MUL_SSE WRT_OPT] + je _done_gf_vect_mul_dispatch_init + mov arg1, rbx + + ;; Try for AVX + and ecx, (FLAG_CPUID1_ECX_OSXSAVE | FLAG_CPUID1_ECX_AVX) + cmp ecx, (FLAG_CPUID1_ECX_OSXSAVE | FLAG_CPUID1_ECX_AVX) + jne _done_gf_vect_mul_dispatch_init + + ;; Does it have xmm and ymm support + xor ecx, ecx + xgetbv + and eax, FLAG_XGETBV_EAX_XMM_YMM + cmp eax, FLAG_XGETBV_EAX_XMM_YMM + jne _done_gf_vect_mul_dispatch_init + lea arg1, [GF_VECT_MUL_AVX WRT_OPT] + +_done_gf_vect_mul_dispatch_init: + pop rdx + pop rcx + pop rbx + pop rax +%endif ;; END 32-bit check + mov [gf_vect_mul_dispatched], arg1 + pop arg1 + ret + +;;;; +; ec_encode_data_update multibinary function +;;;; +global EC_ENCODE_DATA_UPDATE:function +ec_encode_data_update_mbinit: + call ec_encode_data_update_dispatch_init + +EC_ENCODE_DATA_UPDATE: + jmp wrd_sz [ec_encode_data_update_dispatched] + +ec_encode_data_update_dispatch_init: + push arg1 +%ifidn __OUTPUT_FORMAT__, elf32 ;; 32-bit check + lea arg1, [ec_encode_data_update_base] +%else + push rax + push rbx + push rcx + push rdx + lea arg1, [EC_ENCODE_DATA_UPDATE_BASE WRT_OPT] ; Default + + mov eax, 1 + cpuid + lea rbx, [EC_ENCODE_DATA_UPDATE_SSE WRT_OPT] + test ecx, FLAG_CPUID1_ECX_SSE4_1 + cmovne arg1, rbx + + and ecx, (FLAG_CPUID1_ECX_AVX | FLAG_CPUID1_ECX_OSXSAVE) + cmp ecx, (FLAG_CPUID1_ECX_AVX | FLAG_CPUID1_ECX_OSXSAVE) + lea rbx, [EC_ENCODE_DATA_UPDATE_AVX WRT_OPT] + + jne _done_ec_encode_data_update_init + mov rsi, rbx + + ;; Try for AVX2 + xor ecx, ecx + mov eax, 7 + cpuid + test ebx, FLAG_CPUID1_EBX_AVX2 + lea rbx, [EC_ENCODE_DATA_UPDATE_AVX2 WRT_OPT] + cmovne rsi, rbx + + ;; Does it have xmm and ymm support + xor ecx, ecx + xgetbv + and eax, FLAG_XGETBV_EAX_XMM_YMM + cmp eax, FLAG_XGETBV_EAX_XMM_YMM + je _done_ec_encode_data_update_init + lea rsi, [EC_ENCODE_DATA_UPDATE_SSE WRT_OPT] + +_done_ec_encode_data_update_init: + pop rdx + pop rcx + pop rbx + pop rax +%endif ;; END 32-bit check + mov [ec_encode_data_update_dispatched], arg1 + pop arg1 + ret + +;;;; +; gf_vect_dot_prod multibinary function +;;;; +global GF_VECT_DOT_PROD:function +gf_vect_dot_prod_mbinit: + call gf_vect_dot_prod_dispatch_init + +GF_VECT_DOT_PROD: + jmp wrd_sz [gf_vect_dot_prod_dispatched] + +gf_vect_dot_prod_dispatch_init: + push arg1 + push arg2 + push arg3 + push arg4 + push arg5 + lea arg1, [GF_VECT_DOT_PROD_BASE WRT_OPT] ; Default + + mov eax, 1 + cpuid + lea arg3, [GF_VECT_DOT_PROD_SSE WRT_OPT] + test ecx, FLAG_CPUID1_ECX_SSE4_1 + cmovne arg1, arg3 + + and ecx, (FLAG_CPUID1_ECX_AVX | FLAG_CPUID1_ECX_OSXSAVE) + cmp ecx, (FLAG_CPUID1_ECX_AVX | FLAG_CPUID1_ECX_OSXSAVE) + lea arg3, [GF_VECT_DOT_PROD_AVX WRT_OPT] + + jne _done_gf_vect_dot_prod_init + mov arg1, arg3 + + ;; Try for AVX2 + xor ecx, ecx + mov eax, 7 + cpuid + test ebx, FLAG_CPUID1_EBX_AVX2 + lea arg3, [GF_VECT_DOT_PROD_AVX2 WRT_OPT] + cmovne arg1, arg3 + ;; Does it have xmm and ymm support + xor ecx, ecx + xgetbv + and eax, FLAG_XGETBV_EAX_XMM_YMM + cmp eax, FLAG_XGETBV_EAX_XMM_YMM + je _done_gf_vect_dot_prod_init + lea arg1, [GF_VECT_DOT_PROD_SSE WRT_OPT] + +_done_gf_vect_dot_prod_init: + pop arg5 + pop arg4 + pop arg3 + pop arg2 + mov [gf_vect_dot_prod_dispatched], arg1 + pop arg1 + ret + +;;;; +; gf_vect_mad multibinary function +;;;; +global GF_VECT_MAD:function +gf_vect_mad_mbinit: + call gf_vect_mad_dispatch_init + +GF_VECT_MAD: + jmp wrd_sz [gf_vect_mad_dispatched] + +gf_vect_mad_dispatch_init: + push arg1 +%ifidn __OUTPUT_FORMAT__, elf32 ;; 32-bit check + lea arg1, [gf_vect_mad_base] +%else + push rax + push rbx + push rcx + push rdx + lea arg1, [GF_VECT_MAD_BASE WRT_OPT] ; Default + + mov eax, 1 + cpuid + lea rbx, [GF_VECT_MAD_SSE WRT_OPT] + test ecx, FLAG_CPUID1_ECX_SSE4_1 + cmovne arg1, rbx + + and ecx, (FLAG_CPUID1_ECX_AVX | FLAG_CPUID1_ECX_OSXSAVE) + cmp ecx, (FLAG_CPUID1_ECX_AVX | FLAG_CPUID1_ECX_OSXSAVE) + lea rbx, [GF_VECT_MAD_AVX WRT_OPT] + + jne _done_gf_vect_mad_init + mov rsi, rbx + + ;; Try for AVX2 + xor ecx, ecx + mov eax, 7 + cpuid + test ebx, FLAG_CPUID1_EBX_AVX2 + lea rbx, [GF_VECT_MAD_AVX2 WRT_OPT] + cmovne rsi, rbx + + ;; Does it have xmm and ymm support + xor ecx, ecx + xgetbv + and eax, FLAG_XGETBV_EAX_XMM_YMM + cmp eax, FLAG_XGETBV_EAX_XMM_YMM + je _done_gf_vect_mad_init + lea rsi, [GF_VECT_MAD_SSE WRT_OPT] + +_done_gf_vect_mad_init: + pop rdx + pop rcx + pop rbx + pop rax +%endif ;; END 32-bit check + mov [gf_vect_mad_dispatched], arg1 + pop arg1 + ret + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro + +;;; func core, ver, snum +slversion EC_ENCODE_DATA, 00, 03, 0133 +slversion GF_VECT_MUL, 00, 02, 0134 +slversion EC_ENCODE_DATA_UPDATE, 00, 02, 0212 +slversion GF_VECT_DOT_PROD, 00, 02, 0138 +slversion GF_VECT_MAD, 00, 01, 0213 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_reg_sizes.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_reg_sizes.asm new file mode 100644 index 000000000..8a6f377d3 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_reg_sizes.asm @@ -0,0 +1,96 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +%define EFLAGS_HAS_CPUID (1<<21) +%define FLAG_CPUID1_ECX_CLMUL (1<<1) +%define FLAG_CPUID1_EDX_SSE2 (1<<26) +%define FLAG_CPUID1_ECX_SSE3 (1) +%define FLAG_CPUID1_ECX_SSE4_1 (1<<19) +%define FLAG_CPUID1_ECX_SSE4_2 (1<<20) +%define FLAG_CPUID1_ECX_POPCNT (1<<23) +%define FLAG_CPUID1_ECX_AESNI (1<<25) +%define FLAG_CPUID1_ECX_OSXSAVE (1<<27) +%define FLAG_CPUID1_ECX_AVX (1<<28) +%define FLAG_CPUID1_EBX_AVX2 (1<<5) +%define FLAG_XGETBV_EAX_XMM_YMM 0x6 + +%define FLAG_CPUID1_EAX_AVOTON 0x000406d0 + +; define d and w variants for registers + +%define raxd eax +%define raxw ax +%define raxb al + +%define rbxd ebx +%define rbxw bx +%define rbxb bl + +%define rcxd ecx +%define rcxw cx +%define rcxb cl + +%define rdxd edx +%define rdxw dx +%define rdxb dl + +%define rsid esi +%define rsiw si +%define rsib sil + +%define rdid edi +%define rdiw di +%define rdib dil + +%define rbpd ebp +%define rbpw bp +%define rbpb bpl + +%define ymm0x xmm0 +%define ymm1x xmm1 +%define ymm2x xmm2 +%define ymm3x xmm3 +%define ymm4x xmm4 +%define ymm5x xmm5 +%define ymm6x xmm6 +%define ymm7x xmm7 +%define ymm8x xmm8 +%define ymm9x xmm9 +%define ymm10x xmm10 +%define ymm11x xmm11 +%define ymm12x xmm12 +%define ymm13x xmm13 +%define ymm14x xmm14 +%define ymm15x xmm15 + +%define DWORD(reg) reg %+ d +%define WORD(reg) reg %+ w +%define BYTE(reg) reg %+ b + +%define XWORD(reg) reg %+ x diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_types.h b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_types.h new file mode 100644 index 000000000..62e61e2dd --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/ec_types.h @@ -0,0 +1,80 @@ +/********************************************************************** + Copyright(c) 2011-2015 Intel Corporation All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**********************************************************************/ + + +/** + * @file types.h + * @brief Defines standard width types. + * + */ + +#ifndef __TYPES_H +#define __TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(__unix__) && !defined(__APPLE__) +#ifdef __MINGW32__ +# include <_mingw.h> +#endif +typedef unsigned __int64 UINT64; +typedef __int64 INT64; +typedef unsigned __int32 UINT32; +typedef unsigned __int16 UINT16; +typedef unsigned char UINT8; +#else +typedef unsigned long int UINT64; +typedef long int INT64; +typedef unsigned int UINT32; +typedef unsigned short int UINT16; +typedef unsigned char UINT8; +#endif + + +#if defined(__unix__) || defined(__APPLE__) +# define DECLARE_ALIGNED(decl, alignval) decl __attribute__((aligned(alignval))) +# define __forceinline static inline +#else +# define DECLARE_ALIGNED(decl, alignval) __declspec(align(alignval)) decl +# define posix_memalign(p, algn, len) (NULL == (*((char**)(p)) = (void*) _aligned_malloc(len, algn))) +#endif + +#ifdef DEBUG +# define DEBUG_PRINT(x) printf x +#else +# define DEBUG_PRINT(x) do {} while (0) +#endif + +#ifdef __cplusplus +} +#endif + +#endif //__TYPES_H diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/erasure_decode.go b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/erasure_decode.go new file mode 100644 index 000000000..91c42ce1b --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/erasure_decode.go @@ -0,0 +1,122 @@ +/* + * Minimalist Object Storage, (C) 2014 Minio, 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 erasure + +// #cgo CFLAGS: -O0 +// #include +// #include "ec_isal-l.h" +// #include "ec_minio_common.h" +import "C" +import ( + "errors" + "fmt" + "unsafe" +) + +// Decode decodes erasure coded blocks of data into its original +// form. Erasure coded data contains K data blocks and M parity +// blocks. Decode can withstand data loss up to any M number of blocks. +// +// "encodedDataBlocks" is an array of K data blocks and M parity +// blocks. Data blocks are position and order dependent. Missing blocks +// are set to "nil". There must be at least "K" number of data|parity +// blocks. +// +// "dataLen" is the length of original source data +func (e *Erasure) Decode(encodedDataBlocks [][]byte, dataLen int) (decodedData []byte, err error) { + var source, target **C.uchar + + k := int(e.params.K) + m := int(e.params.M) + n := k + m + // We need the data and parity blocks preserved in the same order. Missing blocks are set to nil. + if len(encodedDataBlocks) != n { + msg := fmt.Sprintf("Encoded data blocks slice must of length [%d]", n) + return nil, errors.New(msg) + } + + // Length of a single encoded block + encodedBlockLen := GetEncodedBlockLen(dataLen, uint8(k)) + + // Keep track of errors per block. + missingEncodedBlocks := make([]int, n+1) + var missingEncodedBlocksCount int + + // Check for the missing encoded blocks + for i := range encodedDataBlocks { + if encodedDataBlocks[i] == nil || len(encodedDataBlocks[i]) == 0 { + missingEncodedBlocks[missingEncodedBlocksCount] = i + missingEncodedBlocksCount++ + } + } + missingEncodedBlocks[missingEncodedBlocksCount] = -1 + missingEncodedBlocksCount++ + + // Cannot reconstruct original data. Need at least M number of data or parity blocks. + if missingEncodedBlocksCount-1 > m { + return nil, fmt.Errorf("Cannot reconstruct original data. Need at least [%d] data or parity blocks", m) + } + + // Convert from Go int slice to C int array + missingEncodedBlocksC := intSlice2CIntArray(missingEncodedBlocks[:missingEncodedBlocksCount]) + + // Allocate buffer for the missing blocks + for i := range encodedDataBlocks { + if encodedDataBlocks[i] == nil || len(encodedDataBlocks[i]) == 0 { + encodedDataBlocks[i] = make([]byte, encodedBlockLen) + } + } + + // If not already initialized, recompute and cache + if e.decodeMatrix == nil || e.decodeTbls == nil || e.decodeIndex == nil { + var decodeMatrix, decodeTbls *C.uchar + var decodeIndex *C.uint32_t + + C.minio_init_decoder(missingEncodedBlocksC, C.int(k), C.int(n), C.int(missingEncodedBlocksCount-1), + e.encodeMatrix, &decodeMatrix, &decodeTbls, &decodeIndex) + + // cache this for future needs + e.decodeMatrix = decodeMatrix + e.decodeTbls = decodeTbls + e.decodeIndex = decodeIndex + } + + // Make a slice of pointers to encoded blocks. Necessary to bridge to the C world. + pointers := make([]*byte, n) + for i := range encodedDataBlocks { + pointers[i] = &encodedDataBlocks[i][0] + } + + // Get pointers to source "data" and target "parity" blocks from the output byte array. + ret := C.minio_get_source_target(C.int(missingEncodedBlocksCount-1), C.int(k), C.int(m), missingEncodedBlocksC, + e.decodeIndex, (**C.uchar)(unsafe.Pointer(&pointers[0])), &source, &target) + if int(ret) == -1 { + return nil, errors.New("Unable to decode data") + } + + // Decode data + C.ec_encode_data(C.int(encodedBlockLen), C.int(k), C.int(missingEncodedBlocksCount-1), e.decodeTbls, + source, target) + + // Allocate buffer to output buffer + decodedData = make([]byte, 0, encodedBlockLen*int(k)) + for i := 0; i < int(k); i++ { + decodedData = append(decodedData, encodedDataBlocks[i]...) + } + + return decodedData[:dataLen], nil +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/erasure_encode.go b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/erasure_encode.go new file mode 100644 index 000000000..5088edfbb --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/erasure_encode.go @@ -0,0 +1,197 @@ +/* + * Minimalist Object Storage, (C) 2014 Minio, 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 erasure + +// #cgo CFLAGS: -O0 +// #include +// #include "ec_isal-l.h" +// #include "ec_minio_common.h" +import "C" +import ( + "errors" + "unsafe" +) + +// Technique - type of matrix type used in encoding +type Technique uint8 + +// Different types of supported matrix types +const ( + Vandermonde Technique = iota + Cauchy + None +) + +// Default Data and Parity blocks +const ( + K = 10 + M = 3 +) + +// Block alignment +const ( + SIMDAlign = 32 +) + +// ErasureParams is a configuration set for building an encoder. It is created using ValidateParams(). +type ErasureParams struct { + K uint8 + M uint8 + Technique Technique // cauchy or vandermonde matrix (RS) +} + +// Erasure is an object used to encode and decode data. +type Erasure struct { + params *ErasureParams + encodeMatrix, encodeTbls *C.uchar + decodeMatrix, decodeTbls *C.uchar + decodeIndex *C.uint32_t +} + +// ValidateParams creates an ErasureParams object. +// +// k and m represent the matrix size, which corresponds to the protection level +// technique is the matrix type. Valid inputs are Cauchy (recommended) or Vandermonde. +// +func ValidateParams(k, m uint8, technique Technique) (*ErasureParams, error) { + if k < 1 { + return nil, errors.New("k cannot be zero") + } + + if m < 1 { + return nil, errors.New("m cannot be zero") + } + + if k+m > 255 { + return nil, errors.New("(k + m) cannot be bigger than Galois field GF(2^8) - 1") + } + + switch technique { + case Vandermonde: + break + case Cauchy: + break + default: + return nil, errors.New("Technique can be either vandermonde or cauchy") + } + + return &ErasureParams{ + K: k, + M: m, + Technique: technique, + }, nil +} + +// NewErasure creates an encoder object with a given set of parameters. +func NewErasure(ep *ErasureParams) *Erasure { + var k = C.int(ep.K) + var m = C.int(ep.M) + + var encodeMatrix *C.uchar + var encodeTbls *C.uchar + + C.minio_init_encoder(C.int(ep.Technique), k, m, &encodeMatrix, + &encodeTbls) + + return &Erasure{ + params: ep, + encodeMatrix: encodeMatrix, + encodeTbls: encodeTbls, + decodeMatrix: nil, + decodeTbls: nil, + decodeIndex: nil, + } +} + +// GetEncodedBlocksLen - total length of all encoded blocks +func GetEncodedBlocksLen(inputLen int, k, m uint8) (outputLen int) { + outputLen = GetEncodedBlockLen(inputLen, k) * int(k+m) + return outputLen +} + +// GetEncodedBlockLen - length per block of encoded blocks +func GetEncodedBlockLen(inputLen int, k uint8) (encodedOutputLen int) { + alignment := int(k) * SIMDAlign + remainder := inputLen % alignment + + paddedInputLen := inputLen + if remainder != 0 { + paddedInputLen = inputLen + (alignment - remainder) + } + encodedOutputLen = paddedInputLen / int(k) + return encodedOutputLen +} + +// Encode erasure codes a block of data in "k" data blocks and "m" parity blocks. +// Output is [k+m][]blocks of data and parity slices. +func (e *Erasure) Encode(inputData []byte) (encodedBlocks [][]byte, err error) { + k := int(e.params.K) // "k" data blocks + m := int(e.params.M) // "m" parity blocks + n := k + m // "n" total encoded blocks + + // Length of a single encoded chunk. + // Total number of encoded chunks = "k" data + "m" parity blocks + encodedBlockLen := GetEncodedBlockLen(len(inputData), uint8(k)) + + // Length of total number of "k" data chunks + encodedDataBlocksLen := encodedBlockLen * k + + // Length of extra padding required for the data blocks. + encodedDataBlocksPadLen := encodedDataBlocksLen - len(inputData) + + // Extend inputData buffer to accommodate coded data blocks if necesssary + if encodedDataBlocksPadLen > 0 { + padding := make([]byte, encodedDataBlocksPadLen) + // Expand with new padded blocks to the byte array + inputData = append(inputData, padding...) + } + + // Extend inputData buffer to accommodate coded parity blocks + { // Local Scope + encodedParityBlocksLen := encodedBlockLen * m + parityBlocks := make([]byte, encodedParityBlocksLen) + inputData = append(inputData, parityBlocks...) + } + + // Allocate memory to the "encoded blocks" return buffer + encodedBlocks = make([][]byte, n) // Return buffer + + // Nessary to bridge Go to the C world. C requires 2D arry of pointers to + // byte array. "encodedBlocks" is a 2D slice. + pointersToEncodedBlock := make([]*byte, n) // Pointers to encoded blocks. + + // Copy data block slices to encoded block buffer + for i := 0; i < k; i++ { + encodedBlocks[i] = inputData[i*encodedBlockLen : (i+1)*encodedBlockLen] + pointersToEncodedBlock[i] = &encodedBlocks[i][0] + } + + // Copy erasure block slices to encoded block buffer + for i := k; i < n; i++ { + encodedBlocks[i] = make([]byte, encodedBlockLen) + pointersToEncodedBlock[i] = &encodedBlocks[i][0] + } + + // Erasure code the data into K data blocks and M parity + // blocks. Only the parity blocks are filled. Data blocks remain + // intact. + C.ec_encode_data(C.int(encodedBlockLen), C.int(k), C.int(m), e.encodeTbls, + (**C.uchar)(unsafe.Pointer(&pointersToEncodedBlock[:k][0])), // Pointers to data blocks + (**C.uchar)(unsafe.Pointer(&pointersToEncodedBlock[k:][0]))) // Pointers to parity blocks + + return encodedBlocks, nil +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/erasure_yasm_darwin.go b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/erasure_yasm_darwin.go new file mode 100644 index 000000000..55380b0e2 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/erasure_yasm_darwin.go @@ -0,0 +1,43 @@ +// !build amd64 + +package erasure + +//go:generate yasm -f macho64 ec_multibinary.asm -o ec_multibinary.syso +//go:generate yasm -f macho64 gf_2vect_mad_avx2.asm -o gf_2vect_mad_avx2.syso +//go:generate yasm -f macho64 gf_2vect_mad_avx.asm -o gf_2vect_mad_avx.syso +//go:generate yasm -f macho64 gf_2vect_mad_sse.asm -o gf_2vect_mad_sse.syso +//go:generate yasm -f macho64 gf_3vect_mad_avx2.asm -o gf_3vect_mad_avx2.syso +//go:generate yasm -f macho64 gf_3vect_mad_avx.asm -o gf_3vect_mad_avx.syso +//go:generate yasm -f macho64 gf_3vect_mad_sse.asm -o gf_3vect_mad_sse.syso +//go:generate yasm -f macho64 gf_4vect_mad_avx2.asm -o gf_4vect_mad_avx2.syso +//go:generate yasm -f macho64 gf_4vect_mad_avx.asm -o gf_4vect_mad_avx.syso +//go:generate yasm -f macho64 gf_4vect_mad_sse.asm -o gf_4vect_mad_sse.syso +//go:generate yasm -f macho64 gf_5vect_mad_avx2.asm -o gf_5vect_mad_avx2.syso +//go:generate yasm -f macho64 gf_5vect_mad_avx.asm -o gf_5vect_mad_avx.syso +//go:generate yasm -f macho64 gf_5vect_mad_sse.asm -o gf_5vect_mad_sse.syso +//go:generate yasm -f macho64 gf_6vect_mad_avx2.asm -o gf_6vect_mad_avx2.syso +//go:generate yasm -f macho64 gf_6vect_mad_avx.asm -o gf_6vect_mad_avx.syso +//go:generate yasm -f macho64 gf_6vect_mad_sse.asm -o gf_6vect_mad_sse.syso +//go:generate yasm -f macho64 gf_vect_mad_avx2.asm -o gf_vect_mad_avx2.syso +//go:generate yasm -f macho64 gf_vect_mad_avx.asm -o gf_vect_mad_avx.syso +//go:generate yasm -f macho64 gf_vect_mad_sse.asm -o gf_vect_mad_sse.syso +//go:generate yasm -f macho64 gf_2vect_dot_prod_avx2.asm -o gf_2vect_dot_prod_avx2.syso +//go:generate yasm -f macho64 gf_2vect_dot_prod_avx.asm -o gf_2vect_dot_prod_avx.syso +//go:generate yasm -f macho64 gf_2vect_dot_prod_sse.asm -o gf_2vect_dot_prod_sse.syso +//go:generate yasm -f macho64 gf_3vect_dot_prod_avx2.asm -o gf_3vect_dot_prod_avx2.syso +//go:generate yasm -f macho64 gf_3vect_dot_prod_avx.asm -o gf_3vect_dot_prod_avx.syso +//go:generate yasm -f macho64 gf_3vect_dot_prod_sse.asm -o gf_3vect_dot_prod_sse.syso +//go:generate yasm -f macho64 gf_4vect_dot_prod_avx2.asm -o gf_4vect_dot_prod_avx2.syso +//go:generate yasm -f macho64 gf_4vect_dot_prod_avx.asm -o gf_4vect_dot_prod_avx.syso +//go:generate yasm -f macho64 gf_4vect_dot_prod_sse.asm -o gf_4vect_dot_prod_sse.syso +//go:generate yasm -f macho64 gf_5vect_dot_prod_avx2.asm -o gf_5vect_dot_prod_avx2.syso +//go:generate yasm -f macho64 gf_5vect_dot_prod_avx.asm -o gf_5vect_dot_prod_avx.syso +//go:generate yasm -f macho64 gf_5vect_dot_prod_sse.asm -o gf_5vect_dot_prod_sse.syso +//go:generate yasm -f macho64 gf_6vect_dot_prod_avx2.asm -o gf_6vect_dot_prod_avx2.syso +//go:generate yasm -f macho64 gf_6vect_dot_prod_avx.asm -o gf_6vect_dot_prod_avx.syso +//go:generate yasm -f macho64 gf_6vect_dot_prod_sse.asm -o gf_6vect_dot_prod_sse.syso +//go:generate yasm -f macho64 gf_vect_dot_prod_avx2.asm -o gf_vect_dot_prod_avx2.syso +//go:generate yasm -f macho64 gf_vect_dot_prod_avx.asm -o gf_vect_dot_prod_avx.syso +//go:generate yasm -f macho64 gf_vect_dot_prod_sse.asm -o gf_vect_dot_prod_sse.syso +//go:generate yasm -f macho64 gf_vect_mul_avx.asm -o gf_vect_mul_avx.syso +//go:generate yasm -f macho64 gf_vect_mul_sse.asm -o gf_vect_mul_sse.syso diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/erasure_yasm_linux.go b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/erasure_yasm_linux.go new file mode 100644 index 000000000..0574a7ccc --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/erasure_yasm_linux.go @@ -0,0 +1,43 @@ +// !build amd64 + +package erasure + +//go:generate yasm -f elf64 ec_multibinary.asm -o ec_multibinary.syso +//go:generate yasm -f elf64 gf_2vect_mad_avx2.asm -o gf_2vect_mad_avx2.syso +//go:generate yasm -f elf64 gf_2vect_mad_avx.asm -o gf_2vect_mad_avx.syso +//go:generate yasm -f elf64 gf_2vect_mad_sse.asm -o gf_2vect_mad_sse.syso +//go:generate yasm -f elf64 gf_3vect_mad_avx2.asm -o gf_3vect_mad_avx2.syso +//go:generate yasm -f elf64 gf_3vect_mad_avx.asm -o gf_3vect_mad_avx.syso +//go:generate yasm -f elf64 gf_3vect_mad_sse.asm -o gf_3vect_mad_sse.syso +//go:generate yasm -f elf64 gf_4vect_mad_avx2.asm -o gf_4vect_mad_avx2.syso +//go:generate yasm -f elf64 gf_4vect_mad_avx.asm -o gf_4vect_mad_avx.syso +//go:generate yasm -f elf64 gf_4vect_mad_sse.asm -o gf_4vect_mad_sse.syso +//go:generate yasm -f elf64 gf_5vect_mad_avx2.asm -o gf_5vect_mad_avx2.syso +//go:generate yasm -f elf64 gf_5vect_mad_avx.asm -o gf_5vect_mad_avx.syso +//go:generate yasm -f elf64 gf_5vect_mad_sse.asm -o gf_5vect_mad_sse.syso +//go:generate yasm -f elf64 gf_6vect_mad_avx2.asm -o gf_6vect_mad_avx2.syso +//go:generate yasm -f elf64 gf_6vect_mad_avx.asm -o gf_6vect_mad_avx.syso +//go:generate yasm -f elf64 gf_6vect_mad_sse.asm -o gf_6vect_mad_sse.syso +//go:generate yasm -f elf64 gf_vect_mad_avx2.asm -o gf_vect_mad_avx2.syso +//go:generate yasm -f elf64 gf_vect_mad_avx.asm -o gf_vect_mad_avx.syso +//go:generate yasm -f elf64 gf_vect_mad_sse.asm -o gf_vect_mad_sse.syso +//go:generate yasm -f elf64 gf_2vect_dot_prod_avx2.asm -o gf_2vect_dot_prod_avx2.syso +//go:generate yasm -f elf64 gf_2vect_dot_prod_avx.asm -o gf_2vect_dot_prod_avx.syso +//go:generate yasm -f elf64 gf_2vect_dot_prod_sse.asm -o gf_2vect_dot_prod_sse.syso +//go:generate yasm -f elf64 gf_3vect_dot_prod_avx2.asm -o gf_3vect_dot_prod_avx2.syso +//go:generate yasm -f elf64 gf_3vect_dot_prod_avx.asm -o gf_3vect_dot_prod_avx.syso +//go:generate yasm -f elf64 gf_3vect_dot_prod_sse.asm -o gf_3vect_dot_prod_sse.syso +//go:generate yasm -f elf64 gf_4vect_dot_prod_avx2.asm -o gf_4vect_dot_prod_avx2.syso +//go:generate yasm -f elf64 gf_4vect_dot_prod_avx.asm -o gf_4vect_dot_prod_avx.syso +//go:generate yasm -f elf64 gf_4vect_dot_prod_sse.asm -o gf_4vect_dot_prod_sse.syso +//go:generate yasm -f elf64 gf_5vect_dot_prod_avx2.asm -o gf_5vect_dot_prod_avx2.syso +//go:generate yasm -f elf64 gf_5vect_dot_prod_avx.asm -o gf_5vect_dot_prod_avx.syso +//go:generate yasm -f elf64 gf_5vect_dot_prod_sse.asm -o gf_5vect_dot_prod_sse.syso +//go:generate yasm -f elf64 gf_6vect_dot_prod_avx2.asm -o gf_6vect_dot_prod_avx2.syso +//go:generate yasm -f elf64 gf_6vect_dot_prod_avx.asm -o gf_6vect_dot_prod_avx.syso +//go:generate yasm -f elf64 gf_6vect_dot_prod_sse.asm -o gf_6vect_dot_prod_sse.syso +//go:generate yasm -f elf64 gf_vect_dot_prod_avx2.asm -o gf_vect_dot_prod_avx2.syso +//go:generate yasm -f elf64 gf_vect_dot_prod_avx.asm -o gf_vect_dot_prod_avx.syso +//go:generate yasm -f elf64 gf_vect_dot_prod_sse.asm -o gf_vect_dot_prod_sse.syso +//go:generate yasm -f elf64 gf_vect_mul_avx.asm -o gf_vect_mul_avx.syso +//go:generate yasm -f elf64 gf_vect_mul_sse.asm -o gf_vect_mul_sse.syso diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/erasure_yasm_windows.go b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/erasure_yasm_windows.go new file mode 100644 index 000000000..c3aa6f0de --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/erasure_yasm_windows.go @@ -0,0 +1,43 @@ +// !build amd64 + +package erasure + +//go:generate yasm -f win64 ec_multibinary.asm -o ec_multibinary.syso +//go:generate yasm -f win64 gf_2vect_mad_avx2.asm -o gf_2vect_mad_avx2.syso +//go:generate yasm -f win64 gf_2vect_mad_avx.asm -o gf_2vect_mad_avx.syso +//go:generate yasm -f win64 gf_2vect_mad_sse.asm -o gf_2vect_mad_sse.syso +//go:generate yasm -f win64 gf_3vect_mad_avx2.asm -o gf_3vect_mad_avx2.syso +//go:generate yasm -f win64 gf_3vect_mad_avx.asm -o gf_3vect_mad_avx.syso +//go:generate yasm -f win64 gf_3vect_mad_sse.asm -o gf_3vect_mad_sse.syso +//go:generate yasm -f win64 gf_4vect_mad_avx2.asm -o gf_4vect_mad_avx2.syso +//go:generate yasm -f win64 gf_4vect_mad_avx.asm -o gf_4vect_mad_avx.syso +//go:generate yasm -f win64 gf_4vect_mad_sse.asm -o gf_4vect_mad_sse.syso +//go:generate yasm -f win64 gf_5vect_mad_avx2.asm -o gf_5vect_mad_avx2.syso +//go:generate yasm -f win64 gf_5vect_mad_avx.asm -o gf_5vect_mad_avx.syso +//go:generate yasm -f win64 gf_5vect_mad_sse.asm -o gf_5vect_mad_sse.syso +//go:generate yasm -f win64 gf_6vect_mad_avx2.asm -o gf_6vect_mad_avx2.syso +//go:generate yasm -f win64 gf_6vect_mad_avx.asm -o gf_6vect_mad_avx.syso +//go:generate yasm -f win64 gf_6vect_mad_sse.asm -o gf_6vect_mad_sse.syso +//go:generate yasm -f win64 gf_vect_mad_avx2.asm -o gf_vect_mad_avx2.syso +//go:generate yasm -f win64 gf_vect_mad_avx.asm -o gf_vect_mad_avx.syso +//go:generate yasm -f win64 gf_vect_mad_sse.asm -o gf_vect_mad_sse.syso +//go:generate yasm -f win64 gf_2vect_dot_prod_avx2.asm -o gf_2vect_dot_prod_avx2.syso +//go:generate yasm -f win64 gf_2vect_dot_prod_avx.asm -o gf_2vect_dot_prod_avx.syso +//go:generate yasm -f win64 gf_2vect_dot_prod_sse.asm -o gf_2vect_dot_prod_sse.syso +//go:generate yasm -f win64 gf_3vect_dot_prod_avx2.asm -o gf_3vect_dot_prod_avx2.syso +//go:generate yasm -f win64 gf_3vect_dot_prod_avx.asm -o gf_3vect_dot_prod_avx.syso +//go:generate yasm -f win64 gf_3vect_dot_prod_sse.asm -o gf_3vect_dot_prod_sse.syso +//go:generate yasm -f win64 gf_4vect_dot_prod_avx2.asm -o gf_4vect_dot_prod_avx2.syso +//go:generate yasm -f win64 gf_4vect_dot_prod_avx.asm -o gf_4vect_dot_prod_avx.syso +//go:generate yasm -f win64 gf_4vect_dot_prod_sse.asm -o gf_4vect_dot_prod_sse.syso +//go:generate yasm -f win64 gf_5vect_dot_prod_avx2.asm -o gf_5vect_dot_prod_avx2.syso +//go:generate yasm -f win64 gf_5vect_dot_prod_avx.asm -o gf_5vect_dot_prod_avx.syso +//go:generate yasm -f win64 gf_5vect_dot_prod_sse.asm -o gf_5vect_dot_prod_sse.syso +//go:generate yasm -f win64 gf_6vect_dot_prod_avx2.asm -o gf_6vect_dot_prod_avx2.syso +//go:generate yasm -f win64 gf_6vect_dot_prod_avx.asm -o gf_6vect_dot_prod_avx.syso +//go:generate yasm -f win64 gf_6vect_dot_prod_sse.asm -o gf_6vect_dot_prod_sse.syso +//go:generate yasm -f win64 gf_vect_dot_prod_avx2.asm -o gf_vect_dot_prod_avx2.syso +//go:generate yasm -f win64 gf_vect_dot_prod_avx.asm -o gf_vect_dot_prod_avx.syso +//go:generate yasm -f win64 gf_vect_dot_prod_sse.asm -o gf_vect_dot_prod_sse.syso +//go:generate yasm -f win64 gf_vect_mul_avx.asm -o gf_vect_mul_avx.syso +//go:generate yasm -f win64 gf_vect_mul_sse.asm -o gf_vect_mul_sse.syso diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_2vect_dot_prod_avx.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_2vect_dot_prod_avx.asm new file mode 100644 index 000000000..8dcc3382f --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_2vect_dot_prod_avx.asm @@ -0,0 +1,381 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_2vect_dot_prod_avx(len, vec, *g_tbls, **buffs, **dests); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_2VECT_DOT_PROD_AVX _gf_2vect_dot_prod_avx +%else + %define GF_2VECT_DOT_PROD_AVX gf_2vect_dot_prod_avx +%endif + +%ifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp2 r10 + %define tmp3 r9 + %define tmp4 r12 ; must be saved and restored + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + %endmacro + %macro FUNC_RESTORE 0 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r12 ; must be saved and restored + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + %endmacro + %macro FUNC_RESTORE 0 + pop r13 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + + %define arg4 r12 ; must be saved, loaded and restored + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r14 ; must be saved and restored + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define LOG_PS 3 + %define stack_size 3*16 + 3*8 ; must be an odd multiple of 8 + %define arg(x) [rsp + stack_size + PS + PS*x] + + %define func(x) proc_frame x + %macro FUNC_SAVE 0 + alloc_stack stack_size + save_xmm128 xmm6, 0*16 + save_xmm128 xmm7, 1*16 + save_xmm128 xmm8, 2*16 + save_reg r12, 3*16 + 0*8 + save_reg r13, 3*16 + 1*8 + save_reg r14, 3*16 + 2*8 + end_prolog + mov arg4, arg(4) + %endmacro + + %macro FUNC_RESTORE 0 + vmovdqa xmm6, [rsp + 0*16] + vmovdqa xmm7, [rsp + 1*16] + vmovdqa xmm8, [rsp + 2*16] + mov r12, [rsp + 3*16 + 0*8] + mov r13, [rsp + 3*16 + 1*8] + mov r14, [rsp + 3*16 + 2*8] + add rsp, stack_size + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, elf32 + +;;;================== High Address; +;;; arg4 +;;; arg3 +;;; arg2 +;;; arg1 +;;; arg0 +;;; return +;;;<================= esp of caller +;;; ebp +;;;<================= ebp = esp +;;; var0 +;;; esi +;;; edi +;;; ebx +;;;<================= esp of callee +;;; +;;;================== Low Address; + + %define PS 4 + %define LOG_PS 2 + %define func(x) x: + %define arg(x) [ebp + PS*2 + PS*x] + %define var(x) [ebp - PS - PS*x] + + %define trans ecx + %define trans2 esi + %define arg0 trans ;trans and trans2 are for the variables in stack + %define arg0_m arg(0) + %define arg1 ebx + %define arg2 arg2_m + %define arg2_m arg(2) + %define arg3 trans + %define arg3_m arg(3) + %define arg4 trans + %define arg4_m arg(4) + %define tmp edx + %define tmp2 edi + %define tmp3 trans2 + %define tmp4 trans2 + %define tmp4_m var(0) + %define return eax + %macro SLDR 2 ;; stack load/restore + mov %1, %2 + %endmacro + %define SSTR SLDR + + %macro FUNC_SAVE 0 + push ebp + mov ebp, esp + sub esp, PS*1 ;1 local variable + push esi + push edi + push ebx + mov arg1, arg(1) + %endmacro + + %macro FUNC_RESTORE 0 + pop ebx + pop edi + pop esi + add esp, PS*1 ;1 local variable + pop ebp + %endmacro + +%endif ; output formats + +%define len arg0 +%define vec arg1 +%define mul_array arg2 +%define src arg3 +%define dest1 arg4 + +%define vec_i tmp2 +%define ptr tmp3 +%define dest2 tmp4 +%define pos return + + %ifidn PS,4 ;32-bit code + %define len_m arg0_m + %define src_m arg3_m + %define dest1_m arg4_m + %define dest2_m tmp4_m + %endif + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR vmovdqu + %define XSTR vmovdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR vmovdqa + %define XSTR vmovdqa + %else + %define XLDR vmovntdqa + %define XSTR vmovntdq + %endif +%endif + +%ifidn PS,8 ; 64-bit code + default rel + [bits 64] +%endif + +section .text + +%ifidn PS,8 ;64-bit code + %define xmask0f xmm8 + %define xgft1_lo xmm7 + %define xgft1_hi xmm6 + %define xgft2_lo xmm5 + %define xgft2_hi xmm4 + + %define x0 xmm0 + %define xtmpa xmm1 + %define xp1 xmm2 + %define xp2 xmm3 +%else ;32-bit code + %define xmask0f xmm4 + %define xgft1_lo xmm7 + %define xgft1_hi xmm6 + %define xgft2_lo xgft1_lo + %define xgft2_hi xgft1_hi + + %define x0 xmm0 + %define xtmpa xmm1 + %define xp1 xmm2 + %define xp2 xmm3 +%endif + +align 16 +global GF_2VECT_DOT_PROD_AVX:function + +func(GF_2VECT_DOT_PROD_AVX) + FUNC_SAVE + SLDR len, len_m + sub len, 16 + SSTR len_m, len + jl .return_fail + xor pos, pos + vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS + SLDR dest1, dest1_m + mov dest2, [dest1+PS] + SSTR dest2_m, dest2 + mov dest1, [dest1] + SSTR dest1_m, dest1 + +.loop16 + vpxor xp1, xp1 + vpxor xp2, xp2 + mov tmp, mul_array + xor vec_i, vec_i + +.next_vect + SLDR src, src_m + mov ptr, [src+vec_i] + + vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} + vmovdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, ..., Ax{f0} + %ifidn PS,8 ; 64-bit code + vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} + vmovdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} + add tmp, 32 + add vec_i, PS + %endif + XLDR x0, [ptr+pos] ;Get next source vector + + vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + + vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft1_hi, xgft1_lo ;GF add high and low partials + vpxor xp1, xgft1_hi ;xp1 += partial + + %ifidn PS,4 ; 32-bit code + vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} + vmovdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} + add tmp, 32 + add vec_i, PS + %endif + vpshufb xgft2_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft2_hi, xgft2_lo ;GF add high and low partials + vpxor xp2, xgft2_hi ;xp2 += partial + + cmp vec_i, vec + jl .next_vect + + SLDR dest1, dest1_m + SLDR dest2, dest2_m + XSTR [dest1+pos], xp1 + XSTR [dest2+pos], xp2 + + SLDR len, len_m + add pos, 16 ;Loop on 16 bytes at a time + cmp pos, len + jle .loop16 + + lea tmp, [len + 16] + cmp pos, tmp + je .return_pass + + ;; Tail len + mov pos, len ;Overlapped offset length-16 + jmp .loop16 ;Do one more overlap pass + +.return_pass: + mov return, 0 + FUNC_RESTORE + ret + +.return_fail: + mov return, 1 + FUNC_RESTORE + ret + +endproc_frame + +section .data + +align 16 +mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_2VECT_DOT_PROD_AVX, 02, 04, 0191 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_2vect_dot_prod_avx2.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_2vect_dot_prod_avx2.asm new file mode 100644 index 000000000..583ce7416 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_2vect_dot_prod_avx2.asm @@ -0,0 +1,398 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_2vect_dot_prod_avx2(len, vec, *g_tbls, **buffs, **dests); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_2VECT_DOT_PROD_AVX2 _gf_2vect_dot_prod_avx2 +%else + %define GF_2VECT_DOT_PROD_AVX2 gf_2vect_dot_prod_avx2 +%endif + +%ifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define tmp3 r9 + %define tmp4 r12 ; must be saved and restored + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + %endmacro + %macro FUNC_RESTORE 0 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define tmp3 r9 + %define tmp4 r12 ; must be saved and restored + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + %endmacro + %macro FUNC_RESTORE 0 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + + %define arg4 r12 ; must be saved, loaded and restored + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r14 ; must be saved and restored + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define LOG_PS 3 + %define stack_size 3*16 + 3*8 ; must be an odd multiple of 8 + %define arg(x) [rsp + stack_size + PS + PS*x] + + %define func(x) proc_frame x + %macro FUNC_SAVE 0 + alloc_stack stack_size + vmovdqa [rsp + 0*16], xmm6 + vmovdqa [rsp + 1*16], xmm7 + vmovdqa [rsp + 2*16], xmm8 + save_reg r12, 3*16 + 0*8 + save_reg r13, 3*16 + 1*8 + save_reg r14, 3*16 + 2*8 + end_prolog + mov arg4, arg(4) + %endmacro + + %macro FUNC_RESTORE 0 + vmovdqa xmm6, [rsp + 0*16] + vmovdqa xmm7, [rsp + 1*16] + vmovdqa xmm8, [rsp + 2*16] + mov r12, [rsp + 3*16 + 0*8] + mov r13, [rsp + 3*16 + 1*8] + mov r14, [rsp + 3*16 + 2*8] + add rsp, stack_size + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, elf32 + +;;;================== High Address; +;;; arg4 +;;; arg3 +;;; arg2 +;;; arg1 +;;; arg0 +;;; return +;;;<================= esp of caller +;;; ebp +;;;<================= ebp = esp +;;; var0 +;;; esi +;;; edi +;;; ebx +;;;<================= esp of callee +;;; +;;;================== Low Address; + + %define PS 4 + %define LOG_PS 2 + %define func(x) x: + %define arg(x) [ebp + PS*2 + PS*x] + %define var(x) [ebp - PS - PS*x] + + %define trans ecx + %define trans2 esi + %define arg0 trans ;trans and trans2 are for the variables in stack + %define arg0_m arg(0) + %define arg1 ebx + %define arg2 arg2_m + %define arg2_m arg(2) + %define arg3 trans + %define arg3_m arg(3) + %define arg4 trans + %define arg4_m arg(4) + %define tmp edx + %define tmp.w edx + %define tmp.b dl + %define tmp2 edi + %define tmp3 trans2 + %define tmp4 trans2 + %define tmp4_m var(0) + %define return eax + %macro SLDR 2 ;stack load/restore + mov %1, %2 + %endmacro + %define SSTR SLDR + + %macro FUNC_SAVE 0 + push ebp + mov ebp, esp + sub esp, PS*1 ;1 local variable + push esi + push edi + push ebx + mov arg1, arg(1) + %endmacro + + %macro FUNC_RESTORE 0 + pop ebx + pop edi + pop esi + add esp, PS*1 ;1 local variable + pop ebp + %endmacro + +%endif ; output formats + +%define len arg0 +%define vec arg1 +%define mul_array arg2 +%define src arg3 +%define dest1 arg4 + +%define vec_i tmp2 +%define ptr tmp3 +%define dest2 tmp4 +%define pos return + +%ifidn PS,4 ;32-bit code + %define len_m arg0_m + %define src_m arg3_m + %define dest1_m arg4_m + %define dest2_m tmp4_m +%endif + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR vmovdqu + %define XSTR vmovdqu +%else + +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR vmovdqa + %define XSTR vmovdqa + %else + %define XLDR vmovntdqa + %define XSTR vmovntdq + %endif +%endif + +%ifidn PS,8 ;64-bit code + default rel + [bits 64] +%endif + +section .text + +%ifidn PS,8 ;64-bit code + %define xmask0f ymm8 + %define xmask0fx xmm8 + %define xgft1_lo ymm7 + %define xgft1_hi ymm6 + %define xgft2_lo ymm5 + %define xgft2_hi ymm4 + + %define x0 ymm0 + %define xtmpa ymm1 + %define xp1 ymm2 + %define xp2 ymm3 +%else ;32-bit code + %define xmask0f ymm7 + %define xmask0fx xmm7 + %define xgft1_lo ymm5 + %define xgft1_hi ymm4 + %define xgft2_lo xgft1_lo + %define xgft2_hi xgft1_hi + + %define x0 ymm0 + %define xtmpa ymm1 + %define xp1 ymm2 + %define xp2 ymm3 + +%endif + +align 16 +global GF_2VECT_DOT_PROD_AVX2:function + +func(GF_2VECT_DOT_PROD_AVX2) + FUNC_SAVE + SLDR len, len_m + sub len, 32 + SSTR len_m, len + jl .return_fail + xor pos, pos + mov tmp.b, 0x0f + vpinsrb xmask0fx, xmask0fx, tmp.w, 0 + vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f... + + sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS + SLDR dest1, dest1_m + mov dest2, [dest1+PS] + SSTR dest2_m, dest2 + mov dest1, [dest1] + SSTR dest1_m, dest1 + +.loop32 + vpxor xp1, xp1 + vpxor xp2, xp2 + mov tmp, mul_array + xor vec_i, vec_i + +.next_vect + SLDR src, src_m + mov ptr, [src+vec_i] + + vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} + ; " Ax{00}, Ax{10}, ..., Ax{f0} + vperm2i128 xgft1_hi, xgft1_lo, xgft1_lo, 0x11 ; swapped to hi | hi + vperm2i128 xgft1_lo, xgft1_lo, xgft1_lo, 0x00 ; swapped to lo | lo + %ifidn PS,8 ; 64-bit code + vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} + ; " Bx{00}, Bx{10}, ..., Bx{f0} + vperm2i128 xgft2_hi, xgft2_lo, xgft2_lo, 0x11 ; swapped to hi | hi + vperm2i128 xgft2_lo, xgft2_lo, xgft2_lo, 0x00 ; swapped to lo | lo + + XLDR x0, [ptr+pos] ;Get next source vector + add tmp, 32 + add vec_i, PS + %else + XLDR x0, [ptr+pos] ;Get next source vector + %endif + + vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + + vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft1_hi, xgft1_lo ;GF add high and low partials + vpxor xp1, xgft1_hi ;xp1 += partial + + %ifidn PS,4 ; 32-bit code + vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} + ; " Bx{00}, Bx{10}, ..., Bx{f0} + vperm2i128 xgft2_hi, xgft2_lo, xgft2_lo, 0x11 ; swapped to hi | hi + vperm2i128 xgft2_lo, xgft2_lo, xgft2_lo, 0x00 ; swapped to lo | lo + add tmp, 32 + add vec_i, PS + %endif + vpshufb xgft2_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft2_hi, xgft2_lo ;GF add high and low partials + vpxor xp2, xgft2_hi ;xp2 += partial + + cmp vec_i, vec + jl .next_vect + + SLDR dest1, dest1_m + SLDR dest2, dest2_m + XSTR [dest1+pos], xp1 + XSTR [dest2+pos], xp2 + + SLDR len, len_m + add pos, 32 ;Loop on 32 bytes at a time + cmp pos, len + jle .loop32 + + lea tmp, [len + 32] + cmp pos, tmp + je .return_pass + + ;; Tail len + mov pos, len ;Overlapped offset length-16 + jmp .loop32 ;Do one more overlap pass + +.return_pass: + mov return, 0 + FUNC_RESTORE + ret + +.return_fail: + mov return, 1 + FUNC_RESTORE + ret + +endproc_frame + +section .data + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_2VECT_DOT_PROD_AVX2, 04, 04, 0196 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_2vect_dot_prod_sse.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_2vect_dot_prod_sse.asm new file mode 100644 index 000000000..5237314c6 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_2vect_dot_prod_sse.asm @@ -0,0 +1,383 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_2vect_dot_prod_sse(len, vec, *g_tbls, **buffs, **dests); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_2VECT_DOT_PROD_SSE _gf_2vect_dot_prod_sse +%else + %define GF_2VECT_DOT_PROD_SSE gf_2vect_dot_prod_sse +%endif + +%ifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp2 r10 + %define tmp3 r9 + %define tmp4 r12 ; must be saved and restored + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + %endmacro + %macro FUNC_RESTORE 0 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r12 ; must be saved and restored + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + %endmacro + %macro FUNC_RESTORE 0 + pop r13 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + + %define arg4 r12 ; must be saved, loaded and restored + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r14 ; must be saved and restored + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define LOG_PS 3 + %define stack_size 3*16 + 3*8 ; must be an odd multiple of 8 + %define arg(x) [rsp + stack_size + PS + PS*x] + + %define func(x) proc_frame x + %macro FUNC_SAVE 0 + alloc_stack stack_size + save_xmm128 xmm6, 0*16 + save_xmm128 xmm7, 1*16 + save_xmm128 xmm8, 2*16 + save_reg r12, 3*16 + 0*8 + save_reg r13, 3*16 + 1*8 + save_reg r14, 3*16 + 2*8 + end_prolog + mov arg4, arg(4) + %endmacro + + %macro FUNC_RESTORE 0 + movdqa xmm6, [rsp + 0*16] + movdqa xmm7, [rsp + 1*16] + movdqa xmm8, [rsp + 2*16] + mov r12, [rsp + 3*16 + 0*8] + mov r13, [rsp + 3*16 + 1*8] + mov r14, [rsp + 3*16 + 2*8] + add rsp, stack_size + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, elf32 + +;;;================== High Address; +;;; arg4 +;;; arg3 +;;; arg2 +;;; arg1 +;;; arg0 +;;; return +;;;<================= esp of caller +;;; ebp +;;;<================= ebp = esp +;;; var0 +;;; esi +;;; edi +;;; ebx +;;;<================= esp of callee +;;; +;;;================== Low Address; + + %define PS 4 + %define LOG_PS 2 + %define func(x) x: + %define arg(x) [ebp + PS*2 + PS*x] + %define var(x) [ebp - PS - PS*x] + + %define trans ecx + %define trans2 esi + %define arg0 trans ;trans and trans2 are for the variables in stack + %define arg0_m arg(0) + %define arg1 ebx + %define arg2 arg2_m + %define arg2_m arg(2) + %define arg3 trans + %define arg3_m arg(3) + %define arg4 trans + %define arg4_m arg(4) + %define tmp edx + %define tmp2 edi + %define tmp3 trans2 + %define tmp4 trans2 + %define tmp4_m var(0) + %define return eax + %macro SLDR 2 ;; stack load/restore + mov %1, %2 + %endmacro + %define SSTR SLDR + + %macro FUNC_SAVE 0 + push ebp + mov ebp, esp + sub esp, PS*1 ;1 local variable + push esi + push edi + push ebx + mov arg1, arg(1) + %endmacro + + %macro FUNC_RESTORE 0 + pop ebx + pop edi + pop esi + add esp, PS*1 ;1 local variable + pop ebp + %endmacro + +%endif ; output formats + +%define len arg0 +%define vec arg1 +%define mul_array arg2 +%define src arg3 +%define dest1 arg4 + +%define vec_i tmp2 +%define ptr tmp3 +%define dest2 tmp4 +%define pos return + + %ifidn PS,4 ;32-bit code + %define len_m arg0_m + %define src_m arg3_m + %define dest1_m arg4_m + %define dest2_m tmp4_m + %endif + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR movdqu + %define XSTR movdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR movdqa + %define XSTR movdqa + %else + %define XLDR movntdqa + %define XSTR movntdq + %endif +%endif + +%ifidn PS,8 ;64-bit code + default rel + [bits 64] +%endif + +section .text + +%ifidn PS,8 ;64-bit code + %define xmask0f xmm8 + %define xgft1_lo xmm7 + %define xgft1_hi xmm6 + %define xgft2_lo xmm5 + %define xgft2_hi xmm4 + + %define x0 xmm0 + %define xtmpa xmm1 + %define xp1 xmm2 + %define xp2 xmm3 +%else ;32-bit code + %define xmask0f xmm4 + %define xgft1_lo xmm7 + %define xgft1_hi xmm6 + %define xgft2_lo xgft1_lo + %define xgft2_hi xgft1_hi + + %define x0 xmm0 + %define xtmpa xmm1 + %define xp1 xmm2 + %define xp2 xmm3 +%endif + +align 16 +global GF_2VECT_DOT_PROD_SSE:function + +func(GF_2VECT_DOT_PROD_SSE) + FUNC_SAVE + SLDR len, len_m + sub len, 16 + SSTR len_m, len + jl .return_fail + xor pos, pos + movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS + SLDR dest1, dest1_m + mov dest2, [dest1+PS] + SSTR dest2_m, dest2 + mov dest1, [dest1] + SSTR dest1_m, dest1 + +.loop16 + pxor xp1, xp1 + pxor xp2, xp2 + mov tmp, mul_array + xor vec_i, vec_i + +.next_vect + SLDR src, src_m + mov ptr, [src+vec_i] + + movdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} + movdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, ..., Ax{f0} + %ifidn PS,8 ;64-bit code + movdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} + movdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} + add tmp, 32 + add vec_i, PS + %endif + XLDR x0, [ptr+pos] ;Get next source vector + + movdqa xtmpa, x0 ;Keep unshifted copy of src + psraw x0, 4 ;Shift to put high nibble into bits 4-0 + pand x0, xmask0f ;Mask high src nibble in bits 4-0 + pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 + + pshufb xgft1_hi, x0 ;Lookup mul table of high nibble + pshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft1_hi, xgft1_lo ;GF add high and low partials + pxor xp1, xgft1_hi ;xp1 += partial + + %ifidn PS,4 ;32-bit code + movdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} + movdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} + + add tmp, 32 + add vec_i, PS + %endif + pshufb xgft2_hi, x0 ;Lookup mul table of high nibble + pshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft2_hi, xgft2_lo ;GF add high and low partials + pxor xp2, xgft2_hi ;xp2 += partial + + cmp vec_i, vec + jl .next_vect + + SLDR dest1, dest1_m + SLDR dest2, dest2_m + XSTR [dest1+pos], xp1 + XSTR [dest2+pos], xp2 + + SLDR len, len_m + add pos, 16 ;Loop on 16 bytes at a time + cmp pos, len + jle .loop16 + + lea tmp, [len + 16] + cmp pos, tmp + je .return_pass + + ;; Tail len + mov pos, len ;Overlapped offset length-16 + jmp .loop16 ;Do one more overlap pass + +.return_pass: + mov return, 0 + FUNC_RESTORE + ret + +.return_fail: + mov return, 1 + FUNC_RESTORE + ret + +endproc_frame + +section .data + +align 16 +mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_2VECT_DOT_PROD_SSE, 00, 03, 0062 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_2vect_mad_avx.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_2vect_mad_avx.asm new file mode 100644 index 000000000..9542e7e6b --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_2vect_mad_avx.asm @@ -0,0 +1,264 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_2vect_mad_avx(len, vec, vec_i, mul_array, src, dest); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_2VECT_MAD_AVX _gf_2vect_mad_avx +%else + %define GF_2VECT_MAD_AVX gf_2vect_mad_avx +%endif + +%define PS 8 + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg0.w ecx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + %define arg4 r12 + %define arg5 r15 + %define tmp r11 + %define tmp2 r10 + %define return rax + %define return.w eax + %define stack_size 16*9 + 3*8 + %define arg(x) [rsp + stack_size + PS + PS*x] + %define func(x) proc_frame x + +%macro FUNC_SAVE 0 + sub rsp, stack_size + movdqa [rsp+16*0],xmm6 + movdqa [rsp+16*1],xmm7 + movdqa [rsp+16*2],xmm8 + movdqa [rsp+16*3],xmm9 + movdqa [rsp+16*4],xmm10 + movdqa [rsp+16*5],xmm11 + movdqa [rsp+16*6],xmm12 + movdqa [rsp+16*7],xmm13 + movdqa [rsp+16*8],xmm14 + save_reg r12, 9*16 + 0*8 + save_reg r15, 9*16 + 1*8 + end_prolog + mov arg4, arg(4) + mov arg5, arg(5) +%endmacro + +%macro FUNC_RESTORE 0 + movdqa xmm6, [rsp+16*0] + movdqa xmm7, [rsp+16*1] + movdqa xmm8, [rsp+16*2] + movdqa xmm9, [rsp+16*3] + movdqa xmm10, [rsp+16*4] + movdqa xmm11, [rsp+16*5] + movdqa xmm12, [rsp+16*6] + movdqa xmm13, [rsp+16*7] + movdqa xmm14, [rsp+16*8] + mov r12, [rsp + 9*16 + 0*8] + mov r15, [rsp + 9*16 + 1*8] + add rsp, stack_size +%endmacro + +%elifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define tmp2 r10 + %define return rax + %define return.w eax + + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%elifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define tmp2 r10 + %define return rax + %define return.w eax + + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%endif + +;;; gf_2vect_mad_avx(len, vec, vec_i, mul_array, src, dest) +%define len arg0 +%define len.w arg0.w +%define vec arg1 +%define vec_i arg2 +%define mul_array arg3 +%define src arg4 +%define dest1 arg5 +%define pos return +%define pos.w return.w + +%define dest2 tmp2 + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR vmovdqu + %define XSTR vmovdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR vmovdqa + %define XSTR vmovdqa + %else + %define XLDR vmovntdqa + %define XSTR vmovntdq + %endif +%endif + + +default rel + +[bits 64] +section .text + +%define xmask0f xmm14 +%define xgft1_lo xmm13 +%define xgft1_hi xmm12 +%define xgft2_lo xmm11 +%define xgft2_hi xmm10 + +%define x0 xmm0 +%define xtmpa xmm1 +%define xtmph1 xmm2 +%define xtmpl1 xmm3 +%define xtmph2 xmm4 +%define xtmpl2 xmm5 +%define xd1 xmm6 +%define xd2 xmm7 +%define xtmpd1 xmm8 +%define xtmpd2 xmm9 + + +align 16 +global GF_2VECT_MAD_AVX:function + +func(GF_2VECT_MAD_AVX) + FUNC_SAVE + sub len, 16 + jl .return_fail + + xor pos, pos + vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + sal vec_i, 5 ;Multiply by 32 + sal vec, 5 + lea tmp, [mul_array + vec_i] + vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, Ax{02}, ... + vmovdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} + vmovdqu xgft2_lo, [tmp+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... + vmovdqu xgft2_hi, [tmp+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} + + mov dest2, [dest1+PS] + mov dest1, [dest1] + + XLDR xtmpd1, [dest1+len] ;backup the last 16 bytes in dest + XLDR xtmpd2, [dest2+len] ;backup the last 16 bytes in dest + +.loop16 + XLDR xd1, [dest1+pos] ;Get next dest vector + XLDR xd2, [dest2+pos] ;Get next dest vector +.loop16_overlap: + XLDR x0, [src+pos] ;Get next source vector + + vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + + vpshufb xtmph1, xgft1_hi, x0 ;Lookup mul table of high nibble + vpshufb xtmpl1, xgft1_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph1, xtmph1, xtmpl1 ;GF add high and low partials + vpxor xd1, xd1, xtmph1 ;xd1 += partial + + vpshufb xtmph2, xgft2_hi, x0 ;Lookup mul table of high nibble + vpshufb xtmpl2, xgft2_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph2, xtmph2, xtmpl2 ;GF add high and low partials + vpxor xd2, xd2, xtmph2 ;xd2 += partial + + XSTR [dest1+pos], xd1 + XSTR [dest2+pos], xd2 + + add pos, 16 ;Loop on 16 bytes at a time + cmp pos, len + jle .loop16 + + lea tmp, [len + 16] + cmp pos, tmp + je .return_pass + + ;; Tail len + mov pos, len ;Overlapped offset length-16 + vmovdqa xd1, xtmpd1 ;Restore xd1 + vmovdqa xd2, xtmpd2 ;Restore xd2 + jmp .loop16_overlap ;Do one more overlap pass + +.return_pass: + mov return, 0 + FUNC_RESTORE + ret + +.return_fail: + mov return, 1 + FUNC_RESTORE + ret + +endproc_frame + +section .data + +align 16 +mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_2VECT_MAD_AVX, 02, 00, 0204 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_2vect_mad_avx2.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_2vect_mad_avx2.asm new file mode 100644 index 000000000..a6a2253ea --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_2vect_mad_avx2.asm @@ -0,0 +1,280 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_2vect_mad_avx2(len, vec, vec_i, mul_array, src, dest); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_2VECT_MAD_AVX2 _gf_2vect_mad_avx2 +%else + %define GF_2VECT_MAD_AVX2 gf_2vect_mad_avx2 +%endif + +%define PS 8 + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg0.w ecx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + %define arg4 r12 + %define arg5 r15 + + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define return rax + %define return.w eax + %define stack_size 16*9 + 3*8 ; must be an odd multiple of 8 + %define arg(x) [rsp + stack_size + PS + PS*x] + + %define func(x) proc_frame x + %macro FUNC_SAVE 0 + sub rsp, stack_size + vmovdqa [rsp+16*0],xmm6 + vmovdqa [rsp+16*1],xmm7 + vmovdqa [rsp+16*2],xmm8 + vmovdqa [rsp+16*3],xmm9 + vmovdqa [rsp+16*4],xmm10 + vmovdqa [rsp+16*5],xmm11 + vmovdqa [rsp+16*6],xmm12 + vmovdqa [rsp+16*7],xmm13 + vmovdqa [rsp+16*8],xmm14 + save_reg r12, 9*16 + 0*8 + save_reg r15, 9*16 + 1*8 + end_prolog + mov arg4, arg(4) + mov arg5, arg(5) + %endmacro + + %macro FUNC_RESTORE 0 + vmovdqa xmm6, [rsp+16*0] + vmovdqa xmm7, [rsp+16*1] + vmovdqa xmm8, [rsp+16*2] + vmovdqa xmm9, [rsp+16*3] + vmovdqa xmm10, [rsp+16*4] + vmovdqa xmm11, [rsp+16*5] + vmovdqa xmm12, [rsp+16*6] + vmovdqa xmm13, [rsp+16*7] + vmovdqa xmm14, [rsp+16*8] + mov r12, [rsp + 9*16 + 0*8] + mov r15, [rsp + 9*16 + 1*8] + add rsp, stack_size + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define return rax + %define return.w eax + + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%endif + +%ifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define return rax + %define return.w eax + + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%endif + +;;; gf_2vect_mad_avx2(len, vec, vec_i, mul_array, src, dest) +%define len arg0 +%define len.w arg0.w +%define vec arg1 +%define vec_i arg2 +%define mul_array arg3 +%define src arg4 +%define dest1 arg5 +%define pos return +%define pos.w return.w + +%define dest2 tmp2 + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR vmovdqu + %define XSTR vmovdqu +%else + +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR vmovdqa + %define XSTR vmovdqa + %else + %define XLDR vmovntdqa + %define XSTR vmovntdq + %endif +%endif + + +default rel + +[bits 64] +section .text + +%define xmask0f ymm14 +%define xmask0fx xmm14 +%define xgft1_lo ymm13 +%define xgft1_hi ymm12 +%define xgft2_lo ymm11 +%define xgft2_hi ymm10 + +%define x0 ymm0 +%define xtmpa ymm1 +%define xtmph1 ymm2 +%define xtmpl1 ymm3 +%define xtmph2 ymm4 +%define xtmpl2 ymm5 +%define xd1 ymm6 +%define xd2 ymm7 +%define xtmpd1 ymm8 +%define xtmpd2 ymm9 + +align 16 +global GF_2VECT_MAD_AVX2:function + +func(GF_2VECT_MAD_AVX2) + FUNC_SAVE + sub len, 32 + jl .return_fail + xor pos, pos + mov tmp.b, 0x0f + vpinsrb xmask0fx, xmask0fx, tmp.w, 0 + vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f... + + sal vec_i, 5 ;Multiply by 32 + sal vec, 5 + lea tmp, [mul_array + vec_i] + vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} + ; " Ax{00}, Ax{10}, ..., Ax{f0} + vmovdqu xgft2_lo, [tmp+vec] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} + ; " Bx{00}, Bx{10}, ..., Bx{f0} + + vperm2i128 xgft1_hi, xgft1_lo, xgft1_lo, 0x11 ; swapped to hi | hi + vperm2i128 xgft1_lo, xgft1_lo, xgft1_lo, 0x00 ; swapped to lo | lo + vperm2i128 xgft2_hi, xgft2_lo, xgft2_lo, 0x11 ; swapped to hi | hi + vperm2i128 xgft2_lo, xgft2_lo, xgft2_lo, 0x00 ; swapped to lo | lo + mov dest2, [dest1+PS] ; reuse mul_array + mov dest1, [dest1] + + XLDR xtmpd1, [dest1+len] ;backup the last 16 bytes in dest + XLDR xtmpd2, [dest2+len] ;backup the last 16 bytes in dest + +.loop32 + XLDR xd1, [dest1+pos] ;Get next dest vector + XLDR xd2, [dest2+pos] ;Get next dest vector +.loop32_overlap: + XLDR x0, [src+pos] ;Get next source vector + + vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + + vpshufb xtmph1, xgft1_hi, x0 ;Lookup mul table of high nibble + vpshufb xtmpl1, xgft1_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph1, xtmph1, xtmpl1 ;GF add high and low partials + vpxor xd1, xd1, xtmph1 ;xd1 += partial + + vpshufb xtmph2, xgft2_hi, x0 ;Lookup mul table of high nibble + vpshufb xtmpl2, xgft2_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph2, xtmph2, xtmpl2 ;GF add high and low partials + vpxor xd2, xd2, xtmph2 ;xd2 += partial + + XSTR [dest1+pos], xd1 + XSTR [dest2+pos], xd2 + + add pos, 32 ;Loop on 32 bytes at a time + cmp pos, len + jle .loop32 + + lea tmp, [len + 32] + cmp pos, tmp + je .return_pass + + ;; Tail len + mov pos, len ;Overlapped offset length-32 + vmovdqa xd1, xtmpd1 ;Restore xd1 + vmovdqa xd2, xtmpd2 ;Restore xd2 + jmp .loop32_overlap ;Do one more overlap pass + +.return_pass: + mov return, 0 + FUNC_RESTORE + ret + +.return_fail: + mov return, 1 + FUNC_RESTORE + ret + +endproc_frame + +section .data + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_2VECT_MAD_AVX2, 04, 00, 0205 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_2vect_mad_sse.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_2vect_mad_sse.asm new file mode 100644 index 000000000..af1b0c0d5 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_2vect_mad_sse.asm @@ -0,0 +1,267 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_2vect_mad_sse(len, vec, vec_i, mul_array, src, dest); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_2VECT_MAD_SSE _gf_2vect_mad_sse +%else + %define GF_2VECT_MAD_SSE gf_2vect_mad_sse +%endif + +%define PS 8 + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg0.w ecx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + %define arg4 r12 + %define arg5 r15 + %define tmp r11 + %define tmp2 r10 + %define return rax + %define return.w eax + %define stack_size 16*9 + 3*8 + %define arg(x) [rsp + stack_size + PS + PS*x] + %define func(x) proc_frame x + +%macro FUNC_SAVE 0 + sub rsp, stack_size + movdqa [rsp+16*0],xmm6 + movdqa [rsp+16*1],xmm7 + movdqa [rsp+16*2],xmm8 + movdqa [rsp+16*3],xmm9 + movdqa [rsp+16*4],xmm10 + movdqa [rsp+16*5],xmm11 + movdqa [rsp+16*6],xmm12 + movdqa [rsp+16*7],xmm13 + movdqa [rsp+16*8],xmm14 + save_reg r12, 9*16 + 0*8 + save_reg r15, 9*16 + 1*8 + end_prolog + mov arg4, arg(4) + mov arg5, arg(5) +%endmacro + +%macro FUNC_RESTORE 0 + movdqa xmm6, [rsp+16*0] + movdqa xmm7, [rsp+16*1] + movdqa xmm8, [rsp+16*2] + movdqa xmm9, [rsp+16*3] + movdqa xmm10, [rsp+16*4] + movdqa xmm11, [rsp+16*5] + movdqa xmm12, [rsp+16*6] + movdqa xmm13, [rsp+16*7] + movdqa xmm14, [rsp+16*8] + mov r12, [rsp + 9*16 + 0*8] + mov r15, [rsp + 9*16 + 1*8] + add rsp, stack_size +%endmacro + +%elifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define tmp2 r10 + %define return rax + %define return.w eax + + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%elifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define tmp2 r10 + %define return rax + %define return.w eax + + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%endif + +;;; gf_2vect_mad_sse(len, vec, vec_i, mul_array, src, dest) +%define len arg0 +%define len.w arg0.w +%define vec arg1 +%define vec_i arg2 +%define mul_array arg3 +%define src arg4 +%define dest1 arg5 +%define pos return +%define pos.w return.w + +%define dest2 tmp2 + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR movdqu + %define XSTR movdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR movdqa + %define XSTR movdqa + %else + %define XLDR movntdqa + %define XSTR movntdq + %endif +%endif + +default rel + +[bits 64] +section .text + +%define xmask0f xmm14 +%define xgft1_lo xmm13 +%define xgft1_hi xmm12 +%define xgft2_lo xmm11 +%define xgft2_hi xmm10 + +%define x0 xmm0 +%define xtmpa xmm1 +%define xtmph1 xmm2 +%define xtmpl1 xmm3 +%define xtmph2 xmm4 +%define xtmpl2 xmm5 +%define xd1 xmm6 +%define xd2 xmm7 +%define xtmpd1 xmm8 +%define xtmpd2 xmm9 + + +align 16 +global GF_2VECT_MAD_SSE:function +func(GF_2VECT_MAD_SSE) + FUNC_SAVE + sub len, 16 + jl .return_fail + + xor pos, pos + movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + sal vec_i, 5 ;Multiply by 32 + sal vec, 5 + lea tmp, [mul_array + vec_i] + movdqu xgft1_lo,[tmp] ;Load array Ax{00}, Ax{01}, Ax{02}, ... + movdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} + movdqu xgft2_lo, [tmp+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... + movdqu xgft2_hi, [tmp+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} + mov dest2, [dest1+PS] + mov dest1, [dest1] + + XLDR xtmpd1, [dest1+len] ;backup the last 16 bytes in dest + XLDR xtmpd2, [dest2+len] ;backup the last 16 bytes in dest + +.loop16: + XLDR xd1, [dest1+pos] ;Get next dest vector + XLDR xd2, [dest2+pos] ;Get next dest vector +.loop16_overlap: + XLDR x0, [src+pos] ;Get next source vector + movdqa xtmph1, xgft1_hi ;Reload const array registers + movdqa xtmpl1, xgft1_lo + movdqa xtmph2, xgft2_hi ;Reload const array registers + movdqa xtmpl2, xgft2_lo + movdqa xtmpa, x0 ;Keep unshifted copy of src + psraw x0, 4 ;Shift to put high nibble into bits 4-0 + pand x0, xmask0f ;Mask high src nibble in bits 4-0 + pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 + + pshufb xtmph1, x0 ;Lookup mul table of high nibble + pshufb xtmpl1, xtmpa ;Lookup mul table of low nibble + pxor xtmph1, xtmpl1 ;GF add high and low partials + pxor xd1, xtmph1 + + pshufb xtmph2, x0 ;Lookup mul table of high nibble + pshufb xtmpl2, xtmpa ;Lookup mul table of low nibble + pxor xtmph2, xtmpl2 ;GF add high and low partials + pxor xd2, xtmph2 + + XSTR [dest1+pos], xd1 ;Store result + XSTR [dest2+pos], xd2 ;Store result + + add pos, 16 ;Loop on 16 bytes at a time + cmp pos, len + jle .loop16 + + lea tmp, [len + 16] + cmp pos, tmp + je .return_pass + + ;; Tail len + mov pos, len ;Overlapped offset length-16 + movdqa xd1, xtmpd1 ;Restore xd1 + movdqa xd2, xtmpd2 ;Restore xd2 + jmp .loop16_overlap ;Do one more overlap pass + +.return_pass: + FUNC_RESTORE + mov return, 0 + ret + +.return_fail: + FUNC_RESTORE + mov return, 1 + ret + +endproc_frame + +section .data + +align 16 + +mask0f: + ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_2VECT_MAD_SSE, 00, 00, 0203 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_3vect_dot_prod_avx.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_3vect_dot_prod_avx.asm new file mode 100644 index 000000000..70a468f25 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_3vect_dot_prod_avx.asm @@ -0,0 +1,421 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_3vect_dot_prod_avx(len, vec, *g_tbls, **buffs, **dests); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_3VECT_DOT_PROD_AVX _gf_3vect_dot_prod_avx +%else + %define GF_3VECT_DOT_PROD_AVX gf_3vect_dot_prod_avx +%endif + +%ifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r12 ; must be saved and restored + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + %endmacro + %macro FUNC_RESTORE 0 + pop r13 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r12 ; must be saved and restored + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + %endmacro + %macro FUNC_RESTORE 0 + pop r13 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + + %define arg4 r12 ; must be saved, loaded and restored + %define arg5 r15 ; must be saved and restored + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r14 ; must be saved and restored + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define LOG_PS 3 + %define stack_size 6*16 + 5*8 ; must be an odd multiple of 8 + %define arg(x) [rsp + stack_size + PS + PS*x] + + %define func(x) proc_frame x + %macro FUNC_SAVE 0 + alloc_stack stack_size + save_xmm128 xmm6, 0*16 + save_xmm128 xmm7, 1*16 + save_xmm128 xmm8, 2*16 + save_xmm128 xmm9, 3*16 + save_xmm128 xmm10, 4*16 + save_xmm128 xmm11, 5*16 + save_reg r12, 6*16 + 0*8 + save_reg r13, 6*16 + 1*8 + save_reg r14, 6*16 + 2*8 + save_reg r15, 6*16 + 3*8 + end_prolog + mov arg4, arg(4) + %endmacro + + %macro FUNC_RESTORE 0 + vmovdqa xmm6, [rsp + 0*16] + vmovdqa xmm7, [rsp + 1*16] + vmovdqa xmm8, [rsp + 2*16] + vmovdqa xmm9, [rsp + 3*16] + vmovdqa xmm10, [rsp + 4*16] + vmovdqa xmm11, [rsp + 5*16] + mov r12, [rsp + 6*16 + 0*8] + mov r13, [rsp + 6*16 + 1*8] + mov r14, [rsp + 6*16 + 2*8] + mov r15, [rsp + 6*16 + 3*8] + add rsp, stack_size + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, elf32 + +;;;================== High Address; +;;; arg4 +;;; arg3 +;;; arg2 +;;; arg1 +;;; arg0 +;;; return +;;;<================= esp of caller +;;; ebp +;;;<================= ebp = esp +;;; var0 +;;; var1 +;;; esi +;;; edi +;;; ebx +;;;<================= esp of callee +;;; +;;;================== Low Address; + + %define PS 4 + %define LOG_PS 2 + %define func(x) x: + %define arg(x) [ebp + PS*2 + PS*x] + %define var(x) [ebp - PS - PS*x] + + %define trans ecx + %define trans2 esi + %define arg0 trans ;trans and trans2 are for the variables in stack + %define arg0_m arg(0) + %define arg1 ebx + %define arg2 arg2_m + %define arg2_m arg(2) + %define arg3 trans + %define arg3_m arg(3) + %define arg4 trans + %define arg4_m arg(4) + %define arg5 trans2 + %define tmp edx + %define tmp2 edi + %define tmp3 trans2 + %define tmp3_m var(0) + %define tmp4 trans2 + %define tmp4_m var(1) + %define return eax + %macro SLDR 2 ;; stack load/restore + mov %1, %2 + %endmacro + %define SSTR SLDR + + %macro FUNC_SAVE 0 + push ebp + mov ebp, esp + sub esp, PS*2 ;2 local variables + push esi + push edi + push ebx + mov arg1, arg(1) + %endmacro + + %macro FUNC_RESTORE 0 + pop ebx + pop edi + pop esi + add esp, PS*2 ;2 local variables + pop ebp + %endmacro + +%endif ; output formats + +%define len arg0 +%define vec arg1 +%define mul_array arg2 +%define src arg3 +%define dest1 arg4 +%define ptr arg5 + +%define vec_i tmp2 +%define dest2 tmp3 +%define dest3 tmp4 +%define pos return + + %ifidn PS,4 ;32-bit code + %define len_m arg0_m + %define src_m arg3_m + %define dest1_m arg4_m + %define dest2_m tmp3_m + %define dest3_m tmp4_m + %endif + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR vmovdqu + %define XSTR vmovdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR vmovdqa + %define XSTR vmovdqa + %else + %define XLDR vmovntdqa + %define XSTR vmovntdq + %endif +%endif + +%ifidn PS,8 ; 64-bit code + default rel + [bits 64] +%endif + + +section .text + +%ifidn PS,8 ;64-bit code + %define xmask0f xmm11 + %define xgft1_lo xmm10 + %define xgft1_hi xmm9 + %define xgft2_lo xmm8 + %define xgft2_hi xmm7 + %define xgft3_lo xmm6 + %define xgft3_hi xmm5 + + %define x0 xmm0 + %define xtmpa xmm1 + %define xp1 xmm2 + %define xp2 xmm3 + %define xp3 xmm4 +%else + %define xmask0f xmm7 + %define xgft1_lo xmm6 + %define xgft1_hi xmm5 + %define xgft2_lo xgft1_lo + %define xgft2_hi xgft1_hi + %define xgft3_lo xgft1_lo + %define xgft3_hi xgft1_hi + + %define x0 xmm0 + %define xtmpa xmm1 + %define xp1 xmm2 + %define xp2 xmm3 + %define xp3 xmm4 +%endif + +align 16 +global GF_3VECT_DOT_PROD_AVX:function +func(GF_3VECT_DOT_PROD_AVX) + FUNC_SAVE + SLDR len, len_m + sub len, 16 + SSTR len_m, len + jl .return_fail + xor pos, pos + vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS + SLDR dest1, dest1_m + mov dest2, [dest1+PS] + SSTR dest2_m, dest2 + mov dest3, [dest1+2*PS] + SSTR dest3_m, dest3 + mov dest1, [dest1] + SSTR dest1_m, dest1 + +.loop16: + vpxor xp1, xp1 + vpxor xp2, xp2 + vpxor xp3, xp3 + mov tmp, mul_array + xor vec_i, vec_i + +.next_vect: + SLDR src, src_m + mov ptr, [src+vec_i] + + vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} + vmovdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, ..., Ax{f0} + %ifidn PS,8 ; 64-bit code + vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} + vmovdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} + vmovdqu xgft3_lo, [tmp+vec*(64/PS)] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} + vmovdqu xgft3_hi, [tmp+vec*(64/PS)+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} + add tmp, 32 + add vec_i, PS + %endif + XLDR x0, [ptr+pos] ;Get next source vector + + vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + + vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft1_hi, xgft1_lo ;GF add high and low partials + vpxor xp1, xgft1_hi ;xp1 += partial + + %ifidn PS,4 ; 32-bit code + vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} + vmovdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} + %endif + vpshufb xgft2_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft2_hi, xgft2_lo ;GF add high and low partials + vpxor xp2, xgft2_hi ;xp2 += partial + + %ifidn PS,4 ; 32-bit code + sal vec, 1 + vmovdqu xgft3_lo, [tmp+vec*(32/PS)] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} + vmovdqu xgft3_hi, [tmp+vec*(32/PS)+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} + sar vec, 1 + add tmp, 32 + add vec_i, PS + %endif + vpshufb xgft3_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft3_hi, xgft3_lo ;GF add high and low partials + vpxor xp3, xgft3_hi ;xp3 += partial + + cmp vec_i, vec + jl .next_vect + + SLDR dest1, dest1_m + SLDR dest2, dest2_m + XSTR [dest1+pos], xp1 + XSTR [dest2+pos], xp2 + SLDR dest3, dest3_m + XSTR [dest3+pos], xp3 + + SLDR len, len_m + add pos, 16 ;Loop on 16 bytes at a time + cmp pos, len + jle .loop16 + + lea tmp, [len + 16] + cmp pos, tmp + je .return_pass + + ;; Tail len + mov pos, len ;Overlapped offset length-16 + jmp .loop16 ;Do one more overlap pass + +.return_pass: + mov return, 0 + FUNC_RESTORE + ret + +.return_fail: + mov return, 1 + FUNC_RESTORE + ret + +endproc_frame + +section .data + +align 16 +mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_3VECT_DOT_PROD_AVX, 02, 04, 0192 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_3vect_dot_prod_avx2.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_3vect_dot_prod_avx2.asm new file mode 100644 index 000000000..469a41098 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_3vect_dot_prod_avx2.asm @@ -0,0 +1,441 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_3vect_dot_prod_avx2(len, vec, *g_tbls, **buffs, **dests); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_3VECT_DOT_PROD_AVX2 _gf_3vect_dot_prod_avx2 +%else + %define GF_3VECT_DOT_PROD_AVX2 gf_3vect_dot_prod_avx2 +%endif + +%ifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r12 ; must be saved and restored + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + %endmacro + %macro FUNC_RESTORE 0 + pop r13 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r12 ; must be saved and restored + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + %endmacro + %macro FUNC_RESTORE 0 + pop r13 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + + %define arg4 r12 ; must be saved, loaded and restored + %define arg5 r15 ; must be saved and restored + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r14 ; must be saved and restored + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define LOG_PS 3 + %define stack_size 6*16 + 5*8 ; must be an odd multiple of 8 + %define arg(x) [rsp + stack_size + PS + PS*x] + + %define func(x) proc_frame x + %macro FUNC_SAVE 0 + alloc_stack stack_size + vmovdqa [rsp + 0*16], xmm6 + vmovdqa [rsp + 1*16], xmm7 + vmovdqa [rsp + 2*16], xmm8 + vmovdqa [rsp + 3*16], xmm9 + vmovdqa [rsp + 4*16], xmm10 + vmovdqa [rsp + 5*16], xmm11 + save_reg r12, 6*16 + 0*8 + save_reg r13, 6*16 + 1*8 + save_reg r14, 6*16 + 2*8 + save_reg r15, 6*16 + 3*8 + end_prolog + mov arg4, arg(4) + %endmacro + + %macro FUNC_RESTORE 0 + vmovdqa xmm6, [rsp + 0*16] + vmovdqa xmm7, [rsp + 1*16] + vmovdqa xmm8, [rsp + 2*16] + vmovdqa xmm9, [rsp + 3*16] + vmovdqa xmm10, [rsp + 4*16] + vmovdqa xmm11, [rsp + 5*16] + mov r12, [rsp + 6*16 + 0*8] + mov r13, [rsp + 6*16 + 1*8] + mov r14, [rsp + 6*16 + 2*8] + mov r15, [rsp + 6*16 + 3*8] + add rsp, stack_size + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, elf32 + +;;;================== High Address; +;;; arg4 +;;; arg3 +;;; arg2 +;;; arg1 +;;; arg0 +;;; return +;;;<================= esp of caller +;;; ebp +;;;<================= ebp = esp +;;; var0 +;;; var1 +;;; esi +;;; edi +;;; ebx +;;;<================= esp of callee +;;; +;;;================== Low Address; + + %define PS 4 + %define LOG_PS 2 + %define func(x) x: + %define arg(x) [ebp + PS*2 + PS*x] + %define var(x) [ebp - PS - PS*x] + + %define trans ecx + %define trans2 esi + %define arg0 trans ;trans and trans2 are for the variables in stack + %define arg0_m arg(0) + %define arg1 ebx + %define arg2 arg2_m + %define arg2_m arg(2) + %define arg3 trans + %define arg3_m arg(3) + %define arg4 trans + %define arg4_m arg(4) + %define arg5 trans2 + %define tmp edx + %define tmp.w edx + %define tmp.b dl + %define tmp2 edi + %define tmp3 trans2 + %define tmp3_m var(0) + %define tmp4 trans2 + %define tmp4_m var(1) + %define return eax + %macro SLDR 2 ;stack load/restore + mov %1, %2 + %endmacro + %define SSTR SLDR + + %macro FUNC_SAVE 0 + push ebp + mov ebp, esp + sub esp, PS*2 ;2 local variables + push esi + push edi + push ebx + mov arg1, arg(1) + %endmacro + + %macro FUNC_RESTORE 0 + pop ebx + pop edi + pop esi + add esp, PS*2 ;2 local variables + pop ebp + %endmacro + +%endif ; output formats + +%define len arg0 +%define vec arg1 +%define mul_array arg2 +%define src arg3 +%define dest1 arg4 +%define ptr arg5 + +%define vec_i tmp2 +%define dest2 tmp3 +%define dest3 tmp4 +%define pos return + +%ifidn PS,4 ;32-bit code + %define len_m arg0_m + %define src_m arg3_m + %define dest1_m arg4_m + %define dest2_m tmp3_m + %define dest3_m tmp4_m +%endif + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR vmovdqu + %define XSTR vmovdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR vmovdqa + %define XSTR vmovdqa + %else + %define XLDR vmovntdqa + %define XSTR vmovntdq + %endif +%endif + +%ifidn PS,8 ;64-bit code + default rel + [bits 64] +%endif + +section .text + +%ifidn PS,8 ;64-bit code + %define xmask0f ymm11 + %define xmask0fx xmm11 + %define xgft1_lo ymm10 + %define xgft1_hi ymm9 + %define xgft2_lo ymm8 + %define xgft2_hi ymm7 + %define xgft3_lo ymm6 + %define xgft3_hi ymm5 + + %define x0 ymm0 + %define xtmpa ymm1 + %define xp1 ymm2 + %define xp2 ymm3 + %define xp3 ymm4 +%else + %define xmask0f ymm7 + %define xmask0fx xmm7 + %define xgft1_lo ymm6 + %define xgft1_hi ymm5 + %define xgft2_lo xgft1_lo + %define xgft2_hi xgft1_hi + %define xgft3_lo xgft1_lo + %define xgft3_hi xgft1_hi + + %define x0 ymm0 + %define xtmpa ymm1 + %define xp1 ymm2 + %define xp2 ymm3 + %define xp3 ymm4 + +%endif + +align 16 +global GF_3VECT_DOT_PROD_AVX2:function +func(GF_3VECT_DOT_PROD_AVX2) + FUNC_SAVE + SLDR len, len_m + sub len, 32 + SSTR len_m, len + jl .return_fail + xor pos, pos + mov tmp.b, 0x0f + vpinsrb xmask0fx, xmask0fx, tmp.w, 0 + vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f... + + sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS + SLDR dest1, dest1_m + mov dest2, [dest1+PS] + SSTR dest2_m, dest2 + mov dest3, [dest1+2*PS] + SSTR dest3_m, dest3 + mov dest1, [dest1] + SSTR dest1_m, dest1 + +.loop32: + vpxor xp1, xp1 + vpxor xp2, xp2 + vpxor xp3, xp3 + mov tmp, mul_array + xor vec_i, vec_i + +.next_vect: + SLDR src, src_m + mov ptr, [src+vec_i] + + vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} + ; " Ax{00}, Ax{10}, ..., Ax{f0} + vperm2i128 xgft1_hi, xgft1_lo, xgft1_lo, 0x11 ; swapped to hi | hi + vperm2i128 xgft1_lo, xgft1_lo, xgft1_lo, 0x00 ; swapped to lo | lo + %ifidn PS,8 ; 64-bit code + vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} + ; " Bx{00}, Bx{10}, ..., Bx{f0} + vperm2i128 xgft2_hi, xgft2_lo, xgft2_lo, 0x11 ; swapped to hi | hi + vperm2i128 xgft2_lo, xgft2_lo, xgft2_lo, 0x00 ; swapped to lo | lo + + vmovdqu xgft3_lo, [tmp+vec*(64/PS)] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} + ; " Cx{00}, Cx{10}, ..., Cx{f0} + vperm2i128 xgft3_hi, xgft3_lo, xgft3_lo, 0x11 ; swapped to hi | hi + vperm2i128 xgft3_lo, xgft3_lo, xgft3_lo, 0x00 ; swapped to lo | lo + + add tmp, 32 + add vec_i, PS + %endif + XLDR x0, [ptr+pos] ;Get next source vector + + vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + + vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft1_hi, xgft1_lo ;GF add high and low partials + vpxor xp1, xgft1_hi ;xp1 += partial + + %ifidn PS,4 ; 32-bit code + vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} + ; " Bx{00}, Bx{10}, ..., Bx{f0} + vperm2i128 xgft2_hi, xgft2_lo, xgft2_lo, 0x11 ; swapped to hi | hi + vperm2i128 xgft2_lo, xgft2_lo, xgft2_lo, 0x00 ; swapped to lo | lo + %endif + vpshufb xgft2_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft2_hi, xgft2_lo ;GF add high and low partials + vpxor xp2, xgft2_hi ;xp2 += partial + + %ifidn PS,4 ; 32-bit code + sal vec, 1 + vmovdqu xgft3_lo, [tmp+vec*(32/PS)] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} + ; " Cx{00}, Cx{10}, ..., Cx{f0} + vperm2i128 xgft3_hi, xgft3_lo, xgft3_lo, 0x11 ; swapped to hi | hi + vperm2i128 xgft3_lo, xgft3_lo, xgft3_lo, 0x00 ; swapped to lo | lo + sar vec, 1 + add tmp, 32 + add vec_i, PS + %endif + vpshufb xgft3_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft3_hi, xgft3_lo ;GF add high and low partials + vpxor xp3, xgft3_hi ;xp3 += partial + + cmp vec_i, vec + jl .next_vect + + SLDR dest1, dest1_m + SLDR dest2, dest2_m + XSTR [dest1+pos], xp1 + XSTR [dest2+pos], xp2 + SLDR dest3, dest3_m + XSTR [dest3+pos], xp3 + + SLDR len, len_m + add pos, 32 ;Loop on 32 bytes at a time + cmp pos, len + jle .loop32 + + lea tmp, [len + 32] + cmp pos, tmp + je .return_pass + + ;; Tail len + mov pos, len ;Overlapped offset length-16 + jmp .loop32 ;Do one more overlap pass + +.return_pass: + mov return, 0 + FUNC_RESTORE + ret + +.return_fail: + mov return, 1 + FUNC_RESTORE + ret + +endproc_frame + +section .data + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_3VECT_DOT_PROD_AVX2, 04, 04, 0197 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_3vect_dot_prod_sse.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_3vect_dot_prod_sse.asm new file mode 100644 index 000000000..bd0ae4f5f --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_3vect_dot_prod_sse.asm @@ -0,0 +1,422 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_3vect_dot_prod_sse(len, vec, *g_tbls, **buffs, **dests); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_3VECT_DOT_PROD_SSE _gf_3vect_dot_prod_sse +%else + %define GF_3VECT_DOT_PROD_SSE gf_3vect_dot_prod_sse +%endif + +%ifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r12 ; must be saved and restored + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + %endmacro + %macro FUNC_RESTORE 0 + pop r13 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r12 ; must be saved and restored + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + %endmacro + %macro FUNC_RESTORE 0 + pop r13 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + + %define arg4 r12 ; must be saved, loaded and restored + %define arg5 r15 ; must be saved and restored + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r14 ; must be saved and restored + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define LOG_PS 3 + %define stack_size 6*16 + 5*8 ; must be an odd multiple of 8 + %define arg(x) [rsp + stack_size + PS + PS*x] + + %define func(x) proc_frame x + %macro FUNC_SAVE 0 + alloc_stack stack_size + save_xmm128 xmm6, 0*16 + save_xmm128 xmm7, 1*16 + save_xmm128 xmm8, 2*16 + save_xmm128 xmm9, 3*16 + save_xmm128 xmm10, 4*16 + save_xmm128 xmm11, 5*16 + save_reg r12, 6*16 + 0*8 + save_reg r13, 6*16 + 1*8 + save_reg r14, 6*16 + 2*8 + save_reg r15, 6*16 + 3*8 + end_prolog + mov arg4, arg(4) + %endmacro + + %macro FUNC_RESTORE 0 + movdqa xmm6, [rsp + 0*16] + movdqa xmm7, [rsp + 1*16] + movdqa xmm8, [rsp + 2*16] + movdqa xmm9, [rsp + 3*16] + movdqa xmm10, [rsp + 4*16] + movdqa xmm11, [rsp + 5*16] + mov r12, [rsp + 6*16 + 0*8] + mov r13, [rsp + 6*16 + 1*8] + mov r14, [rsp + 6*16 + 2*8] + mov r15, [rsp + 6*16 + 3*8] + add rsp, stack_size + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, elf32 + +;;;================== High Address; +;;; arg4 +;;; arg3 +;;; arg2 +;;; arg1 +;;; arg0 +;;; return +;;;<================= esp of caller +;;; ebp +;;;<================= ebp = esp +;;; var0 +;;; var1 +;;; esi +;;; edi +;;; ebx +;;;<================= esp of callee +;;; +;;;================== Low Address; + + %define PS 4 + %define LOG_PS 2 + %define func(x) x: + %define arg(x) [ebp + PS*2 + PS*x] + %define var(x) [ebp - PS - PS*x] + + %define trans ecx + %define trans2 esi + %define arg0 trans ;trans and trans2 are for the variables in stack + %define arg0_m arg(0) + %define arg1 ebx + %define arg2 arg2_m + %define arg2_m arg(2) + %define arg3 trans + %define arg3_m arg(3) + %define arg4 trans + %define arg4_m arg(4) + %define arg5 trans2 + %define tmp edx + %define tmp2 edi + %define tmp3 trans2 + %define tmp3_m var(0) + %define tmp4 trans2 + %define tmp4_m var(1) + %define return eax + %macro SLDR 2 ;; stack load/restore + mov %1, %2 + %endmacro + %define SSTR SLDR + + %macro FUNC_SAVE 0 + push ebp + mov ebp, esp + sub esp, PS*2 ;2 local variables + push esi + push edi + push ebx + mov arg1, arg(1) + %endmacro + + %macro FUNC_RESTORE 0 + pop ebx + pop edi + pop esi + add esp, PS*2 ;2 local variables + pop ebp + %endmacro + +%endif ; output formats + +%define len arg0 +%define vec arg1 +%define mul_array arg2 +%define src arg3 +%define dest1 arg4 +%define ptr arg5 + +%define vec_i tmp2 +%define dest2 tmp3 +%define dest3 tmp4 +%define pos return + + %ifidn PS,4 ;32-bit code + %define len_m arg0_m + %define src_m arg3_m + %define dest1_m arg4_m + %define dest2_m tmp3_m + %define dest3_m tmp4_m + %endif + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR movdqu + %define XSTR movdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR movdqa + %define XSTR movdqa + %else + %define XLDR movntdqa + %define XSTR movntdq + %endif +%endif + +%ifidn PS,8 ; 64-bit code + default rel + [bits 64] +%endif + + +section .text + +%ifidn PS,8 ;64-bit code + %define xmask0f xmm11 + %define xgft1_lo xmm2 + %define xgft1_hi xmm3 + %define xgft2_lo xmm4 + %define xgft2_hi xmm7 + %define xgft3_lo xmm6 + %define xgft3_hi xmm5 + + %define x0 xmm0 + %define xtmpa xmm1 + %define xp1 xmm10 + %define xp2 xmm9 + %define xp3 xmm8 +%else + %define xmask0f xmm7 + %define xgft1_lo xmm6 + %define xgft1_hi xmm5 + %define xgft2_lo xgft1_lo + %define xgft2_hi xgft1_hi + %define xgft3_lo xgft1_lo + %define xgft3_hi xgft1_hi + + %define x0 xmm0 + %define xtmpa xmm1 + %define xp1 xmm2 + %define xp2 xmm3 + %define xp3 xmm4 +%endif + +align 16 +global GF_3VECT_DOT_PROD_SSE:function +func(GF_3VECT_DOT_PROD_SSE) + FUNC_SAVE + SLDR len, len_m + sub len, 16 + SSTR len_m, len + jl .return_fail + xor pos, pos + movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS + SLDR dest1, dest1_m + mov dest2, [dest1+PS] + SSTR dest2_m, dest2 + mov dest3, [dest1+2*PS] + SSTR dest3_m, dest3 + mov dest1, [dest1] + SSTR dest1_m, dest1 + +.loop16: + pxor xp1, xp1 + pxor xp2, xp2 + pxor xp3, xp3 + mov tmp, mul_array + xor vec_i, vec_i + +.next_vect: + SLDR src, src_m + mov ptr, [src+vec_i] + + movdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} + movdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, ..., Ax{f0} + %ifidn PS,8 ;64-bit code + movdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} + movdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} + movdqu xgft3_lo, [tmp+vec*(64/PS)] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} + movdqu xgft3_hi, [tmp+vec*(64/PS)+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} + add tmp, 32 + add vec_i, PS + %endif + XLDR x0, [ptr+pos] ;Get next source vector + + movdqa xtmpa, x0 ;Keep unshifted copy of src + psraw x0, 4 ;Shift to put high nibble into bits 4-0 + pand x0, xmask0f ;Mask high src nibble in bits 4-0 + pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 + + pshufb xgft1_hi, x0 ;Lookup mul table of high nibble + pshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft1_hi, xgft1_lo ;GF add high and low partials + pxor xp1, xgft1_hi ;xp1 += partial + + %ifidn PS,4 ;32-bit code + movdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} + movdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} + %endif + pshufb xgft2_hi, x0 ;Lookup mul table of high nibble + pshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft2_hi, xgft2_lo ;GF add high and low partials + pxor xp2, xgft2_hi ;xp2 += partial + + %ifidn PS,4 ;32-bit code + sal vec, 1 + movdqu xgft3_lo, [tmp+vec*(32/PS)] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} + movdqu xgft3_hi, [tmp+vec*(32/PS)+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} + sar vec, 1 + add tmp, 32 + add vec_i, PS + %endif + pshufb xgft3_hi, x0 ;Lookup mul table of high nibble + pshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft3_hi, xgft3_lo ;GF add high and low partials + pxor xp3, xgft3_hi ;xp3 += partial + + cmp vec_i, vec + jl .next_vect + + SLDR dest1, dest1_m + SLDR dest2, dest2_m + XSTR [dest1+pos], xp1 + XSTR [dest2+pos], xp2 + SLDR dest3, dest3_m + XSTR [dest3+pos], xp3 + + SLDR len, len_m + add pos, 16 ;Loop on 16 bytes at a time + cmp pos, len + jle .loop16 + + lea tmp, [len + 16] + cmp pos, tmp + je .return_pass + + ;; Tail len + mov pos, len ;Overlapped offset length-16 + jmp .loop16 ;Do one more overlap pass + +.return_pass: + mov return, 0 + FUNC_RESTORE + ret + +.return_fail: + mov return, 1 + FUNC_RESTORE + ret + +endproc_frame + +section .data + +align 16 +mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_3VECT_DOT_PROD_SSE, 00, 05, 0063 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_3vect_mad_avx.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_3vect_mad_avx.asm new file mode 100644 index 000000000..f3cabd68e --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_3vect_mad_avx.asm @@ -0,0 +1,315 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_3vect_mad_avx(len, vec, vec_i, mul_array, src, dest); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_3VECT_MAD_AVX _gf_3vect_mad_avx +%else + %define GF_3VECT_MAD_AVX gf_3vect_mad_avx +%endif + +%define PS 8 + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg0.w ecx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + %define arg4 r12 + %define arg5 r15 + %define tmp r11 + %define return rax + %define return.w eax + %define stack_size 16*10 + 3*8 + %define arg(x) [rsp + stack_size + PS + PS*x] + %define func(x) proc_frame x + +%macro FUNC_SAVE 0 + sub rsp, stack_size + vmovdqa [rsp+16*0],xmm6 + vmovdqa [rsp+16*1],xmm7 + vmovdqa [rsp+16*2],xmm8 + vmovdqa [rsp+16*3],xmm9 + vmovdqa [rsp+16*4],xmm10 + vmovdqa [rsp+16*5],xmm11 + vmovdqa [rsp+16*6],xmm12 + vmovdqa [rsp+16*7],xmm13 + vmovdqa [rsp+16*8],xmm14 + vmovdqa [rsp+16*9],xmm15 + save_reg r12, 10*16 + 0*8 + save_reg r15, 10*16 + 1*8 + end_prolog + mov arg4, arg(4) + mov arg5, arg(5) +%endmacro + +%macro FUNC_RESTORE 0 + vmovdqa xmm6, [rsp+16*0] + vmovdqa xmm7, [rsp+16*1] + vmovdqa xmm8, [rsp+16*2] + vmovdqa xmm9, [rsp+16*3] + vmovdqa xmm10, [rsp+16*4] + vmovdqa xmm11, [rsp+16*5] + vmovdqa xmm12, [rsp+16*6] + vmovdqa xmm13, [rsp+16*7] + vmovdqa xmm14, [rsp+16*8] + vmovdqa xmm15, [rsp+16*9] + mov r12, [rsp + 10*16 + 0*8] + mov r15, [rsp + 10*16 + 1*8] + add rsp, stack_size +%endmacro + +%elifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define return rax + %define return.w eax + + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%elifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define return rax + %define return.w eax + + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%endif + +;;; gf_3vect_mad_avx(len, vec, vec_i, mul_array, src, dest) +%define len arg0 +%define len.w arg0.w +%define vec arg1 +%define vec_i arg2 +%define mul_array arg3 +%define src arg4 +%define dest1 arg5 +%define pos return +%define pos.w return.w + +%define dest2 mul_array +%define dest3 vec_i + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR vmovdqu + %define XSTR vmovdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR vmovdqa + %define XSTR vmovdqa + %else + %define XLDR vmovntdqa + %define XSTR vmovntdq + %endif +%endif + + +default rel + +[bits 64] +section .text + +%define xmask0f xmm15 +%define xgft1_lo xmm14 +%define xgft1_hi xmm13 +%define xgft2_lo xmm12 +%define xgft2_hi xmm11 +%define xgft3_lo xmm10 +%define xgft3_hi xmm9 + +%define x0 xmm0 +%define xtmpa xmm1 +%define xtmph1 xmm2 +%define xtmpl1 xmm3 +%define xtmph2 xmm4 +%define xtmpl2 xmm5 +%define xtmph3 xmm6 +%define xtmpl3 xmm7 +%define xd1 xmm8 +%define xd2 xtmpl1 +%define xd3 xtmph1 + +align 16 +global GF_3VECT_MAD_AVX:function +func(GF_3VECT_MAD_AVX) + FUNC_SAVE + sub len, 16 + jl .return_fail + xor pos, pos + vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + + sal vec_i, 5 ;Multiply by 32 + sal vec, 5 + lea tmp, [mul_array + vec_i] + vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, Ax{02}, ... + vmovdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} + vmovdqu xgft2_lo, [tmp+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... + vmovdqu xgft2_hi, [tmp+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} + vmovdqu xgft3_lo, [tmp+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... + vmovdqu xgft3_hi, [tmp+2*vec+16]; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} + mov dest2, [dest1+PS] ; reuse mul_array + mov dest3, [dest1+2*PS] ; reuse vec_i + mov dest1, [dest1] + +.loop16: + XLDR x0, [src+pos] ;Get next source vector + XLDR xd1, [dest1+pos] ;Get next dest vector + + vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + + ; dest1 + vpshufb xtmph1, xgft1_hi, x0 ;Lookup mul table of high nibble + vpshufb xtmpl1, xgft1_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph1, xtmph1, xtmpl1 ;GF add high and low partials + vpxor xd1, xd1, xtmph1 ;xd1 += partial + + XLDR xd2, [dest2+pos] ;reuse xtmpl1. Get next dest vector + XLDR xd3, [dest3+pos] ;reuse xtmph1. Get next dest vector + + ; dest2 + vpshufb xtmph2, xgft2_hi, x0 ;Lookup mul table of high nibble + vpshufb xtmpl2, xgft2_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph2, xtmph2, xtmpl2 ;GF add high and low partials + vpxor xd2, xd2, xtmph2 ;xd2 += partial + + ; dest3 + vpshufb xtmph3, xgft3_hi, x0 ;Lookup mul table of high nibble + vpshufb xtmpl3, xgft3_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph3, xtmph3, xtmpl3 ;GF add high and low partials + vpxor xd3, xd3, xtmph3 ;xd3 += partial + + XSTR [dest1+pos], xd1 + XSTR [dest2+pos], xd2 + XSTR [dest3+pos], xd3 + + add pos, 16 ;Loop on 16 bytes at a time + cmp pos, len + jle .loop16 + + lea tmp, [len + 16] + cmp pos, tmp + je .return_pass + +.lessthan16: + ;; Tail len + ;; Do one more overlap pass + mov tmp, len ;Overlapped offset length-16 + XLDR x0, [src+tmp] ;Get next source vector + XLDR xd1, [dest1+tmp] ;Get next dest vector + XLDR xd2, [dest2+tmp] ;reuse xtmpl1. Get next dest vector + XLDR xd3, [dest3+tmp] ;reuse xtmph1. Get next dest vector + + sub len, pos + + movdqa xtmph3, [constip16] ;Load const of i + 16 + vpinsrb xtmpl3, xtmpl3, len.w, 15 + vpshufb xtmpl3, xtmpl3, xmask0f ;Broadcast len to all bytes + vpcmpgtb xtmpl3, xtmpl3, xtmph3 + + vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + + ; dest1 + vpshufb xgft1_hi, xgft1_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft1_lo, xgft1_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft1_hi, xgft1_hi, xgft1_lo ;GF add high and low partials + vpand xgft1_hi, xgft1_hi, xtmpl3 + vpxor xd1, xd1, xgft1_hi + + ; dest2 + vpshufb xgft2_hi, xgft2_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft2_lo, xgft2_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft2_hi, xgft2_hi, xgft2_lo ;GF add high and low partials + vpand xgft2_hi, xgft2_hi, xtmpl3 + vpxor xd2, xd2, xgft2_hi + + ; dest3 + vpshufb xgft3_hi, xgft3_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft3_lo, xgft3_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft3_hi, xgft3_hi, xgft3_lo ;GF add high and low partials + vpand xgft3_hi, xgft3_hi, xtmpl3 + vpxor xd3, xd3, xgft3_hi + + XSTR [dest1+tmp], xd1 + XSTR [dest2+tmp], xd2 + XSTR [dest3+tmp], xd3 + +.return_pass: + mov return, 0 + FUNC_RESTORE + ret + +.return_fail: + mov return, 1 + FUNC_RESTORE + ret + +endproc_frame + +section .data + +align 16 +mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f +constip16: + ddq 0xf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_3VECT_MAD_AVX, 02, 00, 0207 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_3vect_mad_avx2.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_3vect_mad_avx2.asm new file mode 100644 index 000000000..092538000 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_3vect_mad_avx2.asm @@ -0,0 +1,347 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_3vect_mad_avx2(len, vec, vec_i, mul_array, src, dest); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_3VECT_MAD_AVX2 _gf_3vect_mad_avx2 +%else + %define GF_3VECT_MAD_AVX2 gf_3vect_mad_avx2 +%endif + +%define PS 8 + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg0.w ecx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + %define arg4 r12 ; must be saved, loaded and restored + %define arg5 r15 ; must be saved and restored + + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define return rax + %define return.w eax + %define stack_size 16*10 + 3*8 + %define arg(x) [rsp + stack_size + PS + PS*x] + %define func(x) proc_frame x + + %macro FUNC_SAVE 0 + sub rsp, stack_size + vmovdqa [rsp+16*0],xmm6 + vmovdqa [rsp+16*1],xmm7 + vmovdqa [rsp+16*2],xmm8 + vmovdqa [rsp+16*3],xmm9 + vmovdqa [rsp+16*4],xmm10 + vmovdqa [rsp+16*5],xmm11 + vmovdqa [rsp+16*6],xmm12 + vmovdqa [rsp+16*7],xmm13 + vmovdqa [rsp+16*8],xmm14 + vmovdqa [rsp+16*9],xmm15 + save_reg r12, 10*16 + 0*8 + save_reg r15, 10*16 + 1*8 + end_prolog + mov arg4, arg(4) + mov arg5, arg(5) + %endmacro + + %macro FUNC_RESTORE 0 + vmovdqa xmm6, [rsp+16*0] + vmovdqa xmm7, [rsp+16*1] + vmovdqa xmm8, [rsp+16*2] + vmovdqa xmm9, [rsp+16*3] + vmovdqa xmm10, [rsp+16*4] + vmovdqa xmm11, [rsp+16*5] + vmovdqa xmm12, [rsp+16*6] + vmovdqa xmm13, [rsp+16*7] + vmovdqa xmm14, [rsp+16*8] + vmovdqa xmm15, [rsp+16*9] + mov r12, [rsp + 10*16 + 0*8] + mov r15, [rsp + 10*16 + 1*8] + add rsp, stack_size + %endmacro + +%elifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define return rax + %define return.w eax + + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%elifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define return rax + %define return.w eax + + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%endif + +;;; gf_3vect_mad_avx2(len, vec, vec_i, mul_array, src, dest) +%define len arg0 +%define len.w arg0.w +%define vec arg1 +%define vec_i arg2 +%define mul_array arg3 +%define src arg4 +%define dest1 arg5 +%define pos return +%define pos.w return.w + +%define dest2 mul_array +%define dest3 vec_i + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR vmovdqu + %define XSTR vmovdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR vmovdqa + %define XSTR vmovdqa + %else + %define XLDR vmovntdqa + %define XSTR vmovntdq + %endif +%endif + + +default rel + +[bits 64] +section .text + +%define xmask0f ymm15 +%define xmask0fx xmm15 +%define xgft1_lo ymm14 +%define xgft1_hi ymm13 +%define xgft2_lo ymm12 +%define xgft3_lo ymm11 + +%define x0 ymm0 +%define xtmpa ymm1 +%define xtmph1 ymm2 +%define xtmpl1 ymm3 +%define xtmph2 ymm4 +%define xtmpl2 ymm5 +%define xtmpl2x xmm5 +%define xtmph3 ymm6 +%define xtmpl3 ymm7 +%define xtmpl3x xmm7 +%define xd1 ymm8 +%define xd2 ymm9 +%define xd3 ymm10 + +align 16 +global GF_3VECT_MAD_AVX2:function +func(GF_3VECT_MAD_AVX2) + FUNC_SAVE + sub len, 32 + jl .return_fail + xor pos, pos + mov tmp.b, 0x0f + vpinsrb xmask0fx, xmask0fx, tmp.w, 0 + vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f... + + sal vec_i, 5 ;Multiply by 32 + sal vec, 5 + lea tmp, [mul_array + vec_i] + + vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} + ; " Ax{00}, Ax{10}, ..., Ax{f0} + vperm2i128 xgft1_hi, xgft1_lo, xgft1_lo, 0x11 ; swapped to hi | hi + vperm2i128 xgft1_lo, xgft1_lo, xgft1_lo, 0x00 ; swapped to lo | lo + + vmovdqu xgft2_lo, [tmp+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... + ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} + vmovdqu xgft3_lo, [tmp+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... + ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} + mov dest2, [dest1+PS] ; reuse mul_array + mov dest3, [dest1+2*PS] ; reuse vec_i + mov dest1, [dest1] + +.loop32: + XLDR x0, [src+pos] ;Get next source vector + XLDR xd1, [dest1+pos] ;Get next dest vector + XLDR xd2, [dest2+pos] ;Get next dest vector + XLDR xd3, [dest3+pos] ;Get next dest vector + vperm2i128 xtmph2, xgft2_lo, xgft2_lo, 0x11 ; swapped to hi | hi + vperm2i128 xtmpl2, xgft2_lo, xgft2_lo, 0x00 ; swapped to lo | lo + + vperm2i128 xtmph3, xgft3_lo, xgft3_lo, 0x11 ; swapped to hi | hi + vperm2i128 xtmpl3, xgft3_lo, xgft3_lo, 0x00 ; swapped to lo | lo + + vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + + ; dest1 + vpshufb xtmph1, xgft1_hi, x0 ;Lookup mul table of high nibble + vpshufb xtmpl1, xgft1_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph1, xtmph1, xtmpl1 ;GF add high and low partials + vpxor xd1, xd1, xtmph1 ;xd1 += partial + + ; dest2 + vpshufb xtmph2, x0 ;Lookup mul table of high nibble + vpshufb xtmpl2, xtmpa ;Lookup mul table of low nibble + vpxor xtmph2, xtmpl2 ;GF add high and low partials + vpxor xd2, xtmph2 ;xd2 += partial + + ; dest3 + vpshufb xtmph3, x0 ;Lookup mul table of high nibble + vpshufb xtmpl3, xtmpa ;Lookup mul table of low nibble + vpxor xtmph3, xtmpl3 ;GF add high and low partials + vpxor xd3, xtmph3 ;xd3 += partial + + XSTR [dest1+pos], xd1 + XSTR [dest2+pos], xd2 + XSTR [dest3+pos], xd3 + + add pos, 32 ;Loop on 32 bytes at a time + cmp pos, len + jle .loop32 + + lea tmp, [len + 32] + cmp pos, tmp + je .return_pass + +.lessthan32: + ;; Tail len + ;; Do one more overlap pass + mov tmp.b, 0x1f + vpinsrb xtmpl2x, xtmpl2x, tmp.w, 0 + vpbroadcastb xtmpl2, xtmpl2x ;Construct mask 0x1f1f1f... + + mov tmp, len ;Overlapped offset length-32 + + XLDR x0, [src+tmp] ;Get next source vector + XLDR xd1, [dest1+tmp] ;Get next dest vector + XLDR xd2, [dest2+tmp] ;Get next dest vector + XLDR xd3, [dest3+tmp] ;Get next dest vector + + sub len, pos + + vmovdqa xtmph3, [constip32] ;Load const of i + 32 + vpinsrb xtmpl3x, xtmpl3x, len.w, 15 + vinserti128 xtmpl3, xtmpl3, xtmpl3x, 1 ;swapped to xtmpl3x | xtmpl3x + vpshufb xtmpl3, xtmpl3, xtmpl2 ;Broadcast len to all bytes. xtmpl2=0x1f1f1f... + vpcmpgtb xtmpl3, xtmpl3, xtmph3 + + vperm2i128 xtmph2, xgft2_lo, xgft2_lo, 0x11 ; swapped to hi | hi + vperm2i128 xgft2_lo, xgft2_lo, xgft2_lo, 0x00 ; swapped to lo | lo + + vperm2i128 xtmph3, xgft3_lo, xgft3_lo, 0x11 ; swapped to hi | hi + vperm2i128 xgft3_lo, xgft3_lo, xgft3_lo, 0x00 ; swapped to lo | lo + + vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + + ; dest1 + vpshufb xtmph1, xgft1_hi, x0 ;Lookup mul table of high nibble + vpshufb xtmpl1, xgft1_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph1, xtmph1, xtmpl1 ;GF add high and low partials + vpand xtmph1, xtmph1, xtmpl3 + vpxor xd1, xd1, xtmph1 ;xd1 += partial + + ; dest2 + vpshufb xtmph2, xtmph2, x0 ;Lookup mul table of high nibble + vpshufb xgft2_lo, xgft2_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph2, xtmph2, xgft2_lo ;GF add high and low partials + vpand xtmph2, xtmph2, xtmpl3 + vpxor xd2, xd2, xtmph2 ;xd2 += partial + + ; dest3 + vpshufb xtmph3, xtmph3, x0 ;Lookup mul table of high nibble + vpshufb xgft3_lo, xgft3_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph3, xtmph3, xgft3_lo ;GF add high and low partials + vpand xtmph3, xtmph3, xtmpl3 + vpxor xd3, xd3, xtmph3 ;xd3 += partial + + XSTR [dest1+tmp], xd1 + XSTR [dest2+tmp], xd2 + XSTR [dest3+tmp], xd3 + +.return_pass: + mov return, 0 + FUNC_RESTORE + ret + +.return_fail: + mov return, 1 + FUNC_RESTORE + ret + +endproc_frame + +section .data + +align 32 +constip32: + ddq 0xf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff + ddq 0xe0e1e2e3e4e5e6e7e8e9eaebecedeeef + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_3VECT_MAD_AVX2, 04, 00, 0208 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_3vect_mad_sse.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_3vect_mad_sse.asm new file mode 100644 index 000000000..c011eba8a --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_3vect_mad_sse.asm @@ -0,0 +1,326 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_3vect_mad_sse(len, vec, vec_i, mul_array, src, dest); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_3VECT_MAD_SSE _gf_3vect_mad_sse +%else + %define GF_3VECT_MAD_SSE gf_3vect_mad_sse +%endif + +%define PS 8 + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg0.w ecx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + %define arg4 r12 + %define arg5 r15 + %define tmp r11 + %define return rax + %define return.w eax + %define stack_size 16*10 + 3*8 + %define arg(x) [rsp + stack_size + PS + PS*x] + %define func(x) proc_frame x + +%macro FUNC_SAVE 0 + sub rsp, stack_size + movdqa [rsp+16*0],xmm6 + movdqa [rsp+16*1],xmm7 + movdqa [rsp+16*2],xmm8 + movdqa [rsp+16*3],xmm9 + movdqa [rsp+16*4],xmm10 + movdqa [rsp+16*5],xmm11 + movdqa [rsp+16*6],xmm12 + movdqa [rsp+16*7],xmm13 + movdqa [rsp+16*8],xmm14 + movdqa [rsp+16*9],xmm15 + save_reg r12, 10*16 + 0*8 + save_reg r15, 10*16 + 1*8 + end_prolog + mov arg4, arg(4) + mov arg5, arg(5) +%endmacro + +%macro FUNC_RESTORE 0 + movdqa xmm6, [rsp+16*0] + movdqa xmm7, [rsp+16*1] + movdqa xmm8, [rsp+16*2] + movdqa xmm9, [rsp+16*3] + movdqa xmm10, [rsp+16*4] + movdqa xmm11, [rsp+16*5] + movdqa xmm12, [rsp+16*6] + movdqa xmm13, [rsp+16*7] + movdqa xmm14, [rsp+16*8] + movdqa xmm15, [rsp+16*9] + mov r12, [rsp + 10*16 + 0*8] + mov r15, [rsp + 10*16 + 1*8] + add rsp, stack_size +%endmacro + +%elifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define return rax + %define return.w eax + + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%elifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define return rax + %define return.w eax + + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%endif + +;;; gf_3vect_mad_sse(len, vec, vec_i, mul_array, src, dest) +%define len arg0 +%define len.w arg0.w +%define vec arg1 +%define vec_i arg2 +%define mul_array arg3 +%define src arg4 +%define dest1 arg5 +%define pos return +%define pos.w return.w + +%define dest2 mul_array +%define dest3 vec_i + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR movdqu + %define XSTR movdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR movdqa + %define XSTR movdqa + %else + %define XLDR movntdqa + %define XSTR movntdq + %endif +%endif + +default rel + +[bits 64] +section .text + +%define xmask0f xmm15 +%define xgft1_lo xmm14 +%define xgft1_hi xmm13 +%define xgft2_lo xmm12 +%define xgft2_hi xmm11 +%define xgft3_lo xmm10 +%define xgft3_hi xmm9 + +%define x0 xmm0 +%define xtmpa xmm1 +%define xtmph1 xmm2 +%define xtmpl1 xmm3 +%define xtmph2 xmm4 +%define xtmpl2 xmm5 +%define xtmph3 xmm6 +%define xtmpl3 xmm7 +%define xd1 xmm8 +%define xd2 xtmpl1 +%define xd3 xtmph1 + +align 16 +global GF_3VECT_MAD_SSE:function +func(GF_3VECT_MAD_SSE) + FUNC_SAVE + sub len, 16 + jl .return_fail + xor pos, pos + movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + sal vec_i, 5 ;Multiply by 32 + sal vec, 5 + lea tmp, [mul_array + vec_i] + + movdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, Ax{02}, ... + movdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} + movdqu xgft2_lo, [tmp+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... + movdqu xgft2_hi, [tmp+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} + movdqu xgft3_lo, [tmp+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... + movdqu xgft3_hi, [tmp+2*vec+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} + mov dest2, [dest1+PS] ; reuse mul_array + mov dest3, [dest1+2*PS] ; reuse vec_i + mov dest1, [dest1] + +.loop16: + XLDR x0, [src+pos] ;Get next source vector + movdqa xtmph1, xgft1_hi ;Reload const array registers + movdqa xtmpl1, xgft1_lo + movdqa xtmph2, xgft2_hi ;Reload const array registers + movdqa xtmpl2, xgft2_lo + movdqa xtmph3, xgft3_hi ;Reload const array registers + movdqa xtmpl3, xgft3_lo + + XLDR xd1, [dest1+pos] ;Get next dest vector + + movdqa xtmpa, x0 ;Keep unshifted copy of src + psraw x0, 4 ;Shift to put high nibble into bits 4-0 + pand x0, xmask0f ;Mask high src nibble in bits 4-0 + pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 + + ; dest1 + pshufb xtmph1, x0 ;Lookup mul table of high nibble + pshufb xtmpl1, xtmpa ;Lookup mul table of low nibble + pxor xtmph1, xtmpl1 ;GF add high and low partials + pxor xd1, xtmph1 + + XLDR xd2, [dest2+pos] ;reuse xtmpl1. Get next dest vector + XLDR xd3, [dest3+pos] ;reuse xtmph1. Get next dest vector + + ; dest2 + pshufb xtmph2, x0 ;Lookup mul table of high nibble + pshufb xtmpl2, xtmpa ;Lookup mul table of low nibble + pxor xtmph2, xtmpl2 ;GF add high and low partials + pxor xd2, xtmph2 + + ; dest3 + pshufb xtmph3, x0 ;Lookup mul table of high nibble + pshufb xtmpl3, xtmpa ;Lookup mul table of low nibble + pxor xtmph3, xtmpl3 ;GF add high and low partials + pxor xd3, xtmph3 + + XSTR [dest1+pos], xd1 ;Store result + XSTR [dest2+pos], xd2 ;Store result + XSTR [dest3+pos], xd3 ;Store result + + add pos, 16 ;Loop on 16 bytes at a time + cmp pos, len + jle .loop16 + + lea tmp, [len + 16] + cmp pos, tmp + je .return_pass + +.lessthan16: + ;; Tail len + ;; Do one more overlap pass + mov tmp, len ;Overlapped offset length-16 + + XLDR x0, [src+tmp] ;Get next source vector + XLDR xd1, [dest1+tmp] ;Get next dest vector + XLDR xd2, [dest2+tmp] ;reuse xtmpl1. Get next dest vector + XLDR xd3, [dest3+tmp] ;reuse xtmph1. Get next dest vector + + sub len, pos + + movdqa xtmph3, [constip16] ;Load const of i + 16 + pinsrb xtmpl3, len.w, 15 + pshufb xtmpl3, xmask0f ;Broadcast len to all bytes + pcmpgtb xtmpl3, xtmph3 + + movdqa xtmpa, x0 ;Keep unshifted copy of src + psraw x0, 4 ;Shift to put high nibble into bits 4-0 + pand x0, xmask0f ;Mask high src nibble in bits 4-0 + pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 + + ; dest1 + pshufb xgft1_hi, x0 ;Lookup mul table of high nibble + pshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft1_hi, xgft1_lo ;GF add high and low partials + pand xgft1_hi, xtmpl3 + pxor xd1, xgft1_hi + + ; dest2 + pshufb xgft2_hi, x0 ;Lookup mul table of high nibble + pshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft2_hi, xgft2_lo ;GF add high and low partials + pand xgft2_hi, xtmpl3 + pxor xd2, xgft2_hi + + ; dest3 + pshufb xgft3_hi, x0 ;Lookup mul table of high nibble + pshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft3_hi, xgft3_lo ;GF add high and low partials + pand xgft3_hi, xtmpl3 + pxor xd3, xgft3_hi + + XSTR [dest1+tmp], xd1 ;Store result + XSTR [dest2+tmp], xd2 ;Store result + XSTR [dest3+tmp], xd3 ;Store result + +.return_pass: + FUNC_RESTORE + mov return, 0 + ret + +.return_fail: + FUNC_RESTORE + mov return, 1 + ret + +endproc_frame + +section .data + +align 16 + +mask0f: + ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f +constip16: + ddq 0xf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_3VECT_MAD_SSE, 00, 00, 0206 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_4vect_dot_prod_avx.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_4vect_dot_prod_avx.asm new file mode 100644 index 000000000..49c882948 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_4vect_dot_prod_avx.asm @@ -0,0 +1,489 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_4vect_dot_prod_avx(len, vec, *g_tbls, **buffs, **dests); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_4VECT_DOT_PROD_AVX _gf_4vect_dot_prod_avx +%else + %define GF_4VECT_DOT_PROD_AVX gf_4vect_dot_prod_avx +%endif + +%ifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r12 ; must be saved and restored + %define tmp5 r14 ; must be saved and restored + %define tmp6 r15 ; must be saved and restored + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + push r14 + push r15 + %endmacro + %macro FUNC_RESTORE 0 + pop r15 + pop r14 + pop r13 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r12 ; must be saved and restored + %define tmp5 r14 ; must be saved and restored + %define tmp6 r15 ; must be saved and restored + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + push r14 + push r15 + %endmacro + %macro FUNC_RESTORE 0 + pop r15 + pop r14 + pop r13 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + + %define arg4 r12 ; must be saved, loaded and restored + %define arg5 r15 ; must be saved and restored + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r14 ; must be saved and restored + %define tmp5 rdi ; must be saved and restored + %define tmp6 rsi ; must be saved and restored + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define LOG_PS 3 + %define stack_size 9*16 + 7*8 ; must be an odd multiple of 8 + %define arg(x) [rsp + stack_size + PS + PS*x] + + %define func(x) proc_frame x + %macro FUNC_SAVE 0 + alloc_stack stack_size + save_xmm128 xmm6, 0*16 + save_xmm128 xmm7, 1*16 + save_xmm128 xmm8, 2*16 + save_xmm128 xmm9, 3*16 + save_xmm128 xmm10, 4*16 + save_xmm128 xmm11, 5*16 + save_xmm128 xmm12, 6*16 + save_xmm128 xmm13, 7*16 + save_xmm128 xmm14, 8*16 + save_reg r12, 9*16 + 0*8 + save_reg r13, 9*16 + 1*8 + save_reg r14, 9*16 + 2*8 + save_reg r15, 9*16 + 3*8 + save_reg rdi, 9*16 + 4*8 + save_reg rsi, 9*16 + 5*8 + end_prolog + mov arg4, arg(4) + %endmacro + + %macro FUNC_RESTORE 0 + vmovdqa xmm6, [rsp + 0*16] + vmovdqa xmm7, [rsp + 1*16] + vmovdqa xmm8, [rsp + 2*16] + vmovdqa xmm9, [rsp + 3*16] + vmovdqa xmm10, [rsp + 4*16] + vmovdqa xmm11, [rsp + 5*16] + vmovdqa xmm12, [rsp + 6*16] + vmovdqa xmm13, [rsp + 7*16] + vmovdqa xmm14, [rsp + 8*16] + mov r12, [rsp + 9*16 + 0*8] + mov r13, [rsp + 9*16 + 1*8] + mov r14, [rsp + 9*16 + 2*8] + mov r15, [rsp + 9*16 + 3*8] + mov rdi, [rsp + 9*16 + 4*8] + mov rsi, [rsp + 9*16 + 5*8] + add rsp, stack_size + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, elf32 + +;;;================== High Address; +;;; arg4 +;;; arg3 +;;; arg2 +;;; arg1 +;;; arg0 +;;; return +;;;<================= esp of caller +;;; ebp +;;;<================= ebp = esp +;;; var0 +;;; var1 +;;; var2 +;;; var3 +;;; esi +;;; edi +;;; ebx +;;;<================= esp of callee +;;; +;;;================== Low Address; + + %define PS 4 + %define LOG_PS 2 + %define func(x) x: + %define arg(x) [ebp + PS*2 + PS*x] + %define var(x) [ebp - PS - PS*x] + + %define trans ecx + %define trans2 esi + %define arg0 trans ;trans and trans2 are for the variables in stack + %define arg0_m arg(0) + %define arg1 ebx + %define arg2 arg2_m + %define arg2_m arg(2) + %define arg3 trans + %define arg3_m arg(3) + %define arg4 trans + %define arg4_m arg(4) + %define arg5 trans2 + %define tmp edx + %define tmp2 edi + %define tmp3 trans2 + %define tmp3_m var(0) + %define tmp4 trans2 + %define tmp4_m var(1) + %define tmp5 trans2 + %define tmp5_m var(2) + %define tmp6 trans2 + %define tmp6_m var(3) + %define return eax + %macro SLDR 2 ;stack load/restore + mov %1, %2 + %endmacro + %define SSTR SLDR + + %macro FUNC_SAVE 0 + push ebp + mov ebp, esp + sub esp, PS*4 ;4 local variables + push esi + push edi + push ebx + mov arg1, arg(1) + %endmacro + + %macro FUNC_RESTORE 0 + pop ebx + pop edi + pop esi + add esp, PS*4 ;4 local variables + pop ebp + %endmacro + +%endif ; output formats + +%define len arg0 +%define vec arg1 +%define mul_array arg2 +%define src arg3 +%define dest1 arg4 +%define ptr arg5 +%define vec_i tmp2 +%define dest2 tmp3 +%define dest3 tmp4 +%define dest4 tmp5 +%define vskip3 tmp6 +%define pos return + + %ifidn PS,4 ;32-bit code + %define len_m arg0_m + %define src_m arg3_m + %define dest1_m arg4_m + %define dest2_m tmp3_m + %define dest3_m tmp4_m + %define dest4_m tmp5_m + %define vskip3_m tmp6_m + %endif + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR vmovdqu + %define XSTR vmovdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR vmovdqa + %define XSTR vmovdqa + %else + %define XLDR vmovntdqa + %define XSTR vmovntdq + %endif +%endif + +%ifidn PS,8 ; 64-bit code + default rel + [bits 64] +%endif + + +section .text + +%ifidn PS,8 ;64-bit code + %define xmask0f xmm14 + %define xgft1_lo xmm13 + %define xgft1_hi xmm12 + %define xgft2_lo xmm11 + %define xgft2_hi xmm10 + %define xgft3_lo xmm9 + %define xgft3_hi xmm8 + %define xgft4_lo xmm7 + %define xgft4_hi xmm6 + + %define x0 xmm0 + %define xtmpa xmm1 + %define xp1 xmm2 + %define xp2 xmm3 + %define xp3 xmm4 + %define xp4 xmm5 +%else + %define xmm_trans xmm7 ;reuse xmask0f and xgft1_lo + %define xmask0f xmm_trans + %define xgft1_lo xmm_trans + %define xgft1_hi xmm6 + %define xgft2_lo xgft1_lo + %define xgft2_hi xgft1_hi + %define xgft3_lo xgft1_lo + %define xgft3_hi xgft1_hi + %define xgft4_lo xgft1_lo + %define xgft4_hi xgft1_hi + + %define x0 xmm0 + %define xtmpa xmm1 + %define xp1 xmm2 + %define xp2 xmm3 + %define xp3 xmm4 + %define xp4 xmm5 +%endif +align 16 +global GF_4VECT_DOT_PROD_AVX:function +func(GF_4VECT_DOT_PROD_AVX) + FUNC_SAVE + SLDR len, len_m + sub len, 16 + SSTR len_m, len + jl .return_fail + xor pos, pos + vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + mov vskip3, vec + imul vskip3, 96 + SSTR vskip3_m, vskip3 + sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS + SLDR dest1, dest1_m + mov dest2, [dest1+PS] + SSTR dest2_m, dest2 + mov dest3, [dest1+2*PS] + SSTR dest3_m, dest3 + mov dest4, [dest1+3*PS] + SSTR dest4_m, dest4 + mov dest1, [dest1] + SSTR dest1_m, dest1 + +.loop16: + vpxor xp1, xp1 + vpxor xp2, xp2 + vpxor xp3, xp3 + vpxor xp4, xp4 + mov tmp, mul_array + xor vec_i, vec_i + +.next_vect: + SLDR src, src_m + mov ptr, [src+vec_i] + + %ifidn PS,8 ;64-bit code + vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} + vmovdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, ..., Ax{f0} + vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} + vmovdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} + vmovdqu xgft3_lo, [tmp+vec*(64/PS)] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} + vmovdqu xgft3_hi, [tmp+vec*(64/PS)+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} + vmovdqu xgft4_lo, [tmp+vskip3] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} + vmovdqu xgft4_hi, [tmp+vskip3+16] ; " Dx{00}, Dx{10}, ..., Dx{f0} + + XLDR x0, [ptr+pos] ;Get next source vector + add tmp, 32 + add vec_i, PS + + vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + %else ;32-bit code + XLDR x0, [ptr+pos] ;Get next source vector + vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + + vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + + vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} + vmovdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, ..., Ax{f0} + %endif + + vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft1_hi, xgft1_lo ;GF add high and low partials + vpxor xp1, xgft1_hi ;xp1 += partial + + %ifidn PS,4 ;32-bit code + vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} + vmovdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} + %endif + vpshufb xgft2_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft2_hi, xgft2_lo ;GF add high and low partials + vpxor xp2, xgft2_hi ;xp2 += partial + + %ifidn PS,4 ;32-bit code + sal vec, 1 + vmovdqu xgft3_lo, [tmp+vec*(32/PS)] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} + vmovdqu xgft3_hi, [tmp+vec*(32/PS)+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} + sar vec, 1 + %endif + vpshufb xgft3_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft3_hi, xgft3_lo ;GF add high and low partials + vpxor xp3, xgft3_hi ;xp3 += partial + + %ifidn PS,4 ;32-bit code + SLDR vskip3, vskip3_m + vmovdqu xgft4_lo, [tmp+vskip3] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} + vmovdqu xgft4_hi, [tmp+vskip3+16] ; " Dx{00}, Dx{10}, ..., Dx{f0} + add tmp, 32 + add vec_i, PS + %endif + vpshufb xgft4_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft4_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft4_hi, xgft4_lo ;GF add high and low partials + vpxor xp4, xgft4_hi ;xp4 += partial + + cmp vec_i, vec + jl .next_vect + + SLDR dest1, dest1_m + SLDR dest2, dest2_m + XSTR [dest1+pos], xp1 + XSTR [dest2+pos], xp2 + SLDR dest3, dest3_m + XSTR [dest3+pos], xp3 + SLDR dest4, dest4_m + XSTR [dest4+pos], xp4 + + SLDR len, len_m + add pos, 16 ;Loop on 16 bytes at a time + cmp pos, len + jle .loop16 + + lea tmp, [len + 16] + cmp pos, tmp + je .return_pass + + ;; Tail len + mov pos, len ;Overlapped offset length-16 + jmp .loop16 ;Do one more overlap pass + +.return_pass: + mov return, 0 + FUNC_RESTORE + ret + +.return_fail: + mov return, 1 + FUNC_RESTORE + ret + +endproc_frame + +section .data + +align 16 +mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_4VECT_DOT_PROD_AVX, 02, 04, 0193 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_4vect_dot_prod_avx2.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_4vect_dot_prod_avx2.asm new file mode 100644 index 000000000..7c835e0b1 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_4vect_dot_prod_avx2.asm @@ -0,0 +1,510 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_4vect_dot_prod_avx2(len, vec, *g_tbls, **buffs, **dests); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_4VECT_DOT_PROD_AVX2 _gf_4vect_dot_prod_avx2 +%else + %define GF_4VECT_DOT_PROD_AVX2 gf_4vect_dot_prod_avx2 +%endif + +%ifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r12 ; must be saved and restored + %define tmp5 r14 ; must be saved and restored + %define tmp6 r15 ; must be saved and restored + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + push r14 + push r15 + %endmacro + %macro FUNC_RESTORE 0 + pop r15 + pop r14 + pop r13 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r12 ; must be saved and restored + %define tmp5 r14 ; must be saved and restored + %define tmp6 r15 ; must be saved and restored + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + push r14 + push r15 + %endmacro + %macro FUNC_RESTORE 0 + pop r15 + pop r14 + pop r13 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + + %define arg4 r12 ; must be saved, loaded and restored + %define arg5 r15 ; must be saved and restored + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r14 ; must be saved and restored + %define tmp5 rdi ; must be saved and restored + %define tmp6 rsi ; must be saved and restored + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define LOG_PS 3 + %define stack_size 9*16 + 7*8 ; must be an odd multiple of 8 + %define arg(x) [rsp + stack_size + PS + PS*x] + + %define func(x) proc_frame x + %macro FUNC_SAVE 0 + alloc_stack stack_size + vmovdqa [rsp + 0*16], xmm6 + vmovdqa [rsp + 1*16], xmm7 + vmovdqa [rsp + 2*16], xmm8 + vmovdqa [rsp + 3*16], xmm9 + vmovdqa [rsp + 4*16], xmm10 + vmovdqa [rsp + 5*16], xmm11 + vmovdqa [rsp + 6*16], xmm12 + vmovdqa [rsp + 7*16], xmm13 + vmovdqa [rsp + 8*16], xmm14 + save_reg r12, 9*16 + 0*8 + save_reg r13, 9*16 + 1*8 + save_reg r14, 9*16 + 2*8 + save_reg r15, 9*16 + 3*8 + save_reg rdi, 9*16 + 4*8 + save_reg rsi, 9*16 + 5*8 + end_prolog + mov arg4, arg(4) + %endmacro + + %macro FUNC_RESTORE 0 + vmovdqa xmm6, [rsp + 0*16] + vmovdqa xmm7, [rsp + 1*16] + vmovdqa xmm8, [rsp + 2*16] + vmovdqa xmm9, [rsp + 3*16] + vmovdqa xmm10, [rsp + 4*16] + vmovdqa xmm11, [rsp + 5*16] + vmovdqa xmm12, [rsp + 6*16] + vmovdqa xmm13, [rsp + 7*16] + vmovdqa xmm14, [rsp + 8*16] + mov r12, [rsp + 9*16 + 0*8] + mov r13, [rsp + 9*16 + 1*8] + mov r14, [rsp + 9*16 + 2*8] + mov r15, [rsp + 9*16 + 3*8] + mov rdi, [rsp + 9*16 + 4*8] + mov rsi, [rsp + 9*16 + 5*8] + add rsp, stack_size + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, elf32 + +;;;================== High Address; +;;; arg4 +;;; arg3 +;;; arg2 +;;; arg1 +;;; arg0 +;;; return +;;;<================= esp of caller +;;; ebp +;;;<================= ebp = esp +;;; var0 +;;; var1 +;;; var2 +;;; var3 +;;; esi +;;; edi +;;; ebx +;;;<================= esp of callee +;;; +;;;================== Low Address; + + %define PS 4 + %define LOG_PS 2 + %define func(x) x: + %define arg(x) [ebp + PS*2 + PS*x] + %define var(x) [ebp - PS - PS*x] + + %define trans ecx + %define trans2 esi + %define arg0 trans ;trans and trans2 are for the variables in stack + %define arg0_m arg(0) + %define arg1 ebx + %define arg2 arg2_m + %define arg2_m arg(2) + %define arg3 trans + %define arg3_m arg(3) + %define arg4 trans + %define arg4_m arg(4) + %define arg5 trans2 + %define tmp edx + %define tmp.w edx + %define tmp.b dl + %define tmp2 edi + %define tmp3 trans2 + %define tmp3_m var(0) + %define tmp4 trans2 + %define tmp4_m var(1) + %define tmp5 trans2 + %define tmp5_m var(2) + %define tmp6 trans2 + %define tmp6_m var(3) + %define return eax + %macro SLDR 2 ;stack load/restore + mov %1, %2 + %endmacro + %define SSTR SLDR + + %macro FUNC_SAVE 0 + push ebp + mov ebp, esp + sub esp, PS*4 ;4 local variables + push esi + push edi + push ebx + mov arg1, arg(1) + %endmacro + + %macro FUNC_RESTORE 0 + pop ebx + pop edi + pop esi + add esp, PS*4 ;4 local variables + pop ebp + %endmacro + +%endif ; output formats + +%define len arg0 +%define vec arg1 +%define mul_array arg2 +%define src arg3 +%define dest1 arg4 +%define ptr arg5 +%define vec_i tmp2 +%define dest2 tmp3 +%define dest3 tmp4 +%define dest4 tmp5 +%define vskip3 tmp6 +%define pos return + + %ifidn PS,4 ;32-bit code + %define len_m arg0_m + %define src_m arg3_m + %define dest1_m arg4_m + %define dest2_m tmp3_m + %define dest3_m tmp4_m + %define dest4_m tmp5_m + %define vskip3_m tmp6_m + %endif + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR vmovdqu + %define XSTR vmovdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR vmovdqa + %define XSTR vmovdqa + %else + %define XLDR vmovntdqa + %define XSTR vmovntdq + %endif +%endif + +%ifidn PS,8 ;64-bit code + default rel + [bits 64] +%endif + + +section .text + +%ifidn PS,8 ;64-bit code + %define xmask0f ymm14 + %define xmask0fx xmm14 + %define xgft1_lo ymm13 + %define xgft1_hi ymm12 + %define xgft2_lo ymm11 + %define xgft2_hi ymm10 + %define xgft3_lo ymm9 + %define xgft3_hi ymm8 + %define xgft4_lo ymm7 + %define xgft4_hi ymm6 + + %define x0 ymm0 + %define xtmpa ymm1 + %define xp1 ymm2 + %define xp2 ymm3 + %define xp3 ymm4 + %define xp4 ymm5 +%else + %define ymm_trans ymm7 ;reuse xmask0f and xgft1_hi + %define xmask0f ymm_trans + %define xmask0fx xmm7 + %define xgft1_lo ymm6 + %define xgft1_hi ymm_trans + %define xgft2_lo xgft1_lo + %define xgft2_hi xgft1_hi + %define xgft3_lo xgft1_lo + %define xgft3_hi xgft1_hi + %define xgft4_lo xgft1_lo + %define xgft4_hi xgft1_hi + + %define x0 ymm0 + %define xtmpa ymm1 + %define xp1 ymm2 + %define xp2 ymm3 + %define xp3 ymm4 + %define xp4 ymm5 +%endif +align 16 +global GF_4VECT_DOT_PROD_AVX2:function +func(GF_4VECT_DOT_PROD_AVX2) + FUNC_SAVE + SLDR len, len_m + sub len, 32 + SSTR len_m, len + jl .return_fail + xor pos, pos + mov tmp.b, 0x0f + vpinsrb xmask0fx, xmask0fx, tmp.w, 0 + vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f... + mov vskip3, vec + imul vskip3, 96 + SSTR vskip3_m, vskip3 + sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS + SLDR dest1, dest1_m + mov dest2, [dest1+PS] + SSTR dest2_m, dest2 + mov dest3, [dest1+2*PS] + SSTR dest3_m, dest3 + mov dest4, [dest1+3*PS] + SSTR dest4_m, dest4 + mov dest1, [dest1] + SSTR dest1_m, dest1 + +.loop32: + vpxor xp1, xp1 + vpxor xp2, xp2 + vpxor xp3, xp3 + vpxor xp4, xp4 + mov tmp, mul_array + xor vec_i, vec_i + +.next_vect: + SLDR src, src_m + mov ptr, [src+vec_i] + XLDR x0, [ptr+pos] ;Get next source vector + + add vec_i, PS + %ifidn PS,8 ;64-bit code + vpand xgft4_lo, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + vperm2i128 xtmpa, xgft4_lo, x0, 0x30 ;swap xtmpa from 1lo|2lo to 1lo|2hi + vperm2i128 x0, xgft4_lo, x0, 0x12 ;swap x0 from 1hi|2hi to 1hi|2lo + + vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} + ; " Ax{00}, Ax{10}, ..., Ax{f0} + vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} + ; " Bx{00}, Bx{10}, ..., Bx{f0} + vmovdqu xgft3_lo, [tmp+vec*(64/PS)] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} + ; " Cx{00}, Cx{10}, ..., Cx{f0} + vmovdqu xgft4_lo, [tmp+vskip3] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} + ; " Dx{00}, Dx{10}, ..., Dx{f0} + + vperm2i128 xgft1_hi, xgft1_lo, xgft1_lo, 0x01 ; swapped to hi | lo + vperm2i128 xgft2_hi, xgft2_lo, xgft2_lo, 0x01 ; swapped to hi | lo + vperm2i128 xgft3_hi, xgft3_lo, xgft3_lo, 0x01 ; swapped to hi | lo + vperm2i128 xgft4_hi, xgft4_lo, xgft4_lo, 0x01 ; swapped to hi | lo + add tmp, 32 + %else ;32-bit code + mov cl, 0x0f ;use ecx as a temp variable + vpinsrb xmask0fx, xmask0fx, ecx, 0 + vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f... + + vpand xgft4_lo, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + vperm2i128 xtmpa, xgft4_lo, x0, 0x30 ;swap xtmpa from 1lo|2lo to 1lo|2hi + vperm2i128 x0, xgft4_lo, x0, 0x12 ;swap x0 from 1hi|2hi to 1hi|2lo + + vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} + ; " Ax{00}, Ax{10}, ..., Ax{f0} + vperm2i128 xgft1_hi, xgft1_lo, xgft1_lo, 0x01 ; swapped to hi | lo + %endif + + vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft1_hi, xgft1_lo ;GF add high and low partials + vpxor xp1, xgft1_hi ;xp1 += partial + + %ifidn PS,4 ; 32-bit code + vmovdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} + ; " Bx{00}, Bx{10}, ..., Bx{f0} + vperm2i128 xgft2_hi, xgft2_lo, xgft2_lo, 0x01 ; swapped to hi | lo + %endif + vpshufb xgft2_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft2_hi, xgft2_lo ;GF add high and low partials + vpxor xp2, xgft2_hi ;xp2 += partial + + %ifidn PS,4 ; 32-bit code + sal vec, 1 + vmovdqu xgft3_lo, [tmp+vec*(32/PS)] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} + ; " Cx{00}, Cx{10}, ..., Cx{f0} + vperm2i128 xgft3_hi, xgft3_lo, xgft3_lo, 0x01 ; swapped to hi | lo + sar vec, 1 + %endif + vpshufb xgft3_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft3_hi, xgft3_lo ;GF add high and low partials + vpxor xp3, xgft3_hi ;xp3 += partial + + %ifidn PS,4 ; 32-bit code + SLDR vskip3, vskip3_m + vmovdqu xgft4_lo, [tmp+vskip3] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} + ; " DX{00}, Dx{10}, ..., Dx{f0} + vperm2i128 xgft4_hi, xgft4_lo, xgft4_lo, 0x01 ; swapped to hi | lo + add tmp, 32 + %endif + vpshufb xgft4_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft4_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft4_hi, xgft4_lo ;GF add high and low partials + vpxor xp4, xgft4_hi ;xp4 += partial + + cmp vec_i, vec + jl .next_vect + + SLDR dest1, dest1_m + SLDR dest2, dest2_m + XSTR [dest1+pos], xp1 + XSTR [dest2+pos], xp2 + SLDR dest3, dest3_m + XSTR [dest3+pos], xp3 + SLDR dest4, dest4_m + XSTR [dest4+pos], xp4 + + SLDR len, len_m + add pos, 32 ;Loop on 32 bytes at a time + cmp pos, len + jle .loop32 + + lea tmp, [len + 32] + cmp pos, tmp + je .return_pass + + ;; Tail len + mov pos, len ;Overlapped offset length-32 + jmp .loop32 ;Do one more overlap pass + +.return_pass: + mov return, 0 + FUNC_RESTORE + ret + +.return_fail: + mov return, 1 + FUNC_RESTORE + ret + +endproc_frame + +section .data + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_4VECT_DOT_PROD_AVX2, 04, 04, 0198 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_4vect_dot_prod_sse.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_4vect_dot_prod_sse.asm new file mode 100644 index 000000000..59432e05d --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_4vect_dot_prod_sse.asm @@ -0,0 +1,491 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_4vect_dot_prod_sse(len, vec, *g_tbls, **buffs, **dests); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_4VECT_DOT_PROD_SSE _gf_4vect_dot_prod_sse +%else + %define GF_4VECT_DOT_PROD_SSE gf_4vect_dot_prod_sse +%endif + +%ifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r12 ; must be saved and restored + %define tmp5 r14 ; must be saved and restored + %define tmp6 r15 ; must be saved and restored + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + push r14 + push r15 + %endmacro + %macro FUNC_RESTORE 0 + pop r15 + pop r14 + pop r13 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r12 ; must be saved and restored + %define tmp5 r14 ; must be saved and restored + %define tmp6 r15 ; must be saved and restored + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + push r14 + push r15 + %endmacro + %macro FUNC_RESTORE 0 + pop r15 + pop r14 + pop r13 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + + %define arg4 r12 ; must be saved, loaded and restored + %define arg5 r15 ; must be saved and restored + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r14 ; must be saved and restored + %define tmp5 rdi ; must be saved and restored + %define tmp6 rsi ; must be saved and restored + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define LOG_PS 3 + %define stack_size 9*16 + 7*8 ; must be an odd multiple of 8 + %define arg(x) [rsp + stack_size + PS + PS*x] + + %define func(x) proc_frame x + %macro FUNC_SAVE 0 + alloc_stack stack_size + save_xmm128 xmm6, 0*16 + save_xmm128 xmm7, 1*16 + save_xmm128 xmm8, 2*16 + save_xmm128 xmm9, 3*16 + save_xmm128 xmm10, 4*16 + save_xmm128 xmm11, 5*16 + save_xmm128 xmm12, 6*16 + save_xmm128 xmm13, 7*16 + save_xmm128 xmm14, 8*16 + save_reg r12, 9*16 + 0*8 + save_reg r13, 9*16 + 1*8 + save_reg r14, 9*16 + 2*8 + save_reg r15, 9*16 + 3*8 + save_reg rdi, 9*16 + 4*8 + save_reg rsi, 9*16 + 5*8 + end_prolog + mov arg4, arg(4) + %endmacro + + %macro FUNC_RESTORE 0 + movdqa xmm6, [rsp + 0*16] + movdqa xmm7, [rsp + 1*16] + movdqa xmm8, [rsp + 2*16] + movdqa xmm9, [rsp + 3*16] + movdqa xmm10, [rsp + 4*16] + movdqa xmm11, [rsp + 5*16] + movdqa xmm12, [rsp + 6*16] + movdqa xmm13, [rsp + 7*16] + movdqa xmm14, [rsp + 8*16] + mov r12, [rsp + 9*16 + 0*8] + mov r13, [rsp + 9*16 + 1*8] + mov r14, [rsp + 9*16 + 2*8] + mov r15, [rsp + 9*16 + 3*8] + mov rdi, [rsp + 9*16 + 4*8] + mov rsi, [rsp + 9*16 + 5*8] + add rsp, stack_size + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, elf32 + +;;;================== High Address; +;;; arg4 +;;; arg3 +;;; arg2 +;;; arg1 +;;; arg0 +;;; return +;;;<================= esp of caller +;;; ebp +;;;<================= ebp = esp +;;; var0 +;;; var1 +;;; var2 +;;; var3 +;;; esi +;;; edi +;;; ebx +;;;<================= esp of callee +;;; +;;;================== Low Address; + + %define PS 4 + %define LOG_PS 2 + %define func(x) x: + %define arg(x) [ebp + PS*2 + PS*x] + %define var(x) [ebp - PS - PS*x] + + %define trans ecx + %define trans2 esi + %define arg0 trans ;trans and trans2 are for the variables in stack + %define arg0_m arg(0) + %define arg1 ebx + %define arg2 arg2_m + %define arg2_m arg(2) + %define arg3 trans + %define arg3_m arg(3) + %define arg4 trans + %define arg4_m arg(4) + %define arg5 trans2 + %define tmp edx + %define tmp2 edi + %define tmp3 trans2 + %define tmp3_m var(0) + %define tmp4 trans2 + %define tmp4_m var(1) + %define tmp5 trans2 + %define tmp5_m var(2) + %define tmp6 trans2 + %define tmp6_m var(3) + %define return eax + %macro SLDR 2 ;stack load/restore + mov %1, %2 + %endmacro + %define SSTR SLDR + + %macro FUNC_SAVE 0 + push ebp + mov ebp, esp + sub esp, PS*4 ;4 local variables + push esi + push edi + push ebx + mov arg1, arg(1) + %endmacro + + %macro FUNC_RESTORE 0 + pop ebx + pop edi + pop esi + add esp, PS*4 ;4 local variables + pop ebp + %endmacro + +%endif ; output formats + +%define len arg0 +%define vec arg1 +%define mul_array arg2 +%define src arg3 +%define dest1 arg4 +%define ptr arg5 +%define vec_i tmp2 +%define dest2 tmp3 +%define dest3 tmp4 +%define dest4 tmp5 +%define vskip3 tmp6 +%define pos return + + %ifidn PS,4 ;32-bit code + %define len_m arg0_m + %define src_m arg3_m + %define dest1_m arg4_m + %define dest2_m tmp3_m + %define dest3_m tmp4_m + %define dest4_m tmp5_m + %define vskip3_m tmp6_m + %endif + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR movdqu + %define XSTR movdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR movdqa + %define XSTR movdqa + %else + %define XLDR movntdqa + %define XSTR movntdq + %endif +%endif + +%ifidn PS,8 ; 64-bit code + default rel + [bits 64] +%endif + + +section .text + +%ifidn PS,8 ;64-bit code + %define xmask0f xmm14 + %define xgft1_lo xmm2 + %define xgft1_hi xmm3 + %define xgft2_lo xmm11 + %define xgft2_hi xmm4 + %define xgft3_lo xmm9 + %define xgft3_hi xmm5 + %define xgft4_lo xmm7 + %define xgft4_hi xmm6 + + %define x0 xmm0 + %define xtmpa xmm1 + %define xp1 xmm8 + %define xp2 xmm10 + %define xp3 xmm12 + %define xp4 xmm13 +%else + %define xmm_trans xmm7 ;reuse xmask0f and xgft1_lo + %define xmask0f xmm_trans + %define xgft1_lo xmm_trans + %define xgft1_hi xmm6 + %define xgft2_lo xgft1_lo + %define xgft2_hi xgft1_hi + %define xgft3_lo xgft1_lo + %define xgft3_hi xgft1_hi + %define xgft4_lo xgft1_lo + %define xgft4_hi xgft1_hi + + %define x0 xmm0 + %define xtmpa xmm1 + %define xp1 xmm2 + %define xp2 xmm3 + %define xp3 xmm4 + %define xp4 xmm5 +%endif +align 16 +global GF_4VECT_DOT_PROD_SSE:function +func(GF_4VECT_DOT_PROD_SSE) + FUNC_SAVE + SLDR len, len_m + sub len, 16 + SSTR len_m, len + jl .return_fail + xor pos, pos + movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + mov vskip3, vec + imul vskip3, 96 + SSTR vskip3_m, vskip3 + sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS + SLDR dest1, dest1_m + mov dest2, [dest1+PS] + SSTR dest2_m, dest2 + mov dest3, [dest1+2*PS] + SSTR dest3_m, dest3 + mov dest4, [dest1+3*PS] + SSTR dest4_m, dest4 + mov dest1, [dest1] + SSTR dest1_m, dest1 + +.loop16: + pxor xp1, xp1 + pxor xp2, xp2 + pxor xp3, xp3 + pxor xp4, xp4 + mov tmp, mul_array + xor vec_i, vec_i + +.next_vect: + SLDR src, src_m + mov ptr, [src+vec_i] + + %ifidn PS,8 ;64-bit code + movdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} + movdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, ..., Ax{f0} + movdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} + movdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} + movdqu xgft3_lo, [tmp+vec*(64/PS)] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} + movdqu xgft3_hi, [tmp+vec*(64/PS)+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} + movdqu xgft4_lo, [tmp+vskip3] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} + movdqu xgft4_hi, [tmp+vskip3+16] ; " Dx{00}, Dx{10}, ..., Dx{f0} + + XLDR x0, [ptr+pos] ;Get next source vector + add tmp, 32 + add vec_i, PS + + movdqa xtmpa, x0 ;Keep unshifted copy of src + psraw x0, 4 ;Shift to put high nibble into bits 4-0 + pand x0, xmask0f ;Mask high src nibble in bits 4-0 + pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 + %else ;32-bit code + XLDR x0, [ptr+pos] ;Get next source vector + movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + + movdqa xtmpa, x0 ;Keep unshifted copy of src + psraw x0, 4 ;Shift to put high nibble into bits 4-0 + pand x0, xmask0f ;Mask high src nibble in bits 4-0 + pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 + + movdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} + movdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, ..., Ax{f0} + %endif + + pshufb xgft1_hi, x0 ;Lookup mul table of high nibble + pshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft1_hi, xgft1_lo ;GF add high and low partials + pxor xp1, xgft1_hi ;xp1 += partial + + %ifidn PS,4 ;32-bit code + movdqu xgft2_lo, [tmp+vec*(32/PS)] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} + movdqu xgft2_hi, [tmp+vec*(32/PS)+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} + %endif + pshufb xgft2_hi, x0 ;Lookup mul table of high nibble + pshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft2_hi, xgft2_lo ;GF add high and low partials + pxor xp2, xgft2_hi ;xp2 += partial + + %ifidn PS,4 ;32-bit code + sal vec, 1 + movdqu xgft3_lo, [tmp+vec*(32/PS)] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} + movdqu xgft3_hi, [tmp+vec*(32/PS)+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} + sar vec, 1 + %endif + pshufb xgft3_hi, x0 ;Lookup mul table of high nibble + pshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft3_hi, xgft3_lo ;GF add high and low partials + pxor xp3, xgft3_hi ;xp3 += partial + + %ifidn PS,4 ;32-bit code + SLDR vskip3, vskip3_m + movdqu xgft4_lo, [tmp+vskip3] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} + movdqu xgft4_hi, [tmp+vskip3+16] ; " Dx{00}, Dx{10}, ..., Dx{f0} + add tmp, 32 + add vec_i, PS + %endif + pshufb xgft4_hi, x0 ;Lookup mul table of high nibble + pshufb xgft4_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft4_hi, xgft4_lo ;GF add high and low partials + pxor xp4, xgft4_hi ;xp4 += partial + + cmp vec_i, vec + jl .next_vect + + SLDR dest1, dest1_m + SLDR dest2, dest2_m + XSTR [dest1+pos], xp1 + XSTR [dest2+pos], xp2 + SLDR dest3, dest3_m + XSTR [dest3+pos], xp3 + SLDR dest4, dest4_m + XSTR [dest4+pos], xp4 + + SLDR len, len_m + add pos, 16 ;Loop on 16 bytes at a time + cmp pos, len + jle .loop16 + + lea tmp, [len + 16] + cmp pos, tmp + je .return_pass + + ;; Tail len + mov pos, len ;Overlapped offset length-16 + jmp .loop16 ;Do one more overlap pass + +.return_pass: + mov return, 0 + FUNC_RESTORE + ret + +.return_fail: + mov return, 1 + FUNC_RESTORE + ret + +endproc_frame + +section .data + +align 16 +mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_4VECT_DOT_PROD_SSE, 00, 05, 0064 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_4vect_mad_avx.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_4vect_mad_avx.asm new file mode 100644 index 000000000..af35d6704 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_4vect_mad_avx.asm @@ -0,0 +1,370 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_4vect_mad_avx(len, vec, vec_i, mul_array, src, dest); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_4VECT_MAD_AVX _gf_4vect_mad_avx +%else + %define GF_4VECT_MAD_AVX gf_4vect_mad_avx +%endif + +%define PS 8 + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg0.w ecx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + %define arg4 r12 + %define arg5 r15 + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 + %define return rax + %define return.w eax + %define stack_size 16*10 + 3*8 + %define arg(x) [rsp + stack_size + PS + PS*x] + %define func(x) proc_frame x + +%macro FUNC_SAVE 0 + sub rsp, stack_size + movdqa [rsp+16*0],xmm6 + movdqa [rsp+16*1],xmm7 + movdqa [rsp+16*2],xmm8 + movdqa [rsp+16*3],xmm9 + movdqa [rsp+16*4],xmm10 + movdqa [rsp+16*5],xmm11 + movdqa [rsp+16*6],xmm12 + movdqa [rsp+16*7],xmm13 + movdqa [rsp+16*8],xmm14 + movdqa [rsp+16*9],xmm15 + save_reg r12, 10*16 + 0*8 + save_reg r13, 10*16 + 1*8 + save_reg r15, 10*16 + 2*8 + end_prolog + mov arg4, arg(4) + mov arg5, arg(5) +%endmacro + +%macro FUNC_RESTORE 0 + movdqa xmm6, [rsp+16*0] + movdqa xmm7, [rsp+16*1] + movdqa xmm8, [rsp+16*2] + movdqa xmm9, [rsp+16*3] + movdqa xmm10, [rsp+16*4] + movdqa xmm11, [rsp+16*5] + movdqa xmm12, [rsp+16*6] + movdqa xmm13, [rsp+16*7] + movdqa xmm14, [rsp+16*8] + movdqa xmm15, [rsp+16*9] + mov r12, [rsp + 10*16 + 0*8] + mov r13, [rsp + 10*16 + 1*8] + mov r15, [rsp + 10*16 + 2*8] + add rsp, stack_size +%endmacro + +%elifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define tmp2 r10 + %define tmp3 r12 + %define return rax + %define return.w eax + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + %endmacro + %macro FUNC_RESTORE 0 + pop r12 + %endmacro +%elifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define tmp2 r10 + %define tmp3 r12 + %define return rax + %define return.w eax + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + %endmacro + %macro FUNC_RESTORE 0 + pop r12 + %endmacro +%endif + +;;; gf_4vect_mad_avx(len, vec, vec_i, mul_array, src, dest) +%define len arg0 +%define len.w arg0.w +%define vec arg1 +%define vec_i arg2 +%define mul_array arg3 +%define src arg4 +%define dest1 arg5 +%define pos return +%define pos.w return.w + +%define dest2 mul_array +%define dest3 tmp2 +%define dest4 vec_i + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR vmovdqu + %define XSTR vmovdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR vmovdqa + %define XSTR vmovdqa + %else + %define XLDR vmovntdqa + %define XSTR vmovntdq + %endif +%endif + + +default rel + +[bits 64] +section .text + +%define xmask0f xmm15 +%define xgft3_hi xmm14 +%define xgft4_hi xmm13 +%define xgft4_lo xmm12 + +%define x0 xmm0 +%define xtmpa xmm1 +%define xtmph1 xmm2 +%define xtmpl1 xmm3 +%define xtmph2 xmm4 +%define xtmpl2 xmm5 +%define xtmph3 xmm6 +%define xtmpl3 xmm7 +%define xtmph4 xmm8 +%define xtmpl4 xmm9 +%define xd1 xmm10 +%define xd2 xmm11 +%define xd3 xtmph1 +%define xd4 xtmpl1 + +align 16 +global GF_4VECT_MAD_AVX:function +func(GF_4VECT_MAD_AVX) + FUNC_SAVE + sub len, 16 + jl .return_fail + xor pos, pos + vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + + mov tmp, vec + + sal vec_i, 5 ;Multiply by 32 + lea tmp3, [mul_array + vec_i] + + sal tmp, 6 ;Multiply by 64 + vmovdqu xgft3_hi, [tmp3+tmp+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} + sal vec, 5 ;Multiply by 32 + add tmp, vec + vmovdqu xgft4_lo, [tmp3+tmp] ;Load array Dx{00}, Dx{01}, Dx{02}, ... + vmovdqu xgft4_hi, [tmp3+tmp+16] ; " Dx{00}, Dx{10}, Dx{20}, ... , Dx{f0} + + mov dest2, [dest1+PS] ; reuse mul_array + mov dest3, [dest1+2*PS] + mov dest4, [dest1+3*PS] ; reuse vec_i + mov dest1, [dest1] + +.loop16: + XLDR x0, [src+pos] ;Get next source vector + vmovdqu xtmph1, [tmp3+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} + vmovdqu xtmpl1, [tmp3] ;Load array Ax{00}, Ax{01}, Ax{02}, ... + vmovdqu xtmph2, [tmp3+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} + vmovdqu xtmpl2, [tmp3+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... + vmovdqu xtmpl3, [tmp3+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... + + XLDR xd1, [dest1+pos] ;Get next dest vector + XLDR xd2, [dest2+pos] ;Get next dest vector + + vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + + ; dest1 + vpshufb xtmph1, xtmph1, x0 ;Lookup mul table of high nibble + vpshufb xtmpl1, xtmpl1, xtmpa ;Lookup mul table of low nibble + vpxor xtmph1, xtmph1, xtmpl1 ;GF add high and low partials + vpxor xd1, xd1, xtmph1 + + XLDR xd3, [dest3+pos] ;Reuse xtmph1, Get next dest vector + XLDR xd4, [dest4+pos] ;Reuse xtmpl1, Get next dest vector + + ; dest2 + vpshufb xtmph2, xtmph2, x0 ;Lookup mul table of high nibble + vpshufb xtmpl2, xtmpl2, xtmpa ;Lookup mul table of low nibble + vpxor xtmph2, xtmph2, xtmpl2 ;GF add high and low partials + vpxor xd2, xd2, xtmph2 + + ; dest3 + vpshufb xtmph3, xgft3_hi, x0 ;Lookup mul table of high nibble + vpshufb xtmpl3, xtmpl3, xtmpa ;Lookup mul table of low nibble + vpxor xtmph3, xtmph3, xtmpl3 ;GF add high and low partials + vpxor xd3, xd3, xtmph3 + + ; dest4 + vpshufb xtmph4, xgft4_hi, x0 ;Lookup mul table of high nibble + vpshufb xtmpl4, xgft4_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph4, xtmph4, xtmpl4 ;GF add high and low partials + vpxor xd4, xd4, xtmph4 + + XSTR [dest1+pos], xd1 ;Store result + XSTR [dest2+pos], xd2 ;Store result + XSTR [dest3+pos], xd3 ;Store result + XSTR [dest4+pos], xd4 ;Store result + + add pos, 16 ;Loop on 16 bytes at a time + cmp pos, len + jle .loop16 + + lea tmp, [len + 16] + cmp pos, tmp + je .return_pass + +.lessthan16: + ;; Tail len + ;; Do one more overlap pass + + mov tmp, len ;Overlapped offset length-16 + + XLDR x0, [src+tmp] ;Get next source vector + + vmovdqu xtmph1, [tmp3+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} + vmovdqu xtmpl1, [tmp3] ;Load array Ax{00}, Ax{01}, Ax{02}, ... + vmovdqu xtmph2, [tmp3+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} + vmovdqu xtmpl2, [tmp3+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... + vmovdqu xtmpl3, [tmp3+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... + + XLDR xd1, [dest1+tmp] ;Get next dest vector + XLDR xd2, [dest2+tmp] ;Get next dest vector + XLDR xtmph4, [dest3+tmp] ;Get next dest vector + + sub len, pos + + vmovdqa xtmpl4, [constip16] ;Load const of i + 16 + vpinsrb xtmph3, xtmph3, len.w, 15 + vpshufb xtmph3, xtmph3, xmask0f ;Broadcast len to all bytes + vpcmpgtb xtmph3, xtmph3, xtmpl4 + + XLDR xtmpl4, [dest4+tmp] ;Get next dest vector + + vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + + ; dest1 + vpshufb xtmph1, xtmph1, x0 ;Lookup mul table of high nibble + vpshufb xtmpl1, xtmpl1, xtmpa ;Lookup mul table of low nibble + vpxor xtmph1, xtmph1, xtmpl1 ;GF add high and low partials + vpand xtmph1, xtmph1, xtmph3 + vpxor xd1, xd1, xtmph1 + + ; dest2 + vpshufb xtmph2, xtmph2, x0 ;Lookup mul table of high nibble + vpshufb xtmpl2, xtmpl2, xtmpa ;Lookup mul table of low nibble + vpxor xtmph2, xtmph2, xtmpl2 ;GF add high and low partials + vpand xtmph2, xtmph2, xtmph3 + vpxor xd2, xd2, xtmph2 + + ; dest3 + vpshufb xgft3_hi, xgft3_hi, x0 ;Lookup mul table of high nibble + vpshufb xtmpl3, xtmpl3, xtmpa ;Lookup mul table of low nibble + vpxor xgft3_hi, xgft3_hi, xtmpl3 ;GF add high and low partials + vpand xgft3_hi, xgft3_hi, xtmph3 + vpxor xtmph4, xtmph4, xgft3_hi + + ; dest4 + vpshufb xgft4_hi, xgft4_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft4_lo, xgft4_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft4_hi, xgft4_hi, xgft4_lo ;GF add high and low partials + vpand xgft4_hi, xgft4_hi, xtmph3 + vpxor xtmpl4, xtmpl4, xgft4_hi + + XSTR [dest1+tmp], xd1 ;Store result + XSTR [dest2+tmp], xd2 ;Store result + XSTR [dest3+tmp], xtmph4 ;Store result + XSTR [dest4+tmp], xtmpl4 ;Store result + +.return_pass: + mov return, 0 + FUNC_RESTORE + ret + +.return_fail: + mov return, 1 + FUNC_RESTORE + ret + +endproc_frame + +section .data + +align 16 +mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f +constip16: + ddq 0xf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff + + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_4VECT_MAD_AVX, 02, 00, 020a diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_4vect_mad_avx2.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_4vect_mad_avx2.asm new file mode 100644 index 000000000..8ea779af2 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_4vect_mad_avx2.asm @@ -0,0 +1,371 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_4vect_mad_avx2(len, vec, vec_i, mul_array, src, dest); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_4VECT_MAD_AVX2 _gf_4vect_mad_avx2 +%else + %define GF_4VECT_MAD_AVX2 gf_4vect_mad_avx2 +%endif + +%define PS 8 + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg0.w ecx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + %define arg4 r12 + %define arg5 r15 + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define return rax + %define return.w eax + %define stack_size 16*10 + 3*8 + %define arg(x) [rsp + stack_size + PS + PS*x] + %define func(x) proc_frame x + +%macro FUNC_SAVE 0 + sub rsp, stack_size + movdqa [rsp+16*0],xmm6 + movdqa [rsp+16*1],xmm7 + movdqa [rsp+16*2],xmm8 + movdqa [rsp+16*3],xmm9 + movdqa [rsp+16*4],xmm10 + movdqa [rsp+16*5],xmm11 + movdqa [rsp+16*6],xmm12 + movdqa [rsp+16*7],xmm13 + movdqa [rsp+16*8],xmm14 + movdqa [rsp+16*9],xmm15 + save_reg r12, 10*16 + 0*8 + save_reg r15, 10*16 + 1*8 + end_prolog + mov arg4, arg(4) + mov arg5, arg(5) +%endmacro + +%macro FUNC_RESTORE 0 + movdqa xmm6, [rsp+16*0] + movdqa xmm7, [rsp+16*1] + movdqa xmm8, [rsp+16*2] + movdqa xmm9, [rsp+16*3] + movdqa xmm10, [rsp+16*4] + movdqa xmm11, [rsp+16*5] + movdqa xmm12, [rsp+16*6] + movdqa xmm13, [rsp+16*7] + movdqa xmm14, [rsp+16*8] + movdqa xmm15, [rsp+16*9] + mov r12, [rsp + 10*16 + 0*8] + mov r15, [rsp + 10*16 + 1*8] + add rsp, stack_size +%endmacro + +%elifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define return rax + %define return.w eax + + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%elifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define return rax + %define return.w eax + + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%endif + + +;;; gf_4vect_mad_avx2(len, vec, vec_i, mul_array, src, dest) +%define len arg0 +%define len.w arg0.w +%define vec arg1 +%define vec_i arg2 +%define mul_array arg3 +%define src arg4 +%define dest1 arg5 +%define pos return +%define pos.w return.w + +%define dest2 mul_array +%define dest3 vec +%define dest4 vec_i + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR vmovdqu + %define XSTR vmovdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR vmovdqa + %define XSTR vmovdqa + %else + %define XLDR vmovntdqa + %define XSTR vmovntdq + %endif +%endif + + +default rel + +[bits 64] +section .text + +%define xmask0f ymm15 +%define xmask0fx xmm15 +%define xgft1_lo ymm14 +%define xgft2_lo ymm13 +%define xgft3_lo ymm12 +%define xgft4_lo ymm11 + +%define x0 ymm0 +%define xtmpa ymm1 +%define xtmpl ymm2 +%define xtmplx xmm2 +%define xtmph1 ymm3 +%define xtmph1x xmm3 +%define xtmph2 ymm4 +%define xtmph3 ymm5 +%define xtmph4 ymm6 +%define xd1 ymm7 +%define xd2 ymm8 +%define xd3 ymm9 +%define xd4 ymm10 + +align 16 +global GF_4VECT_MAD_AVX2:function +func(GF_4VECT_MAD_AVX2) + FUNC_SAVE + sub len, 32 + jl .return_fail + xor pos, pos + mov tmp.b, 0x0f + vpinsrb xmask0fx, xmask0fx, tmp.w, 0 + vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f... + + sal vec_i, 5 ;Multiply by 32 + sal vec, 5 ;Multiply by 32 + lea tmp, [mul_array + vec_i] + + vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, Ax{02}, ... + ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} + vmovdqu xgft2_lo, [tmp+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... + ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} + vmovdqu xgft3_lo, [tmp+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... + ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} + add tmp, vec + vmovdqu xgft4_lo, [tmp+2*vec] ;Load array Dx{00}, Dx{01}, Dx{02}, ... + ; " Dx{00}, Dx{10}, Dx{20}, ... , Dx{f0} + + mov dest2, [dest1+PS] ; reuse mul_array + mov dest3, [dest1+2*PS] ; reuse vec + mov dest4, [dest1+3*PS] ; reuse vec_i + mov dest1, [dest1] + +.loop32: + XLDR x0, [src+pos] ;Get next source vector + + XLDR xd1, [dest1+pos] ;Get next dest vector + XLDR xd2, [dest2+pos] ;Get next dest vector + XLDR xd3, [dest3+pos] ;Get next dest vector + XLDR xd4, [dest4+pos] ;reuse xtmpl1. Get next dest vector + + vpand xtmpl, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + + vperm2i128 xtmpa, xtmpl, x0, 0x30 ;swap xtmpa from 1lo|2lo to 1lo|2hi + vperm2i128 x0, xtmpl, x0, 0x12 ;swap x0 from 1hi|2hi to 1hi|2lo + + vperm2i128 xtmph1, xgft1_lo, xgft1_lo, 0x01 ; swapped to hi | lo + vperm2i128 xtmph2, xgft2_lo, xgft2_lo, 0x01 ; swapped to hi | lo + vperm2i128 xtmph3, xgft3_lo, xgft3_lo, 0x01 ; swapped to hi | lo + vperm2i128 xtmph4, xgft4_lo, xgft4_lo, 0x01 ; swapped to hi | lo + + ; dest1 + vpshufb xtmph1, xtmph1, x0 ;Lookup mul table of high nibble + vpshufb xtmpl, xgft1_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph1, xtmph1, xtmpl ;GF add high and low partials + vpxor xd1, xd1, xtmph1 ;xd1 += partial + + ; dest2 + vpshufb xtmph2, xtmph2, x0 ;Lookup mul table of high nibble + vpshufb xtmpl, xgft2_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph2, xtmph2, xtmpl ;GF add high and low partials + vpxor xd2, xd2, xtmph2 ;xd2 += partial + + ; dest3 + vpshufb xtmph3, xtmph3, x0 ;Lookup mul table of high nibble + vpshufb xtmpl, xgft3_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph3, xtmph3, xtmpl ;GF add high and low partials + vpxor xd3, xd3, xtmph3 ;xd3 += partial + + ; dest4 + vpshufb xtmph4, xtmph4, x0 ;Lookup mul table of high nibble + vpshufb xtmpl, xgft4_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph4, xtmph4, xtmpl ;GF add high and low partials + vpxor xd4, xd4, xtmph4 ;xd4 += partial + + XSTR [dest1+pos], xd1 + XSTR [dest2+pos], xd2 + XSTR [dest3+pos], xd3 + XSTR [dest4+pos], xd4 + + add pos, 32 ;Loop on 32 bytes at a time + cmp pos, len + jle .loop32 + + lea tmp, [len + 32] + cmp pos, tmp + je .return_pass + +.lessthan32: + ;; Tail len + ;; Do one more overlap pass + mov tmp.b, 0x1f + vpinsrb xtmph1x, xtmph1x, tmp.w, 0 + vpbroadcastb xtmph1, xtmph1x ;Construct mask 0x1f1f1f... + + mov tmp, len ;Overlapped offset length-32 + + XLDR x0, [src+tmp] ;Get next source vector + + XLDR xd1, [dest1+tmp] ;Get next dest vector + XLDR xd2, [dest2+tmp] ;Get next dest vector + XLDR xd3, [dest3+tmp] ;Get next dest vector + XLDR xd4, [dest4+tmp] ;Get next dest vector + + sub len, pos + + vmovdqa xtmph2, [constip32] ;Load const of i + 32 + vpinsrb xtmplx, xtmplx, len.w, 15 + vinserti128 xtmpl, xtmpl, xtmplx, 1 ;swapped to xtmplx | xtmplx + vpshufb xtmpl, xtmpl, xtmph1 ;Broadcast len to all bytes. xtmph1=0x1f1f1f... + vpcmpgtb xtmpl, xtmpl, xtmph2 + + vpand xtmph1, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + + vperm2i128 xtmpa, xtmph1, x0, 0x30 ;swap xtmpa from 1lo|2lo to 1lo|2hi + vperm2i128 x0, xtmph1, x0, 0x12 ;swap x0 from 1hi|2hi to 1hi|2lo + + vperm2i128 xtmph1, xgft1_lo, xgft1_lo, 0x01 ; swapped to hi | lo + vperm2i128 xtmph2, xgft2_lo, xgft2_lo, 0x01 ; swapped to hi | lo + vperm2i128 xtmph3, xgft3_lo, xgft3_lo, 0x01 ; swapped to hi | lo + vperm2i128 xtmph4, xgft4_lo, xgft4_lo, 0x01 ; swapped to hi | lo + + ; dest1 + vpshufb xtmph1, xtmph1, x0 ;Lookup mul table of high nibble + vpshufb xgft1_lo, xgft1_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph1, xtmph1, xgft1_lo ;GF add high and low partials + vpand xtmph1, xtmph1, xtmpl + vpxor xd1, xd1, xtmph1 ;xd1 += partial + + ; dest2 + vpshufb xtmph2, xtmph2, x0 ;Lookup mul table of high nibble + vpshufb xgft2_lo, xgft2_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph2, xtmph2, xgft2_lo ;GF add high and low partials + vpand xtmph2, xtmph2, xtmpl + vpxor xd2, xd2, xtmph2 ;xd2 += partial + + ; dest3 + vpshufb xtmph3, xtmph3, x0 ;Lookup mul table of high nibble + vpshufb xgft3_lo, xgft3_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph3, xtmph3, xgft3_lo ;GF add high and low partials + vpand xtmph3, xtmph3, xtmpl + vpxor xd3, xd3, xtmph3 ;xd3 += partial + + ; dest4 + vpshufb xtmph4, xtmph4, x0 ;Lookup mul table of high nibble + vpshufb xgft4_lo, xgft4_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph4, xtmph4, xgft4_lo ;GF add high and low partials + vpand xtmph4, xtmph4, xtmpl + vpxor xd4, xd4, xtmph4 ;xd4 += partial + + XSTR [dest1+tmp], xd1 + XSTR [dest2+tmp], xd2 + XSTR [dest3+tmp], xd3 + XSTR [dest4+tmp], xd4 + +.return_pass: + mov return, 0 + FUNC_RESTORE + ret + +.return_fail: + mov return, 1 + FUNC_RESTORE + ret + +endproc_frame + +section .data +align 32 +constip32: + ddq 0xf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff + ddq 0xe0e1e2e3e4e5e6e7e8e9eaebecedeeef + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_4VECT_MAD_AVX2, 04, 00, 020b diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_4vect_mad_sse.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_4vect_mad_sse.asm new file mode 100644 index 000000000..9f0bc4165 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_4vect_mad_sse.asm @@ -0,0 +1,375 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_4vect_mad_sse(len, vec, vec_i, mul_array, src, dest); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_4VECT_MAD_SSE _gf_4vect_mad_sse +%else + %define GF_4VECT_MAD_SSE gf_4vect_mad_sse +%endif + +%define PS 8 + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg0.w ecx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + %define arg4 r12 + %define arg5 r15 + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 + %define return rax + %define return.w eax + %define stack_size 16*10 + 3*8 + %define arg(x) [rsp + stack_size + PS + PS*x] + %define func(x) proc_frame x + +%macro FUNC_SAVE 0 + sub rsp, stack_size + movdqa [rsp+16*0],xmm6 + movdqa [rsp+16*1],xmm7 + movdqa [rsp+16*2],xmm8 + movdqa [rsp+16*3],xmm9 + movdqa [rsp+16*4],xmm10 + movdqa [rsp+16*5],xmm11 + movdqa [rsp+16*6],xmm12 + movdqa [rsp+16*7],xmm13 + movdqa [rsp+16*8],xmm14 + movdqa [rsp+16*9],xmm15 + save_reg r12, 10*16 + 0*8 + save_reg r13, 10*16 + 1*8 + save_reg r15, 10*16 + 2*8 + end_prolog + mov arg4, arg(4) + mov arg5, arg(5) +%endmacro + +%macro FUNC_RESTORE 0 + movdqa xmm6, [rsp+16*0] + movdqa xmm7, [rsp+16*1] + movdqa xmm8, [rsp+16*2] + movdqa xmm9, [rsp+16*3] + movdqa xmm10, [rsp+16*4] + movdqa xmm11, [rsp+16*5] + movdqa xmm12, [rsp+16*6] + movdqa xmm13, [rsp+16*7] + movdqa xmm14, [rsp+16*8] + movdqa xmm15, [rsp+16*9] + mov r12, [rsp + 10*16 + 0*8] + mov r13, [rsp + 10*16 + 1*8] + mov r15, [rsp + 10*16 + 2*8] + add rsp, stack_size +%endmacro + +%elifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define tmp2 r10 + %define tmp3 r12 + %define return rax + %define return.w eax + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + %endmacro + %macro FUNC_RESTORE 0 + pop r12 + %endmacro +%elifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define tmp2 r10 + %define tmp3 r12 + %define return rax + %define return.w eax + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + %endmacro + %macro FUNC_RESTORE 0 + pop r12 + %endmacro +%endif + +;;; gf_4vect_mad_sse(len, vec, vec_i, mul_array, src, dest) +%define len arg0 +%define len.w arg0.w +%define vec arg1 +%define vec_i arg2 +%define mul_array arg3 +%define src arg4 +%define dest1 arg5 +%define pos return +%define pos.w return.w + +%define dest2 mul_array +%define dest3 tmp2 +%define dest4 vec_i + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR movdqu + %define XSTR movdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR movdqa + %define XSTR movdqa + %else + %define XLDR movntdqa + %define XSTR movntdq + %endif +%endif + +default rel + +[bits 64] +section .text + +%define xmask0f xmm15 +%define xgft3_hi xmm14 +%define xgft4_hi xmm13 +%define xgft4_lo xmm12 + +%define x0 xmm0 +%define xtmpa xmm1 +%define xtmph1 xmm2 +%define xtmpl1 xmm3 +%define xtmph2 xmm4 +%define xtmpl2 xmm5 +%define xtmph3 xmm6 +%define xtmpl3 xmm7 +%define xtmph4 xmm8 +%define xtmpl4 xmm9 +%define xd1 xmm10 +%define xd2 xmm11 +%define xd3 xtmph1 +%define xd4 xtmpl1 + +align 16 +global GF_4VECT_MAD_SSE:function +func(GF_4VECT_MAD_SSE) + FUNC_SAVE + sub len, 16 + jl .return_fail + xor pos, pos + movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + mov tmp, vec + + sal vec_i, 5 ;Multiply by 32 + lea tmp3, [mul_array + vec_i] + + sal tmp, 6 ;Multiply by 64 + + movdqu xgft3_hi, [tmp3+tmp+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} + sal vec, 5 ;Multiply by 32 + add tmp, vec + movdqu xgft4_lo, [tmp3+tmp] ;Load array Dx{00}, Dx{01}, Dx{02}, ... + movdqu xgft4_hi, [tmp3+tmp+16] ; " Dx{00}, Dx{10}, Dx{20}, ... , Dx{f0} + + mov dest2, [dest1+PS] ; reuse mul_array + mov dest3, [dest1+2*PS] + mov dest4, [dest1+3*PS] ; reuse vec_i + mov dest1, [dest1] + +.loop16: + XLDR x0, [src+pos] ;Get next source vector + movdqu xtmph1, [tmp3+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} + movdqu xtmpl1, [tmp3] ;Load array Ax{00}, Ax{01}, Ax{02}, ... + movdqu xtmph2, [tmp3+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} + movdqu xtmpl2, [tmp3+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... + movdqu xtmpl3, [tmp3+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... + + movdqa xtmph3, xgft3_hi + movdqa xtmpl4, xgft4_lo + movdqa xtmph4, xgft4_hi + + XLDR xd1, [dest1+pos] ;Get next dest vector + XLDR xd2, [dest2+pos] ;Get next dest vector + + movdqa xtmpa, x0 ;Keep unshifted copy of src + psraw x0, 4 ;Shift to put high nibble into bits 4-0 + pand x0, xmask0f ;Mask high src nibble in bits 4-0 + pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 + + ; dest1 + pshufb xtmph1, x0 ;Lookup mul table of high nibble + pshufb xtmpl1, xtmpa ;Lookup mul table of low nibble + pxor xtmph1, xtmpl1 ;GF add high and low partials + pxor xd1, xtmph1 + + XLDR xd3, [dest3+pos] ;Reuse xtmph1, Get next dest vector + XLDR xd4, [dest4+pos] ;Reuse xtmpl1, Get next dest vector + + ; dest2 + pshufb xtmph2, x0 ;Lookup mul table of high nibble + pshufb xtmpl2, xtmpa ;Lookup mul table of low nibble + pxor xtmph2, xtmpl2 ;GF add high and low partials + pxor xd2, xtmph2 + + ; dest3 + pshufb xtmph3, x0 ;Lookup mul table of high nibble + pshufb xtmpl3, xtmpa ;Lookup mul table of low nibble + pxor xtmph3, xtmpl3 ;GF add high and low partials + pxor xd3, xtmph3 + + ; dest4 + pshufb xtmph4, x0 ;Lookup mul table of high nibble + pshufb xtmpl4, xtmpa ;Lookup mul table of low nibble + pxor xtmph4, xtmpl4 ;GF add high and low partials + pxor xd4, xtmph4 + + XSTR [dest1+pos], xd1 ;Store result + XSTR [dest2+pos], xd2 ;Store result + XSTR [dest3+pos], xd3 ;Store result + XSTR [dest4+pos], xd4 ;Store result + + add pos, 16 ;Loop on 16 bytes at a time + cmp pos, len + jle .loop16 + + lea tmp, [len + 16] + cmp pos, tmp + je .return_pass + +.lessthan16: + ;; Tail len + ;; Do one more overlap pass + mov tmp, len ;Overlapped offset length-16 + + XLDR x0, [src+tmp] ;Get next source vector + + movdqu xtmph1, [tmp3+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} + movdqu xtmpl1, [tmp3] ;Load array Ax{00}, Ax{01}, Ax{02}, ... + movdqu xtmph2, [tmp3+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} + movdqu xtmpl2, [tmp3+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... + movdqu xtmpl3, [tmp3+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... + + XLDR xd1, [dest1+tmp] ;Get next dest vector + XLDR xd2, [dest2+tmp] ;Get next dest vector + XLDR xtmph4, [dest3+tmp] ;Reuse xtmph1. Get next dest vector + + sub len, pos + + movdqa xtmpl4, [constip16] ;Load const of i + 16 + pinsrb xtmph3, len.w, 15 + pshufb xtmph3, xmask0f ;Broadcast len to all bytes + pcmpgtb xtmph3, xtmpl4 + + XLDR xtmpl4, [dest4+tmp] ;Get next dest vector + + movdqa xtmpa, x0 ;Keep unshifted copy of src + psraw x0, 4 ;Shift to put high nibble into bits 4-0 + pand x0, xmask0f ;Mask high src nibble in bits 4-0 + pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 + + ; dest1 + pshufb xtmph1, x0 ;Lookup mul table of high nibble + pshufb xtmpl1, xtmpa ;Lookup mul table of low nibble + pxor xtmph1, xtmpl1 ;GF add high and low partials + pand xtmph1, xtmph3 + pxor xd1, xtmph1 + + ; dest2 + pshufb xtmph2, x0 ;Lookup mul table of high nibble + pshufb xtmpl2, xtmpa ;Lookup mul table of low nibble + pxor xtmph2, xtmpl2 ;GF add high and low partials + pand xtmph2, xtmph3 + pxor xd2, xtmph2 + + ; dest3 + pshufb xgft3_hi, x0 ;Lookup mul table of high nibble + pshufb xtmpl3, xtmpa ;Lookup mul table of low nibble + pxor xgft3_hi, xtmpl3 ;GF add high and low partials + pand xgft3_hi, xtmph3 + pxor xtmph4, xgft3_hi + + ; dest4 + pshufb xgft4_hi, x0 ;Lookup mul table of high nibble + pshufb xgft4_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft4_hi, xgft4_lo ;GF add high and low partials + pand xgft4_hi, xtmph3 + pxor xtmpl4, xgft4_hi + + XSTR [dest1+tmp], xd1 ;Store result + XSTR [dest2+tmp], xd2 ;Store result + XSTR [dest3+tmp], xtmph4 ;Store result + XSTR [dest4+tmp], xtmpl4 ;Store result + +.return_pass: + FUNC_RESTORE + mov return, 0 + ret + +.return_fail: + FUNC_RESTORE + mov return, 1 + ret + +endproc_frame + +section .data + +align 16 + +mask0f: + ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f +constip16: + ddq 0xf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_4VECT_MAD_SSE, 00, 00, 0209 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_5vect_dot_prod_avx.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_5vect_dot_prod_avx.asm new file mode 100644 index 000000000..4291b8ea5 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_5vect_dot_prod_avx.asm @@ -0,0 +1,348 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_5vect_dot_prod_avx(len, vec, *g_tbls, **buffs, **dests); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_5VECT_DOT_PROD_AVX _gf_5vect_dot_prod_avx +%else + %define GF_5VECT_DOT_PROD_AVX gf_5vect_dot_prod_avx +%endif + +%ifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r12 ; must be saved and restored + %define tmp5 r14 ; must be saved and restored + %define tmp6 r15 ; must be saved and restored + %define return rax + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + push r14 + push r15 + %endmacro + %macro FUNC_RESTORE 0 + pop r15 + pop r14 + pop r13 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r12 ; must be saved and restored + %define tmp5 r14 ; must be saved and restored + %define tmp6 r15 ; must be saved and restored + %define return rax + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + push r14 + push r15 + %endmacro + %macro FUNC_RESTORE 0 + pop r15 + pop r14 + pop r13 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + + %define arg4 r12 ; must be saved, loaded and restored + %define arg5 r15 ; must be saved and restored + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r14 ; must be saved and restored + %define tmp5 rdi ; must be saved and restored + %define tmp6 rsi ; must be saved and restored + %define return rax + %define PS 8 + %define LOG_PS 3 + %define stack_size 10*16 + 7*8 ; must be an odd multiple of 8 + %define arg(x) [rsp + stack_size + PS + PS*x] + + %define func(x) proc_frame x + %macro FUNC_SAVE 0 + alloc_stack stack_size + save_xmm128 xmm6, 0*16 + save_xmm128 xmm7, 1*16 + save_xmm128 xmm8, 2*16 + save_xmm128 xmm9, 3*16 + save_xmm128 xmm10, 4*16 + save_xmm128 xmm11, 5*16 + save_xmm128 xmm12, 6*16 + save_xmm128 xmm13, 7*16 + save_xmm128 xmm14, 8*16 + save_xmm128 xmm15, 9*16 + save_reg r12, 10*16 + 0*8 + save_reg r13, 10*16 + 1*8 + save_reg r14, 10*16 + 2*8 + save_reg r15, 10*16 + 3*8 + save_reg rdi, 10*16 + 4*8 + save_reg rsi, 10*16 + 5*8 + end_prolog + mov arg4, arg(4) + %endmacro + + %macro FUNC_RESTORE 0 + vmovdqa xmm6, [rsp + 0*16] + vmovdqa xmm7, [rsp + 1*16] + vmovdqa xmm8, [rsp + 2*16] + vmovdqa xmm9, [rsp + 3*16] + vmovdqa xmm10, [rsp + 4*16] + vmovdqa xmm11, [rsp + 5*16] + vmovdqa xmm12, [rsp + 6*16] + vmovdqa xmm13, [rsp + 7*16] + vmovdqa xmm14, [rsp + 8*16] + vmovdqa xmm15, [rsp + 9*16] + mov r12, [rsp + 10*16 + 0*8] + mov r13, [rsp + 10*16 + 1*8] + mov r14, [rsp + 10*16 + 2*8] + mov r15, [rsp + 10*16 + 3*8] + mov rdi, [rsp + 10*16 + 4*8] + mov rsi, [rsp + 10*16 + 5*8] + add rsp, stack_size + %endmacro +%endif + +%define len arg0 +%define vec arg1 +%define mul_array arg2 +%define src arg3 +%define dest arg4 +%define ptr arg5 +%define vec_i tmp2 +%define dest1 tmp3 +%define dest2 tmp4 +%define vskip1 tmp5 +%define vskip3 tmp6 +%define pos return + + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR vmovdqu + %define XSTR vmovdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR vmovdqa + %define XSTR vmovdqa + %else + %define XLDR vmovntdqa + %define XSTR vmovntdq + %endif +%endif + +default rel + +[bits 64] +section .text + +%define xmask0f xmm15 +%define xgft1_lo xmm14 +%define xgft1_hi xmm13 +%define xgft2_lo xmm12 +%define xgft2_hi xmm11 +%define xgft3_lo xmm10 +%define xgft3_hi xmm9 +%define xgft4_lo xmm8 +%define xgft4_hi xmm7 + + +%define x0 xmm0 +%define xtmpa xmm1 +%define xp1 xmm2 +%define xp2 xmm3 +%define xp3 xmm4 +%define xp4 xmm5 +%define xp5 xmm6 + +align 16 +global GF_5VECT_DOT_PROD_AVX:function +func(GF_5VECT_DOT_PROD_AVX) + FUNC_SAVE + sub len, 16 + jl .return_fail + xor pos, pos + vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + mov vskip1, vec + imul vskip1, 32 + mov vskip3, vec + imul vskip3, 96 + sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS + mov dest1, [dest] + mov dest2, [dest+PS] + + +.loop16: + mov tmp, mul_array + xor vec_i, vec_i + vpxor xp1, xp1 + vpxor xp2, xp2 + vpxor xp3, xp3 + vpxor xp4, xp4 + vpxor xp5, xp5 + + +.next_vect: + mov ptr, [src+vec_i] + add vec_i, PS + XLDR x0, [ptr+pos] ;Get next source vector + + vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} + vmovdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, ..., Ax{f0} + vmovdqu xgft2_lo, [tmp+vskip1*1] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} + vmovdqu xgft2_hi, [tmp+vskip1*1+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} + vmovdqu xgft3_lo, [tmp+vskip1*2] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} + vmovdqu xgft3_hi, [tmp+vskip1*2+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} + vmovdqu xgft4_lo, [tmp+vskip3] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} + vmovdqu xgft4_hi, [tmp+vskip3+16] ; " Dx{00}, Dx{10}, ..., Dx{f0} + + vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + + vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft1_hi, xgft1_lo ;GF add high and low partials + vpxor xp1, xgft1_hi ;xp1 += partial + + vpshufb xgft2_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft2_hi, xgft2_lo ;GF add high and low partials + vpxor xp2, xgft2_hi ;xp2 += partial + + vmovdqu xgft1_lo, [tmp+vskip1*4] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} + vmovdqu xgft1_hi, [tmp+vskip1*4+16] ; " Ex{00}, Ex{10}, ..., Ex{f0} + add tmp, 32 + + vpshufb xgft3_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft3_hi, xgft3_lo ;GF add high and low partials + vpxor xp3, xgft3_hi ;xp3 += partial + + vpshufb xgft4_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft4_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft4_hi, xgft4_lo ;GF add high and low partials + vpxor xp4, xgft4_hi ;xp4 += partial + + vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft1_hi, xgft1_lo ;GF add high and low partials + vpxor xp5, xgft1_hi ;xp5 += partial + + cmp vec_i, vec + jl .next_vect + + mov tmp, [dest+2*PS] + mov ptr, [dest+3*PS] + mov vec_i, [dest+4*PS] + + XSTR [dest1+pos], xp1 + XSTR [dest2+pos], xp2 + XSTR [tmp+pos], xp3 + XSTR [ptr+pos], xp4 + XSTR [vec_i+pos], xp5 + + add pos, 16 ;Loop on 16 bytes at a time + cmp pos, len + jle .loop16 + + lea tmp, [len + 16] + cmp pos, tmp + je .return_pass + + ;; Tail len + mov pos, len ;Overlapped offset length-16 + jmp .loop16 ;Do one more overlap pass + +.return_pass: + FUNC_RESTORE + mov return, 0 + ret + +.return_fail: + FUNC_RESTORE + mov return, 1 + ret + +endproc_frame + +section .data + +align 16 +mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_5VECT_DOT_PROD_AVX, 02, 03, 0194 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_5vect_dot_prod_avx2.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_5vect_dot_prod_avx2.asm new file mode 100644 index 000000000..5dcbd3740 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_5vect_dot_prod_avx2.asm @@ -0,0 +1,362 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_5vect_dot_prod_avx2(len, vec, *g_tbls, **buffs, **dests); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_5VECT_DOT_PROD_AVX2 _gf_5vect_dot_prod_avx2 +%else + %define GF_5VECT_DOT_PROD_AVX2 gf_5vect_dot_prod_avx2 +%endif + +%ifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r12 ; must be saved and restored + %define tmp5 r14 ; must be saved and restored + %define tmp6 r15 ; must be saved and restored + %define return rax + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + push r14 + push r15 + %endmacro + %macro FUNC_RESTORE 0 + pop r15 + pop r14 + pop r13 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r12 ; must be saved and restored + %define tmp5 r14 ; must be saved and restored + %define tmp6 r15 ; must be saved and restored + %define return rax + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + push r14 + push r15 + %endmacro + %macro FUNC_RESTORE 0 + pop r15 + pop r14 + pop r13 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + + %define arg4 r12 ; must be saved, loaded and restored + %define arg5 r15 ; must be saved and restored + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r14 ; must be saved and restored + %define tmp5 rdi ; must be saved and restored + %define tmp6 rsi ; must be saved and restored + %define return rax + %define PS 8 + %define LOG_PS 3 + %define stack_size 10*16 + 7*8 ; must be an odd multiple of 8 + %define arg(x) [rsp + stack_size + PS + PS*x] + + %define func(x) proc_frame x + %macro FUNC_SAVE 0 + alloc_stack stack_size + vmovdqa [rsp + 0*16], xmm6 + vmovdqa [rsp + 1*16], xmm7 + vmovdqa [rsp + 2*16], xmm8 + vmovdqa [rsp + 3*16], xmm9 + vmovdqa [rsp + 4*16], xmm10 + vmovdqa [rsp + 5*16], xmm11 + vmovdqa [rsp + 6*16], xmm12 + vmovdqa [rsp + 7*16], xmm13 + vmovdqa [rsp + 8*16], xmm14 + vmovdqa [rsp + 9*16], xmm15 + save_reg r12, 10*16 + 0*8 + save_reg r13, 10*16 + 1*8 + save_reg r14, 10*16 + 2*8 + save_reg r15, 10*16 + 3*8 + save_reg rdi, 10*16 + 4*8 + save_reg rsi, 10*16 + 5*8 + end_prolog + mov arg4, arg(4) + %endmacro + + %macro FUNC_RESTORE 0 + vmovdqa xmm6, [rsp + 0*16] + vmovdqa xmm7, [rsp + 1*16] + vmovdqa xmm8, [rsp + 2*16] + vmovdqa xmm9, [rsp + 3*16] + vmovdqa xmm10, [rsp + 4*16] + vmovdqa xmm11, [rsp + 5*16] + vmovdqa xmm12, [rsp + 6*16] + vmovdqa xmm13, [rsp + 7*16] + vmovdqa xmm14, [rsp + 8*16] + vmovdqa xmm15, [rsp + 9*16] + mov r12, [rsp + 10*16 + 0*8] + mov r13, [rsp + 10*16 + 1*8] + mov r14, [rsp + 10*16 + 2*8] + mov r15, [rsp + 10*16 + 3*8] + mov rdi, [rsp + 10*16 + 4*8] + mov rsi, [rsp + 10*16 + 5*8] + add rsp, stack_size + %endmacro +%endif + +%define len arg0 +%define vec arg1 +%define mul_array arg2 +%define src arg3 +%define dest arg4 +%define ptr arg5 +%define vec_i tmp2 +%define dest1 tmp3 +%define dest2 tmp4 +%define vskip1 tmp5 +%define vskip3 tmp6 +%define pos return + + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR vmovdqu + %define XSTR vmovdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR vmovdqa + %define XSTR vmovdqa + %else + %define XLDR vmovntdqa + %define XSTR vmovntdq + %endif +%endif + +default rel + +[bits 64] +section .text + +%define xmask0f ymm15 +%define xmask0fx xmm15 +%define xgft1_lo ymm14 +%define xgft1_hi ymm13 +%define xgft2_lo ymm12 +%define xgft2_hi ymm11 +%define xgft3_lo ymm10 +%define xgft3_hi ymm9 +%define xgft4_lo ymm8 +%define xgft4_hi ymm7 + + +%define x0 ymm0 +%define xtmpa ymm1 +%define xp1 ymm2 +%define xp2 ymm3 +%define xp3 ymm4 +%define xp4 ymm5 +%define xp5 ymm6 + +align 16 +global GF_5VECT_DOT_PROD_AVX2:function +func(GF_5VECT_DOT_PROD_AVX2) + FUNC_SAVE + sub len, 32 + jl .return_fail + xor pos, pos + mov tmp.b, 0x0f + vpinsrb xmask0fx, xmask0fx, tmp.w, 0 + vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f... + mov vskip1, vec + imul vskip1, 32 + mov vskip3, vec + imul vskip3, 96 + sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS + mov dest1, [dest] + mov dest2, [dest+PS] + + +.loop32: + mov tmp, mul_array + xor vec_i, vec_i + vpxor xp1, xp1 + vpxor xp2, xp2 + vpxor xp3, xp3 + vpxor xp4, xp4 + vpxor xp5, xp5 + + +.next_vect: + mov ptr, [src+vec_i] + XLDR x0, [ptr+pos] ;Get next source vector + add vec_i, PS + + vpand xgft4_lo, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + vperm2i128 xtmpa, xgft4_lo, x0, 0x30 ;swap xtmpa from 1lo|2lo to 1lo|2hi + vperm2i128 x0, xgft4_lo, x0, 0x12 ;swap x0 from 1hi|2hi to 1hi|2lo + + vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} + ; " Ax{00}, Ax{10}, ..., Ax{f0} + vmovdqu xgft2_lo, [tmp+vskip1*1] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} + ; " Bx{00}, Bx{10}, ..., Bx{f0} + vmovdqu xgft3_lo, [tmp+vskip1*2] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} + ; " Cx{00}, Cx{10}, ..., Cx{f0} + vmovdqu xgft4_lo, [tmp+vskip3] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} + ; " Dx{00}, Dx{10}, ..., Dx{f0} + + vperm2i128 xgft1_hi, xgft1_lo, xgft1_lo, 0x01 ; swapped to hi | lo + vperm2i128 xgft2_hi, xgft2_lo, xgft2_lo, 0x01 ; swapped to hi | lo + vperm2i128 xgft3_hi, xgft3_lo, xgft3_lo, 0x01 ; swapped to hi | lo + vperm2i128 xgft4_hi, xgft4_lo, xgft4_lo, 0x01 ; swapped to hi | lo + + vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft1_hi, xgft1_lo ;GF add high and low partials + vpxor xp1, xgft1_hi ;xp1 += partial + + vpshufb xgft2_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft2_hi, xgft2_lo ;GF add high and low partials + vpxor xp2, xgft2_hi ;xp2 += partial + + vmovdqu xgft1_lo, [tmp+vskip1*4] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} + ; " Ex{00}, Ex{10}, ..., Ex{f0} + vperm2i128 xgft1_hi, xgft1_lo, xgft1_lo, 0x01 ; swapped to hi | lo + add tmp, 32 + + vpshufb xgft3_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft3_hi, xgft3_lo ;GF add high and low partials + vpxor xp3, xgft3_hi ;xp3 += partial + + vpshufb xgft4_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft4_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft4_hi, xgft4_lo ;GF add high and low partials + vpxor xp4, xgft4_hi ;xp4 += partial + + vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft1_hi, xgft1_lo ;GF add high and low partials + vpxor xp5, xgft1_hi ;xp5 += partial + + cmp vec_i, vec + jl .next_vect + + mov tmp, [dest+2*PS] + mov ptr, [dest+3*PS] + mov vec_i, [dest+4*PS] + + XSTR [dest1+pos], xp1 + XSTR [dest2+pos], xp2 + XSTR [tmp+pos], xp3 + XSTR [ptr+pos], xp4 + XSTR [vec_i+pos], xp5 + + add pos, 32 ;Loop on 32 bytes at a time + cmp pos, len + jle .loop32 + + lea tmp, [len + 32] + cmp pos, tmp + je .return_pass + + ;; Tail len + mov pos, len ;Overlapped offset length-16 + jmp .loop32 ;Do one more overlap pass + +.return_pass: + FUNC_RESTORE + mov return, 0 + ret + +.return_fail: + FUNC_RESTORE + mov return, 1 + ret + +endproc_frame + +section .data + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_5VECT_DOT_PROD_AVX2, 04, 03, 0199 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_5vect_dot_prod_sse.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_5vect_dot_prod_sse.asm new file mode 100644 index 000000000..ac3f65f28 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_5vect_dot_prod_sse.asm @@ -0,0 +1,349 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_5vect_dot_prod_sse(len, vec, *g_tbls, **buffs, **dests); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_5VECT_DOT_PROD_SSE _gf_5vect_dot_prod_sse +%else + %define GF_5VECT_DOT_PROD_SSE gf_5vect_dot_prod_sse +%endif + +%ifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r12 ; must be saved and restored + %define tmp5 r14 ; must be saved and restored + %define tmp6 r15 ; must be saved and restored + %define return rax + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + push r14 + push r15 + %endmacro + %macro FUNC_RESTORE 0 + pop r15 + pop r14 + pop r13 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r12 ; must be saved and restored + %define tmp5 r14 ; must be saved and restored + %define tmp6 r15 ; must be saved and restored + %define return rax + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + push r14 + push r15 + %endmacro + %macro FUNC_RESTORE 0 + pop r15 + pop r14 + pop r13 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + + %define arg4 r12 ; must be saved, loaded and restored + %define arg5 r15 ; must be saved and restored + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r14 ; must be saved and restored + %define tmp5 rdi ; must be saved and restored + %define tmp6 rsi ; must be saved and restored + %define return rax + %define PS 8 + %define LOG_PS 3 + %define stack_size 10*16 + 7*8 ; must be an odd multiple of 8 + %define arg(x) [rsp + stack_size + PS + PS*x] + + %define func(x) proc_frame x + %macro FUNC_SAVE 0 + alloc_stack stack_size + save_xmm128 xmm6, 0*16 + save_xmm128 xmm7, 1*16 + save_xmm128 xmm8, 2*16 + save_xmm128 xmm9, 3*16 + save_xmm128 xmm10, 4*16 + save_xmm128 xmm11, 5*16 + save_xmm128 xmm12, 6*16 + save_xmm128 xmm13, 7*16 + save_xmm128 xmm14, 8*16 + save_xmm128 xmm15, 9*16 + save_reg r12, 10*16 + 0*8 + save_reg r13, 10*16 + 1*8 + save_reg r14, 10*16 + 2*8 + save_reg r15, 10*16 + 3*8 + save_reg rdi, 10*16 + 4*8 + save_reg rsi, 10*16 + 5*8 + end_prolog + mov arg4, arg(4) + %endmacro + + %macro FUNC_RESTORE 0 + movdqa xmm6, [rsp + 0*16] + movdqa xmm7, [rsp + 1*16] + movdqa xmm8, [rsp + 2*16] + movdqa xmm9, [rsp + 3*16] + movdqa xmm10, [rsp + 4*16] + movdqa xmm11, [rsp + 5*16] + movdqa xmm12, [rsp + 6*16] + movdqa xmm13, [rsp + 7*16] + movdqa xmm14, [rsp + 8*16] + movdqa xmm15, [rsp + 9*16] + mov r12, [rsp + 10*16 + 0*8] + mov r13, [rsp + 10*16 + 1*8] + mov r14, [rsp + 10*16 + 2*8] + mov r15, [rsp + 10*16 + 3*8] + mov rdi, [rsp + 10*16 + 4*8] + mov rsi, [rsp + 10*16 + 5*8] + add rsp, stack_size + %endmacro +%endif + +%define len arg0 +%define vec arg1 +%define mul_array arg2 +%define src arg3 +%define dest arg4 +%define ptr arg5 +%define vec_i tmp2 +%define dest1 tmp3 +%define dest2 tmp4 +%define vskip1 tmp5 +%define vskip3 tmp6 +%define pos return + + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR movdqu + %define XSTR movdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR movdqa + %define XSTR movdqa + %else + %define XLDR movntdqa + %define XSTR movntdq + %endif +%endif + +default rel + +[bits 64] +section .text + +%define xmask0f xmm15 +%define xgft1_lo xmm2 +%define xgft1_hi xmm3 +%define xgft2_lo xmm4 +%define xgft2_hi xmm5 +%define xgft3_lo xmm10 +%define xgft3_hi xmm6 +%define xgft4_lo xmm8 +%define xgft4_hi xmm7 + + +%define x0 xmm0 +%define xtmpa xmm1 +%define xp1 xmm9 +%define xp2 xmm11 +%define xp3 xmm12 +%define xp4 xmm13 +%define xp5 xmm14 + +align 16 +global GF_5VECT_DOT_PROD_SSE:function +func(GF_5VECT_DOT_PROD_SSE) + FUNC_SAVE + sub len, 16 + jl .return_fail + xor pos, pos + movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + mov vskip1, vec + imul vskip1, 32 + mov vskip3, vec + imul vskip3, 96 + sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS + mov dest1, [dest] + mov dest2, [dest+PS] + + +.loop16: + mov tmp, mul_array + xor vec_i, vec_i + pxor xp1, xp1 + pxor xp2, xp2 + pxor xp3, xp3 + pxor xp4, xp4 + pxor xp5, xp5 + + +.next_vect: + mov ptr, [src+vec_i] + add vec_i, PS + XLDR x0, [ptr+pos] ;Get next source vector + + movdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} + movdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, ..., Ax{f0} + movdqu xgft2_lo, [tmp+vskip1*1] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} + movdqu xgft2_hi, [tmp+vskip1*1+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} + movdqu xgft3_lo, [tmp+vskip1*2] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} + movdqu xgft3_hi, [tmp+vskip1*2+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} + movdqu xgft4_lo, [tmp+vskip3] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} + movdqu xgft4_hi, [tmp+vskip3+16] ; " Dx{00}, Dx{10}, ..., Dx{f0} + + movdqa xtmpa, x0 ;Keep unshifted copy of src + psraw x0, 4 ;Shift to put high nibble into bits 4-0 + pand x0, xmask0f ;Mask high src nibble in bits 4-0 + pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 + + pshufb xgft1_hi, x0 ;Lookup mul table of high nibble + pshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft1_hi, xgft1_lo ;GF add high and low partials + pxor xp1, xgft1_hi ;xp1 += partial + + pshufb xgft2_hi, x0 ;Lookup mul table of high nibble + pshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft2_hi, xgft2_lo ;GF add high and low partials + pxor xp2, xgft2_hi ;xp2 += partial + + movdqu xgft1_lo, [tmp+vskip1*4] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} + movdqu xgft1_hi, [tmp+vskip1*4+16] ; " Ex{00}, Ex{10}, ..., Ex{f0} + add tmp, 32 + + pshufb xgft3_hi, x0 ;Lookup mul table of high nibble + pshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft3_hi, xgft3_lo ;GF add high and low partials + pxor xp3, xgft3_hi ;xp3 += partial + + pshufb xgft4_hi, x0 ;Lookup mul table of high nibble + pshufb xgft4_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft4_hi, xgft4_lo ;GF add high and low partials + pxor xp4, xgft4_hi ;xp4 += partial + + pshufb xgft1_hi, x0 ;Lookup mul table of high nibble + pshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft1_hi, xgft1_lo ;GF add high and low partials + pxor xp5, xgft1_hi ;xp5 += partial + + cmp vec_i, vec + jl .next_vect + + mov tmp, [dest+2*PS] + mov ptr, [dest+3*PS] + mov vec_i, [dest+4*PS] + + XSTR [dest1+pos], xp1 + XSTR [dest2+pos], xp2 + XSTR [tmp+pos], xp3 + XSTR [ptr+pos], xp4 + XSTR [vec_i+pos], xp5 + + add pos, 16 ;Loop on 16 bytes at a time + cmp pos, len + jle .loop16 + + lea tmp, [len + 16] + cmp pos, tmp + je .return_pass + + ;; Tail len + mov pos, len ;Overlapped offset length-16 + jmp .loop16 ;Do one more overlap pass + +.return_pass: + FUNC_RESTORE + mov return, 0 + ret + +.return_fail: + FUNC_RESTORE + mov return, 1 + ret + +endproc_frame + +section .data + +align 16 +mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_5VECT_DOT_PROD_SSE, 00, 04, 0065 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_5vect_mad_avx.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_5vect_mad_avx.asm new file mode 100644 index 000000000..427662d8d --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_5vect_mad_avx.asm @@ -0,0 +1,401 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_5vect_mad_avx(len, vec, vec_i, mul_array, src, dest); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_5VECT_MAD_AVX _gf_5vect_mad_avx +%else + %define GF_5VECT_MAD_AVX gf_5vect_mad_avx +%endif + +%define PS 8 + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg0.w ecx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + %define arg4 r12 + %define arg5 r15 + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 + %define tmp4 r14 + %define return rax + %define return.w eax + %define stack_size 16*10 + 5*8 + %define arg(x) [rsp + stack_size + PS + PS*x] + %define func(x) proc_frame x + +%macro FUNC_SAVE 0 + sub rsp, stack_size + movdqa [rsp+16*0],xmm6 + movdqa [rsp+16*1],xmm7 + movdqa [rsp+16*2],xmm8 + movdqa [rsp+16*3],xmm9 + movdqa [rsp+16*4],xmm10 + movdqa [rsp+16*5],xmm11 + movdqa [rsp+16*6],xmm12 + movdqa [rsp+16*7],xmm13 + movdqa [rsp+16*8],xmm14 + movdqa [rsp+16*9],xmm15 + save_reg r12, 10*16 + 0*8 + save_reg r13, 10*16 + 1*8 + save_reg r14, 10*16 + 2*8 + save_reg r15, 10*16 + 3*8 + end_prolog + mov arg4, arg(4) + mov arg5, arg(5) +%endmacro + +%macro FUNC_RESTORE 0 + movdqa xmm6, [rsp+16*0] + movdqa xmm7, [rsp+16*1] + movdqa xmm8, [rsp+16*2] + movdqa xmm9, [rsp+16*3] + movdqa xmm10, [rsp+16*4] + movdqa xmm11, [rsp+16*5] + movdqa xmm12, [rsp+16*6] + movdqa xmm13, [rsp+16*7] + movdqa xmm14, [rsp+16*8] + movdqa xmm15, [rsp+16*9] + mov r12, [rsp + 10*16 + 0*8] + mov r13, [rsp + 10*16 + 1*8] + mov r14, [rsp + 10*16 + 2*8] + mov r15, [rsp + 10*16 + 3*8] + add rsp, stack_size +%endmacro + +%elifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define tmp2 r10 + %define tmp3 r12 + %define tmp4 r13 + %define return rax + %define return.w eax + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + %endmacro + %macro FUNC_RESTORE 0 + pop r13 + pop r12 + %endmacro +%elifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define tmp2 r10 + %define tmp3 r12 + %define tmp4 r13 + %define return rax + %define return.w eax + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + %endmacro + %macro FUNC_RESTORE 0 + pop r13 + pop r12 + %endmacro +%endif + +;;; gf_5vect_mad_avx(len, vec, vec_i, mul_array, src, dest) +%define len arg0 +%define len.w arg0.w +%define vec arg1 +%define vec_i arg2 +%define mul_array arg3 +%define src arg4 +%define dest1 arg5 +%define pos return +%define pos.w return.w + +%define dest2 tmp4 +%define dest3 mul_array +%define dest4 tmp2 +%define dest5 vec_i + + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR vmovdqu + %define XSTR vmovdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR vmovdqa + %define XSTR vmovdqa + %else + %define XLDR vmovntdqa + %define XSTR vmovntdq + %endif +%endif + +default rel + +[bits 64] +section .text + +%define xmask0f xmm15 +%define xgft5_hi xmm14 +%define xgft4_lo xmm13 +%define xgft4_hi xmm12 + +%define x0 xmm0 +%define xtmpa xmm1 +%define xtmph1 xmm2 +%define xtmpl1 xmm3 +%define xtmph2 xmm4 +%define xtmpl2 xmm5 +%define xtmph3 xmm6 +%define xtmpl3 xmm7 +%define xtmph5 xmm8 +%define xtmpl5 xmm9 +%define xd1 xmm10 +%define xd2 xmm11 +%define xd3 xtmpl1 +%define xd4 xtmph1 +%define xd5 xtmpl2 + + +align 16 +global GF_5VECT_MAD_AVX:function +func(GF_5VECT_MAD_AVX) + FUNC_SAVE + sub len, 16 + jl .return_fail + xor pos, pos + vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + mov tmp, vec + sal vec_i, 5 ;Multiply by 32 + lea tmp3, [mul_array + vec_i] + sal tmp, 6 ;Multiply by 64 + vmovdqu xgft5_hi, [tmp3+2*tmp+16] ; " Ex{00}, Ex{10}, ..., Ex{f0} + sal vec, 5 ;Multiply by 32 + add tmp, vec + vmovdqu xgft4_hi, [tmp3+tmp+16] ; " Dx{00}, Dx{10}, Dx{20}, ... , Dx{f0} + vmovdqu xgft4_lo, [tmp3+tmp] ;Load array Dx{00}, Dx{01}, Dx{02}, ... + + mov dest3, [dest1+2*PS] ; reuse mul_array + mov dest4, [dest1+3*PS] + mov dest5, [dest1+4*PS] ; reuse vec_i + mov dest2, [dest1+PS] + mov dest1, [dest1] + +.loop16: + XLDR x0, [src+pos] ;Get next source vector + + vmovdqu xtmph1, [tmp3+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} + vmovdqu xtmpl1, [tmp3] ;Load array Ax{00}, Ax{01}, Ax{02}, ... + vmovdqu xtmph2, [tmp3+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} + vmovdqu xtmpl2, [tmp3+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... + vmovdqu xtmph3, [tmp3+2*vec+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} + vmovdqu xtmpl3, [tmp3+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... + vmovdqu xtmpl5, [tmp3+4*vec] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} + + XLDR xd1, [dest1+pos] ;Get next dest vector + XLDR xd2, [dest2+pos] ;Get next dest vector + + vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + + ; dest1 + vpshufb xtmph1, xtmph1, x0 ;Lookup mul table of high nibble + vpshufb xtmpl1, xtmpl1, xtmpa ;Lookup mul table of low nibble + vpxor xtmph1, xtmph1, xtmpl1 ;GF add high and low partials + vpxor xd1, xd1, xtmph1 + + XLDR xd3, [dest3+pos] ;Reuse xtmpl1, Get next dest vector + XLDR xd4, [dest4+pos] ;Reuse xtmph1, Get next dest vector + + ; dest2 + vpshufb xtmph2, xtmph2, x0 ;Lookup mul table of high nibble + vpshufb xtmpl2, xtmpl2, xtmpa ;Lookup mul table of low nibble + vpxor xtmph2, xtmph2, xtmpl2 ;GF add high and low partials + vpxor xd2, xd2, xtmph2 + + XLDR xd5, [dest5+pos] ;Reuse xtmpl2. Get next dest vector + + ; dest3 + vpshufb xtmph3, xtmph3, x0 ;Lookup mul table of high nibble + vpshufb xtmpl3, xtmpl3, xtmpa ;Lookup mul table of low nibble + vpxor xtmph3, xtmph3, xtmpl3 ;GF add high and low partials + vpxor xd3, xd3, xtmph3 + + ; dest4 + vpshufb xtmph2, xgft4_hi, x0 ;Lookup mul table of high nibble + vpshufb xtmpl3, xgft4_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph2, xtmph2, xtmpl3 ;GF add high and low partials + vpxor xd4, xd4, xtmph2 + + ; dest5 + vpshufb xtmph5, xgft5_hi, x0 ;Lookup mul table of high nibble + vpshufb xtmpl5, xtmpl5, xtmpa ;Lookup mul table of low nibble + vpxor xtmph5, xtmph5, xtmpl5 ;GF add high and low partials + vpxor xd5, xd5, xtmph5 + + XSTR [dest1+pos], xd1 ;Store result into dest1 + XSTR [dest2+pos], xd2 ;Store result into dest2 + XSTR [dest3+pos], xd3 ;Store result into dest3 + XSTR [dest4+pos], xd4 ;Store result into dest4 + XSTR [dest5+pos], xd5 ;Store result into dest5 + + add pos, 16 ;Loop on 16 bytes at a time + cmp pos, len + jle .loop16 + + lea tmp, [len + 16] + cmp pos, tmp + je .return_pass + +.lessthan16: + ;; Tail len + ;; Do one more overlap pass + mov tmp, len ;Overlapped offset length-16 + XLDR x0, [src+tmp] ;Get next source vector + + sub len, pos + + vmovdqa xtmph1, [constip16] ;Load const of i + 16 + vpinsrb xtmph5, len.w, 15 + vpshufb xtmph5, xmask0f ;Broadcast len to all bytes + vpcmpgtb xtmph5, xtmph5, xtmph1 + + vmovdqu xtmph1, [tmp3+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} + vmovdqu xtmpl1, [tmp3] ;Load array Ax{00}, Ax{01}, Ax{02}, ... + vmovdqu xtmph2, [tmp3+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} + vmovdqu xtmpl2, [tmp3+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... + vmovdqu xtmph3, [tmp3+2*vec+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} + vmovdqu xtmpl3, [tmp3+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... + vmovdqu xtmpl5, [tmp3+4*vec] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} + + XLDR xd1, [dest1+tmp] ;Get next dest vector + XLDR xd2, [dest2+tmp] ;Get next dest vector + + vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + + ; dest1 + vpshufb xtmph1, xtmph1, x0 ;Lookup mul table of high nibble + vpshufb xtmpl1, xtmpl1, xtmpa ;Lookup mul table of low nibble + vpxor xtmph1, xtmph1, xtmpl1 ;GF add high and low partials + vpand xtmph1, xtmph1, xtmph5 + vpxor xd1, xd1, xtmph1 + + XLDR xd3, [dest3+tmp] ;Reuse xtmpl1, Get next dest vector + XLDR xd4, [dest4+tmp] ;Reuse xtmph1, Get next dest vector + + ; dest2 + vpshufb xtmph2, xtmph2, x0 ;Lookup mul table of high nibble + vpshufb xtmpl2, xtmpl2, xtmpa ;Lookup mul table of low nibble + vpxor xtmph2, xtmph2, xtmpl2 ;GF add high and low partials + vpand xtmph2, xtmph2, xtmph5 + vpxor xd2, xd2, xtmph2 + + XLDR xd5, [dest5+tmp] ;Reuse xtmpl2. Get next dest vector + + ; dest3 + vpshufb xtmph3, xtmph3, x0 ;Lookup mul table of high nibble + vpshufb xtmpl3, xtmpl3, xtmpa ;Lookup mul table of low nibble + vpxor xtmph3, xtmph3, xtmpl3 ;GF add high and low partials + vpand xtmph3, xtmph3, xtmph5 + vpxor xd3, xd3, xtmph3 + + ; dest4 + vpshufb xgft4_hi, xgft4_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft4_lo, xgft4_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft4_hi, xgft4_hi, xgft4_lo ;GF add high and low partials + vpand xgft4_hi, xgft4_hi, xtmph5 + vpxor xd4, xd4, xgft4_hi + + ; dest5 + vpshufb xgft5_hi, xgft5_hi, x0 ;Lookup mul table of high nibble + vpshufb xtmpl5, xtmpl5, xtmpa ;Lookup mul table of low nibble + vpxor xgft5_hi, xgft5_hi, xtmpl5 ;GF add high and low partials + vpand xgft5_hi, xgft5_hi, xtmph5 + vpxor xd5, xd5, xgft5_hi + + XSTR [dest1+tmp], xd1 ;Store result into dest1 + XSTR [dest2+tmp], xd2 ;Store result into dest2 + XSTR [dest3+tmp], xd3 ;Store result into dest3 + XSTR [dest4+tmp], xd4 ;Store result into dest4 + XSTR [dest5+tmp], xd5 ;Store result into dest5 + +.return_pass: + FUNC_RESTORE + mov return, 0 + ret + +.return_fail: + FUNC_RESTORE + mov return, 1 + ret + +endproc_frame + +section .data + +align 16 +mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f +constip16: + ddq 0xf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_5VECT_MAD_AVX, 02, 00, 020d diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_5vect_mad_avx2.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_5vect_mad_avx2.asm new file mode 100644 index 000000000..1b236e9a7 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_5vect_mad_avx2.asm @@ -0,0 +1,393 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_5vect_mad_avx2(len, vec, vec_i, mul_array, src, dest); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_5VECT_MAD_AVX2 _gf_5vect_mad_avx2 +%else + %define GF_5VECT_MAD_AVX2 gf_5vect_mad_avx2 +%endif + +%define PS 8 + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg0.w ecx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + %define arg4 r12 + %define arg5 r15 + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define return rax + %define return.w eax + %define stack_size 16*10 + 3*8 + %define arg(x) [rsp + stack_size + PS + PS*x] + %define func(x) proc_frame x + +%macro FUNC_SAVE 0 + sub rsp, stack_size + movdqa [rsp+16*0],xmm6 + movdqa [rsp+16*1],xmm7 + movdqa [rsp+16*2],xmm8 + movdqa [rsp+16*3],xmm9 + movdqa [rsp+16*4],xmm10 + movdqa [rsp+16*5],xmm11 + movdqa [rsp+16*6],xmm12 + movdqa [rsp+16*7],xmm13 + movdqa [rsp+16*8],xmm14 + movdqa [rsp+16*9],xmm15 + save_reg r12, 10*16 + 0*8 + save_reg r15, 10*16 + 1*8 + end_prolog + mov arg4, arg(4) + mov arg5, arg(5) +%endmacro + +%macro FUNC_RESTORE 0 + movdqa xmm6, [rsp+16*0] + movdqa xmm7, [rsp+16*1] + movdqa xmm8, [rsp+16*2] + movdqa xmm9, [rsp+16*3] + movdqa xmm10, [rsp+16*4] + movdqa xmm11, [rsp+16*5] + movdqa xmm12, [rsp+16*6] + movdqa xmm13, [rsp+16*7] + movdqa xmm14, [rsp+16*8] + movdqa xmm15, [rsp+16*9] + mov r12, [rsp + 10*16 + 0*8] + mov r15, [rsp + 10*16 + 1*8] + add rsp, stack_size +%endmacro + +%elifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define return rax + %define return.w eax + + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%elifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define return rax + %define return.w eax + + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%endif + +;;; gf_5vect_mad_avx2(len, vec, vec_i, mul_array, src, dest) +%define len arg0 +%define len.w arg0.w +%define vec arg1 +%define vec_i arg2 +%define mul_array arg3 +%define src arg4 +%define dest1 arg5 +%define pos return +%define pos.w return.w + +%define dest2 tmp2 +%define dest3 mul_array +%define dest4 vec +%define dest5 vec_i + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR vmovdqu + %define XSTR vmovdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR vmovdqa + %define XSTR vmovdqa + %else + %define XLDR vmovntdqa + %define XSTR vmovntdq + %endif +%endif + +default rel + +[bits 64] +section .text + +%define xmask0f ymm15 +%define xmask0fx xmm15 +%define xgft1_lo ymm14 +%define xgft2_lo ymm13 +%define xgft3_lo ymm12 +%define xgft4_lo ymm11 +%define xgft5_lo ymm10 + +%define x0 ymm0 +%define xtmpa ymm1 +%define xtmpl ymm2 +%define xtmplx xmm2 +%define xtmph1 ymm3 +%define xtmph1x xmm3 +%define xtmph2 ymm4 +%define xd1 ymm5 +%define xd2 ymm6 +%define xd3 ymm7 +%define xd4 ymm8 +%define xd5 ymm9 + +align 16 +global GF_5VECT_MAD_AVX2:function +func(GF_5VECT_MAD_AVX2) + FUNC_SAVE + sub len, 32 + jl .return_fail + xor pos, pos + mov tmp.b, 0x0f + vpinsrb xmask0fx, xmask0fx, tmp.w, 0 + vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f... + + sal vec_i, 5 ;Multiply by 32 + sal vec, 5 ;Multiply by 32 + lea tmp, [mul_array + vec_i] + + vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} + ; " Ax{00}, Ax{10}, ..., Ax{f0} + vmovdqu xgft2_lo, [tmp+vec] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} + ; " Bx{00}, Bx{10}, ..., Bx{f0} + vmovdqu xgft3_lo, [tmp+2*vec] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} + ; " Cx{00}, Cx{10}, ..., Cx{f0} + vmovdqu xgft5_lo, [tmp+4*vec] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} + ; " Ex{00}, Ex{10}, ..., Ex{f0} + add tmp, vec + vmovdqu xgft4_lo, [tmp+2*vec] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} + ; " Dx{00}, Dx{10}, ..., Dx{f0} + + mov dest3, [dest1+2*PS] ; reuse mul_array + mov dest4, [dest1+3*PS] ; reuse vec + mov dest5, [dest1+4*PS] ; reuse vec_i + mov dest2, [dest1+PS] + mov dest1, [dest1] + +.loop32: + XLDR x0, [src+pos] ;Get next source vector + + XLDR xd1, [dest1+pos] ;Get next dest vector + XLDR xd2, [dest2+pos] ;Get next dest vector + XLDR xd3, [dest3+pos] ;Get next dest vector + XLDR xd4, [dest4+pos] ;Get next dest vector + XLDR xd5, [dest5+pos] ;Get next dest vector + + vpand xtmpl, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + vperm2i128 xtmpa, xtmpl, x0, 0x30 ;swap xtmpa from 1lo|2lo to 1lo|2hi + vperm2i128 x0, xtmpl, x0, 0x12 ;swap x0 from 1hi|2hi to 1hi|2lo + + vperm2i128 xtmph1, xgft1_lo, xgft1_lo, 0x01 ; swapped to hi | lo + vperm2i128 xtmph2, xgft2_lo, xgft2_lo, 0x01 ; swapped to hi | lo + + ; dest1 + vpshufb xtmph1, xtmph1, x0 ;Lookup mul table of high nibble + vpshufb xtmpl, xgft1_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph1, xtmph1, xtmpl ;GF add high and low partials + vpxor xd1, xd1, xtmph1 ;xd1 += partial + + vperm2i128 xtmph1, xgft3_lo, xgft3_lo, 0x01 ; swapped to hi | lo + ; dest2 + vpshufb xtmph2, xtmph2, x0 ;Lookup mul table of high nibble + vpshufb xtmpl, xgft2_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph2, xtmph2, xtmpl ;GF add high and low partials + vpxor xd2, xd2, xtmph2 ;xd2 += partial + + vperm2i128 xtmph2, xgft4_lo, xgft4_lo, 0x01 ; swapped to hi | lo + ; dest3 + vpshufb xtmph1, xtmph1, x0 ;Lookup mul table of high nibble + vpshufb xtmpl, xgft3_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph1, xtmph1, xtmpl ;GF add high and low partials + vpxor xd3, xd3, xtmph1 ;xd3 += partial + + vperm2i128 xtmph1, xgft5_lo, xgft5_lo, 0x01 ; swapped to hi | lo + ; dest4 + vpshufb xtmph2, xtmph2, x0 ;Lookup mul table of high nibble + vpshufb xtmpl, xgft4_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph2, xtmph2, xtmpl ;GF add high and low partials + vpxor xd4, xd4, xtmph2 ;xd4 += partial + + ; dest5 + vpshufb xtmph1, xtmph1, x0 ;Lookup mul table of high nibble + vpshufb xtmpl, xgft5_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph1, xtmph1, xtmpl ;GF add high and low partials + vpxor xd5, xd5, xtmph1 ;xd5 += partial + + XSTR [dest1+pos], xd1 + XSTR [dest2+pos], xd2 + XSTR [dest3+pos], xd3 + XSTR [dest4+pos], xd4 + XSTR [dest5+pos], xd5 + + add pos, 32 ;Loop on 32 bytes at a time + cmp pos, len + jle .loop32 + + lea tmp, [len + 32] + cmp pos, tmp + je .return_pass + +.lessthan32: + ;; Tail len + ;; Do one more overlap pass + mov tmp.b, 0x1f + vpinsrb xtmph1x, xtmph1x, tmp.w, 0 + vpbroadcastb xtmph1, xtmph1x ;Construct mask 0x1f1f1f... + + mov tmp, len ;Overlapped offset length-32 + + XLDR x0, [src+tmp] ;Get next source vector + + XLDR xd1, [dest1+tmp] ;Get next dest vector + XLDR xd2, [dest2+tmp] ;Get next dest vector + XLDR xd3, [dest3+tmp] ;Get next dest vector + XLDR xd4, [dest4+tmp] ;Get next dest vector + XLDR xd5, [dest5+tmp] ;Get next dest vector + + sub len, pos + + vmovdqa xtmph2, [constip32] ;Load const of i + 32 + vpinsrb xtmplx, xtmplx, len.w, 15 + vinserti128 xtmpl, xtmpl, xtmplx, 1 ;swapped to xtmplx | xtmplx + vpshufb xtmpl, xtmpl, xtmph1 ;Broadcast len to all bytes. xtmph1=0x1f1f1f... + vpcmpgtb xtmpl, xtmpl, xtmph2 + + vpand xtmph1, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + vperm2i128 xtmpa, xtmph1, x0, 0x30 ;swap xtmpa from 1lo|2lo to 1lo|2hi + vperm2i128 x0, xtmph1, x0, 0x12 ;swap x0 from 1hi|2hi to 1hi|2lo + + vperm2i128 xtmph1, xgft1_lo, xgft1_lo, 0x01 ; swapped to hi | lo + vperm2i128 xtmph2, xgft2_lo, xgft2_lo, 0x01 ; swapped to hi | lo + + ; dest1 + vpshufb xtmph1, xtmph1, x0 ;Lookup mul table of high nibble + vpshufb xgft1_lo, xgft1_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph1, xtmph1, xgft1_lo ;GF add high and low partials + vpand xtmph1, xtmph1, xtmpl + vpxor xd1, xd1, xtmph1 ;xd1 += partial + + vperm2i128 xtmph1, xgft3_lo, xgft3_lo, 0x01 ; swapped to hi | lo + ; dest2 + vpshufb xtmph2, xtmph2, x0 ;Lookup mul table of high nibble + vpshufb xgft2_lo, xgft2_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph2, xtmph2, xgft2_lo ;GF add high and low partials + vpand xtmph2, xtmph2, xtmpl + vpxor xd2, xd2, xtmph2 ;xd2 += partial + + vperm2i128 xtmph2, xgft4_lo, xgft4_lo, 0x01 ; swapped to hi | lo + ; dest3 + vpshufb xtmph1, xtmph1, x0 ;Lookup mul table of high nibble + vpshufb xgft3_lo, xgft3_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph1, xtmph1, xgft3_lo ;GF add high and low partials + vpand xtmph1, xtmph1, xtmpl + vpxor xd3, xd3, xtmph1 ;xd3 += partial + + vperm2i128 xtmph1, xgft5_lo, xgft5_lo, 0x01 ; swapped to hi | lo + ; dest4 + vpshufb xtmph2, xtmph2, x0 ;Lookup mul table of high nibble + vpshufb xgft4_lo, xgft4_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph2, xtmph2, xgft4_lo ;GF add high and low partials + vpand xtmph2, xtmph2, xtmpl + vpxor xd4, xd4, xtmph2 ;xd4 += partial + + ; dest5 + vpshufb xtmph1, xtmph1, x0 ;Lookup mul table of high nibble + vpshufb xgft5_lo, xgft5_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph1, xtmph1, xgft5_lo ;GF add high and low partials + vpand xtmph1, xtmph1, xtmpl + vpxor xd5, xd5, xtmph1 ;xd5 += partial + + XSTR [dest1+tmp], xd1 + XSTR [dest2+tmp], xd2 + XSTR [dest3+tmp], xd3 + XSTR [dest4+tmp], xd4 + XSTR [dest5+tmp], xd5 + +.return_pass: + FUNC_RESTORE + mov return, 0 + ret + +.return_fail: + FUNC_RESTORE + mov return, 1 + ret + +endproc_frame + +section .data +align 32 +constip32: + ddq 0xf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff + ddq 0xe0e1e2e3e4e5e6e7e8e9eaebecedeeef + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_5VECT_MAD_AVX2, 04, 00, 020e diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_5vect_mad_sse.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_5vect_mad_sse.asm new file mode 100644 index 000000000..3137f9e55 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_5vect_mad_sse.asm @@ -0,0 +1,409 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_5vect_mad_sse(len, vec, vec_i, mul_array, src, dest); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_5VECT_MAD_SSE _gf_5vect_mad_sse +%else + %define GF_5VECT_MAD_SSE gf_5vect_mad_sse +%endif + +%define PS 8 + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg0.w ecx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + %define arg4 r12 + %define arg5 r15 + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 + %define tmp4 r14 + %define return rax + %define return.w eax + %define stack_size 16*10 + 5*8 + %define arg(x) [rsp + stack_size + PS + PS*x] + %define func(x) proc_frame x + +%macro FUNC_SAVE 0 + sub rsp, stack_size + movdqa [rsp+16*0],xmm6 + movdqa [rsp+16*1],xmm7 + movdqa [rsp+16*2],xmm8 + movdqa [rsp+16*3],xmm9 + movdqa [rsp+16*4],xmm10 + movdqa [rsp+16*5],xmm11 + movdqa [rsp+16*6],xmm12 + movdqa [rsp+16*7],xmm13 + movdqa [rsp+16*8],xmm14 + movdqa [rsp+16*9],xmm15 + save_reg r12, 10*16 + 0*8 + save_reg r13, 10*16 + 1*8 + save_reg r14, 10*16 + 2*8 + save_reg r15, 10*16 + 3*8 + end_prolog + mov arg4, arg(4) + mov arg5, arg(5) +%endmacro + +%macro FUNC_RESTORE 0 + movdqa xmm6, [rsp+16*0] + movdqa xmm7, [rsp+16*1] + movdqa xmm8, [rsp+16*2] + movdqa xmm9, [rsp+16*3] + movdqa xmm10, [rsp+16*4] + movdqa xmm11, [rsp+16*5] + movdqa xmm12, [rsp+16*6] + movdqa xmm13, [rsp+16*7] + movdqa xmm14, [rsp+16*8] + movdqa xmm15, [rsp+16*9] + mov r12, [rsp + 10*16 + 0*8] + mov r13, [rsp + 10*16 + 1*8] + mov r14, [rsp + 10*16 + 2*8] + mov r15, [rsp + 10*16 + 3*8] + add rsp, stack_size +%endmacro + +%elifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define tmp2 r10 + %define tmp3 r12 + %define tmp4 r13 + %define return rax + %define return.w eax + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + %endmacro + %macro FUNC_RESTORE 0 + pop r13 + pop r12 + %endmacro +%elifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define tmp2 r10 + %define tmp3 r12 + %define tmp4 r13 + %define return rax + %define return.w eax + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + %endmacro + %macro FUNC_RESTORE 0 + pop r13 + pop r12 + %endmacro +%endif + +;;; gf_5vect_mad_sse(len, vec, vec_i, mul_array, src, dest) +%define len arg0 +%define len.w arg0.w +%define vec arg1 +%define vec_i arg2 +%define mul_array arg3 +%define src arg4 +%define dest1 arg5 +%define pos return +%define pos.w return.w + +%define dest2 tmp4 +%define dest3 mul_array +%define dest4 tmp2 +%define dest5 vec_i + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR movdqu + %define XSTR movdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR movdqa + %define XSTR movdqa + %else + %define XLDR movntdqa + %define XSTR movntdq + %endif +%endif + +default rel + +[bits 64] +section .text + +%define xmask0f xmm15 +%define xgft5_hi xmm14 +%define xgft4_lo xmm13 +%define xgft4_hi xmm12 + +%define x0 xmm0 +%define xtmpa xmm1 +%define xtmph1 xmm2 +%define xtmpl1 xmm3 +%define xtmph2 xmm4 +%define xtmpl2 xmm5 +%define xtmph3 xmm6 +%define xtmpl3 xmm7 +%define xtmph5 xmm8 +%define xtmpl5 xmm9 +%define xd1 xmm10 +%define xd2 xmm11 +%define xd3 xtmpl1 +%define xd4 xtmph1 +%define xd5 xtmpl2 + + +align 16 +global GF_5VECT_MAD_SSE:function +func(GF_5VECT_MAD_SSE) + FUNC_SAVE + sub len, 16 + jl .return_fail + xor pos, pos + + movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + mov tmp, vec + sal vec_i, 5 ;Multiply by 32 + lea tmp3, [mul_array + vec_i] + sal tmp, 6 ;Multiply by 64 + movdqu xgft5_hi, [tmp3+2*tmp+16] ; " Ex{00}, Ex{10}, ..., Ex{f0} + sal vec, 5 ;Multiply by 32 + add tmp, vec + movdqu xgft4_hi, [tmp3+tmp+16] ; " Dx{00}, Dx{10}, Dx{20}, ... , Dx{f0} + movdqu xgft4_lo, [tmp3+tmp] ;Load array Dx{00}, Dx{01}, Dx{02}, ... + + mov dest3, [dest1+2*PS] ; reuse mul_array + mov dest4, [dest1+3*PS] + mov dest5, [dest1+4*PS] ; reuse vec_i + mov dest2, [dest1+PS] + mov dest1, [dest1] + +.loop16: + XLDR x0, [src+pos] ;Get next source vector + + movdqu xtmph1, [tmp3+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} + movdqu xtmpl1, [tmp3] ;Load array Ax{00}, Ax{01}, Ax{02}, ... + movdqu xtmph2, [tmp3+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} + movdqu xtmpl2, [tmp3+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... + movdqu xtmph3, [tmp3+2*vec+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} + movdqu xtmpl3, [tmp3+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... + movdqu xtmpl5, [tmp3+4*vec] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} + movdqa xtmph5, xgft5_hi ;Reload const array registers + + XLDR xd1, [dest1+pos] ;Get next dest vector + XLDR xd2, [dest2+pos] ;Get next dest vector + + movdqa xtmpa, x0 ;Keep unshifted copy of src + psraw x0, 4 ;Shift to put high nibble into bits 4-0 + pand x0, xmask0f ;Mask high src nibble in bits 4-0 + pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 + + ; dest1 + pshufb xtmph1, x0 ;Lookup mul table of high nibble + pshufb xtmpl1, xtmpa ;Lookup mul table of low nibble + pxor xtmph1, xtmpl1 ;GF add high and low partials + pxor xd1, xtmph1 + + XLDR xd3, [dest3+pos] ;Reuse xtmpl1, Get next dest vector + XLDR xd4, [dest4+pos] ;Reuse xtmph1. Get next dest vector + + ; dest2 + pshufb xtmph2, x0 ;Lookup mul table of high nibble + pshufb xtmpl2, xtmpa ;Lookup mul table of low nibble + pxor xtmph2, xtmpl2 ;GF add high and low partials + pxor xd2, xtmph2 + + XLDR xd5, [dest5+pos] ;Reuse xtmpl2. Get next dest vector + + ; dest3 + pshufb xtmph3, x0 ;Lookup mul table of high nibble + pshufb xtmpl3, xtmpa ;Lookup mul table of low nibble + pxor xtmph3, xtmpl3 ;GF add high and low partials + pxor xd3, xtmph3 + + movdqa xtmph2, xgft4_hi ;Reload const array registers + movdqa xtmpl3, xgft4_lo ;Reload const array registers + + ; dest5 + pshufb xtmph5, x0 ;Lookup mul table of high nibble + pshufb xtmpl5, xtmpa ;Lookup mul table of low nibble + pxor xtmph5, xtmpl5 ;GF add high and low partials + pxor xd5, xtmph5 + + ; dest4 + pshufb xtmph2, x0 ;Lookup mul table of high nibble + pshufb xtmpl3, xtmpa ;Lookup mul table of low nibble + pxor xtmph2, xtmpl3 ;GF add high and low partials + pxor xd4, xtmph2 + + XSTR [dest1+pos], xd1 ;Store result into dest1 + XSTR [dest2+pos], xd2 ;Store result into dest2 + XSTR [dest3+pos], xd3 ;Store result into dest3 + XSTR [dest4+pos], xd4 ;Store result into dest4 + XSTR [dest5+pos], xd5 ;Store result into dest5 + + add pos, 16 ;Loop on 16 bytes at a time + cmp pos, len + jle .loop16 + + lea tmp, [len + 16] + cmp pos, tmp + je .return_pass + +.lessthan16: + ;; Tail len + ;; Do one more overlap pass + mov tmp, len ;Overlapped offset length-16 + XLDR x0, [src+tmp] ;Get next source vector + + sub len, pos + + movdqa xtmpl1, [constip16] ;Load const of i + 16 + pinsrb xtmph5, len.w, 15 + pshufb xtmph5, xmask0f ;Broadcast len to all bytes + pcmpgtb xtmph5, xtmpl1 + + movdqu xtmph1, [tmp3+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} + movdqu xtmpl1, [tmp3] ;Load array Ax{00}, Ax{01}, Ax{02}, ... + movdqu xtmph2, [tmp3+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} + movdqu xtmpl2, [tmp3+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... + movdqu xtmph3, [tmp3+2*vec+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} + movdqu xtmpl3, [tmp3+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... + movdqu xtmpl5, [tmp3+4*vec] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} + + XLDR xd1, [dest1+tmp] ;Get next dest vector + XLDR xd2, [dest2+tmp] ;Get next dest vector + + movdqa xtmpa, x0 ;Keep unshifted copy of src + psraw x0, 4 ;Shift to put high nibble into bits 4-0 + pand x0, xmask0f ;Mask high src nibble in bits 4-0 + pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 + + ; dest1 + pshufb xtmph1, x0 ;Lookup mul table of high nibble + pshufb xtmpl1, xtmpa ;Lookup mul table of low nibble + pxor xtmph1, xtmpl1 ;GF add high and low partials + pand xtmph1, xtmph5 + pxor xd1, xtmph1 + + XLDR xd3, [dest3+tmp] ;Reuse xtmpl1, Get next dest vector + XLDR xd4, [dest4+tmp] ;Reuse xtmph1. Get next dest vector + + ; dest2 + pshufb xtmph2, x0 ;Lookup mul table of high nibble + pshufb xtmpl2, xtmpa ;Lookup mul table of low nibble + pxor xtmph2, xtmpl2 ;GF add high and low partials + pand xtmph2, xtmph5 + pxor xd2, xtmph2 + + XLDR xd5, [dest5+tmp] ;Reuse xtmpl2. Get next dest vector + + ; dest3 + pshufb xtmph3, x0 ;Lookup mul table of high nibble + pshufb xtmpl3, xtmpa ;Lookup mul table of low nibble + pxor xtmph3, xtmpl3 ;GF add high and low partials + pand xtmph3, xtmph5 + pxor xd3, xtmph3 + + ; dest4 + pshufb xgft4_hi, x0 ;Lookup mul table of high nibble + pshufb xgft4_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft4_hi, xgft4_lo ;GF add high and low partials + pand xgft4_hi, xtmph5 + pxor xd4, xgft4_hi + + ; dest5 + pshufb xgft5_hi, x0 ;Lookup mul table of high nibble + pshufb xtmpl5, xtmpa ;Lookup mul table of low nibble + pxor xgft5_hi, xtmpl5 ;GF add high and low partials + pand xgft5_hi, xtmph5 + pxor xd5, xgft5_hi + + XSTR [dest1+tmp], xd1 ;Store result into dest1 + XSTR [dest2+tmp], xd2 ;Store result into dest2 + XSTR [dest3+tmp], xd3 ;Store result into dest3 + XSTR [dest4+tmp], xd4 ;Store result into dest4 + XSTR [dest5+tmp], xd5 ;Store result into dest5 + +.return_pass: + FUNC_RESTORE + mov return, 0 + ret + +.return_fail: + FUNC_RESTORE + mov return, 1 + ret + +endproc_frame + +section .data + +align 16 + +mask0f: + ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f +constip16: + ddq 0xf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_5VECT_MAD_SSE, 00, 00, 020c diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_6vect_dot_prod_avx.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_6vect_dot_prod_avx.asm new file mode 100644 index 000000000..34c0bdafb --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_6vect_dot_prod_avx.asm @@ -0,0 +1,360 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_6vect_dot_prod_avx(len, vec, *g_tbls, **buffs, **dests); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_6VECT_DOT_PROD_AVX _gf_6vect_dot_prod_avx +%else + %define GF_6VECT_DOT_PROD_AVX gf_6vect_dot_prod_avx +%endif + +%ifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r12 ; must be saved and restored + %define tmp5 r14 ; must be saved and restored + %define tmp6 r15 ; must be saved and restored + %define return rax + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + push r14 + push r15 + %endmacro + %macro FUNC_RESTORE 0 + pop r15 + pop r14 + pop r13 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r12 ; must be saved and restored + %define tmp5 r14 ; must be saved and restored + %define tmp6 r15 ; must be saved and restored + %define return rax + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + push r14 + push r15 + %endmacro + %macro FUNC_RESTORE 0 + pop r15 + pop r14 + pop r13 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + + %define arg4 r12 ; must be saved, loaded and restored + %define arg5 r15 ; must be saved and restored + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r14 ; must be saved and restored + %define tmp5 rdi ; must be saved and restored + %define tmp6 rsi ; must be saved and restored + %define return rax + %define PS 8 + %define LOG_PS 3 + %define stack_size 10*16 + 7*8 ; must be an odd multiple of 8 + %define arg(x) [rsp + stack_size + PS + PS*x] + + %define func(x) proc_frame x + %macro FUNC_SAVE 0 + alloc_stack stack_size + save_xmm128 xmm6, 0*16 + save_xmm128 xmm7, 1*16 + save_xmm128 xmm8, 2*16 + save_xmm128 xmm9, 3*16 + save_xmm128 xmm10, 4*16 + save_xmm128 xmm11, 5*16 + save_xmm128 xmm12, 6*16 + save_xmm128 xmm13, 7*16 + save_xmm128 xmm14, 8*16 + save_xmm128 xmm15, 9*16 + save_reg r12, 10*16 + 0*8 + save_reg r13, 10*16 + 1*8 + save_reg r14, 10*16 + 2*8 + save_reg r15, 10*16 + 3*8 + save_reg rdi, 10*16 + 4*8 + save_reg rsi, 10*16 + 5*8 + end_prolog + mov arg4, arg(4) + %endmacro + + %macro FUNC_RESTORE 0 + vmovdqa xmm6, [rsp + 0*16] + vmovdqa xmm7, [rsp + 1*16] + vmovdqa xmm8, [rsp + 2*16] + vmovdqa xmm9, [rsp + 3*16] + vmovdqa xmm10, [rsp + 4*16] + vmovdqa xmm11, [rsp + 5*16] + vmovdqa xmm12, [rsp + 6*16] + vmovdqa xmm13, [rsp + 7*16] + vmovdqa xmm14, [rsp + 8*16] + vmovdqa xmm15, [rsp + 9*16] + mov r12, [rsp + 10*16 + 0*8] + mov r13, [rsp + 10*16 + 1*8] + mov r14, [rsp + 10*16 + 2*8] + mov r15, [rsp + 10*16 + 3*8] + mov rdi, [rsp + 10*16 + 4*8] + mov rsi, [rsp + 10*16 + 5*8] + add rsp, stack_size + %endmacro +%endif + +%define len arg0 +%define vec arg1 +%define mul_array arg2 +%define src arg3 +%define dest arg4 +%define ptr arg5 +%define vec_i tmp2 +%define dest1 tmp3 +%define dest2 tmp4 +%define vskip1 tmp5 +%define vskip3 tmp6 +%define pos return + + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR vmovdqu + %define XSTR vmovdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR vmovdqa + %define XSTR vmovdqa + %else + %define XLDR vmovntdqa + %define XSTR vmovntdq + %endif +%endif + + +default rel + +[bits 64] +section .text + +%define xmask0f xmm15 +%define xgft1_lo xmm14 +%define xgft1_hi xmm13 +%define xgft2_lo xmm12 +%define xgft2_hi xmm11 +%define xgft3_lo xmm10 +%define xgft3_hi xmm9 +%define x0 xmm0 +%define xtmpa xmm1 +%define xp1 xmm2 +%define xp2 xmm3 +%define xp3 xmm4 +%define xp4 xmm5 +%define xp5 xmm6 +%define xp6 xmm7 + +align 16 +global GF_6VECT_DOT_PROD_AVX:function +func(GF_6VECT_DOT_PROD_AVX) + FUNC_SAVE + sub len, 16 + jl .return_fail + xor pos, pos + vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + mov vskip1, vec + imul vskip1, 32 + mov vskip3, vec + imul vskip3, 96 + sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS + mov dest1, [dest] + mov dest2, [dest+PS] + + +.loop16: + mov tmp, mul_array + xor vec_i, vec_i + vpxor xp1, xp1 + vpxor xp2, xp2 + vpxor xp3, xp3 + vpxor xp4, xp4 + vpxor xp5, xp5 + vpxor xp6, xp6 + +.next_vect: + mov ptr, [src+vec_i] + add vec_i, PS + XLDR x0, [ptr+pos] ;Get next source vector + + vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} + vmovdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, ..., Ax{f0} + vmovdqu xgft2_lo, [tmp+vskip1*1] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} + vmovdqu xgft2_hi, [tmp+vskip1*1+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} + vmovdqu xgft3_lo, [tmp+vskip1*2] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} + vmovdqu xgft3_hi, [tmp+vskip1*2+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} + lea ptr, [vskip1 + vskip1*4] ;ptr = vskip5 + + vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + + + vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft1_hi, xgft1_lo ;GF add high and low partials + vpxor xp1, xgft1_hi ;xp1 += partial + + vpshufb xgft2_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft2_hi, xgft2_lo ;GF add high and low partials + vpxor xp2, xgft2_hi ;xp2 += partial + + vpshufb xgft3_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft3_hi, xgft3_lo ;GF add high and low partials + vpxor xp3, xgft3_hi ;xp3 += partial + + + vmovdqu xgft1_lo, [tmp+vskip3] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} + vmovdqu xgft1_hi, [tmp+vskip3+16] ; " Dx{00}, Dx{10}, ..., Dx{f0} + vmovdqu xgft2_lo, [tmp+vskip1*4] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} + vmovdqu xgft2_hi, [tmp+vskip1*4+16] ; " Ex{00}, Ex{10}, ..., Ex{f0} + vmovdqu xgft3_lo, [tmp+ptr] ;Load array Fx{00}, Fx{01}, ..., Fx{0f} + vmovdqu xgft3_hi, [tmp+ptr+16] ; " Fx{00}, Fx{10}, ..., Fx{f0} + add tmp, 32 + + + vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft1_hi, xgft1_lo ;GF add high and low partials + vpxor xp4, xgft1_hi ;xp4 += partial + + vpshufb xgft2_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft2_hi, xgft2_lo ;GF add high and low partials + vpxor xp5, xgft2_hi ;xp5 += partial + + vpshufb xgft3_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft3_hi, xgft3_lo ;GF add high and low partials + vpxor xp6, xgft3_hi ;xp6 += partial + + cmp vec_i, vec + jl .next_vect + + + mov tmp, [dest+2*PS] + mov ptr, [dest+3*PS] + mov vec_i, [dest+4*PS] + + XSTR [dest1+pos], xp1 + XSTR [dest2+pos], xp2 + XSTR [tmp+pos], xp3 + mov tmp, [dest+5*PS] + XSTR [ptr+pos], xp4 + XSTR [vec_i+pos], xp5 + XSTR [tmp+pos], xp6 + + add pos, 16 ;Loop on 16 bytes at a time + cmp pos, len + jle .loop16 + + lea tmp, [len + 16] + cmp pos, tmp + je .return_pass + + ;; Tail len + mov pos, len ;Overlapped offset length-16 + jmp .loop16 ;Do one more overlap pass + +.return_pass: + FUNC_RESTORE + mov return, 0 + ret + +.return_fail: + FUNC_RESTORE + mov return, 1 + ret + +endproc_frame + +section .data + +align 16 +mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_6VECT_DOT_PROD_AVX, 02, 03, 0195 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_6vect_dot_prod_avx2.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_6vect_dot_prod_avx2.asm new file mode 100644 index 000000000..9a020f70f --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_6vect_dot_prod_avx2.asm @@ -0,0 +1,373 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_6vect_dot_prod_avx2(len, vec, *g_tbls, **buffs, **dests); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_6VECT_DOT_PROD_AVX2 _gf_6vect_dot_prod_avx2 +%else + %define GF_6VECT_DOT_PROD_AVX2 gf_6vect_dot_prod_avx2 +%endif + +%ifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r12 ; must be saved and restored + %define tmp5 r14 ; must be saved and restored + %define tmp6 r15 ; must be saved and restored + %define return rax + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + push r14 + push r15 + %endmacro + %macro FUNC_RESTORE 0 + pop r15 + pop r14 + pop r13 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r12 ; must be saved and restored + %define tmp5 r14 ; must be saved and restored + %define tmp6 r15 ; must be saved and restored + %define return rax + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + push r14 + push r15 + %endmacro + %macro FUNC_RESTORE 0 + pop r15 + pop r14 + pop r13 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + + %define arg4 r12 ; must be saved, loaded and restored + %define arg5 r15 ; must be saved and restored + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r14 ; must be saved and restored + %define tmp5 rdi ; must be saved and restored + %define tmp6 rsi ; must be saved and restored + %define return rax + %define PS 8 + %define LOG_PS 3 + %define stack_size 10*16 + 7*8 ; must be an odd multiple of 8 + %define arg(x) [rsp + stack_size + PS + PS*x] + + %define func(x) proc_frame x + %macro FUNC_SAVE 0 + alloc_stack stack_size + vmovdqa [rsp + 0*16], xmm6 + vmovdqa [rsp + 1*16], xmm7 + vmovdqa [rsp + 2*16], xmm8 + vmovdqa [rsp + 3*16], xmm9 + vmovdqa [rsp + 4*16], xmm10 + vmovdqa [rsp + 5*16], xmm11 + vmovdqa [rsp + 6*16], xmm12 + vmovdqa [rsp + 7*16], xmm13 + vmovdqa [rsp + 8*16], xmm14 + vmovdqa [rsp + 9*16], xmm15 + save_reg r12, 10*16 + 0*8 + save_reg r13, 10*16 + 1*8 + save_reg r14, 10*16 + 2*8 + save_reg r15, 10*16 + 3*8 + save_reg rdi, 10*16 + 4*8 + save_reg rsi, 10*16 + 5*8 + end_prolog + mov arg4, arg(4) + %endmacro + + %macro FUNC_RESTORE 0 + vmovdqa xmm6, [rsp + 0*16] + vmovdqa xmm7, [rsp + 1*16] + vmovdqa xmm8, [rsp + 2*16] + vmovdqa xmm9, [rsp + 3*16] + vmovdqa xmm10, [rsp + 4*16] + vmovdqa xmm11, [rsp + 5*16] + vmovdqa xmm12, [rsp + 6*16] + vmovdqa xmm13, [rsp + 7*16] + vmovdqa xmm14, [rsp + 8*16] + vmovdqa xmm15, [rsp + 9*16] + mov r12, [rsp + 10*16 + 0*8] + mov r13, [rsp + 10*16 + 1*8] + mov r14, [rsp + 10*16 + 2*8] + mov r15, [rsp + 10*16 + 3*8] + mov rdi, [rsp + 10*16 + 4*8] + mov rsi, [rsp + 10*16 + 5*8] + add rsp, stack_size + %endmacro +%endif + +%define len arg0 +%define vec arg1 +%define mul_array arg2 +%define src arg3 +%define dest arg4 +%define ptr arg5 +%define vec_i tmp2 +%define dest1 tmp3 +%define dest2 tmp4 +%define vskip1 tmp5 +%define vskip3 tmp6 +%define pos return + + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR vmovdqu + %define XSTR vmovdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR vmovdqa + %define XSTR vmovdqa + %else + %define XLDR vmovntdqa + %define XSTR vmovntdq + %endif +%endif + + +default rel + +[bits 64] +section .text + +%define xmask0f ymm15 +%define xmask0fx xmm15 +%define xgft1_lo ymm14 +%define xgft1_hi ymm13 +%define xgft2_lo ymm12 +%define xgft2_hi ymm11 +%define xgft3_lo ymm10 +%define xgft3_hi ymm9 +%define x0 ymm0 +%define xtmpa ymm1 +%define xp1 ymm2 +%define xp2 ymm3 +%define xp3 ymm4 +%define xp4 ymm5 +%define xp5 ymm6 +%define xp6 ymm7 + +align 16 +global GF_6VECT_DOT_PROD_AVX2:function +func(GF_6VECT_DOT_PROD_AVX2) + FUNC_SAVE + sub len, 32 + jl .return_fail + xor pos, pos + mov tmp.b, 0x0f + vpinsrb xmask0fx, xmask0fx, tmp.w, 0 + vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f... + mov vskip1, vec + imul vskip1, 32 + mov vskip3, vec + imul vskip3, 96 + sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS + mov dest1, [dest] + mov dest2, [dest+PS] + + +.loop32: + mov tmp, mul_array + xor vec_i, vec_i + vpxor xp1, xp1 + vpxor xp2, xp2 + vpxor xp3, xp3 + vpxor xp4, xp4 + vpxor xp5, xp5 + vpxor xp6, xp6 + +.next_vect: + mov ptr, [src+vec_i] + XLDR x0, [ptr+pos] ;Get next source vector + add vec_i, PS + + vpand xgft3_lo, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + vperm2i128 xtmpa, xgft3_lo, x0, 0x30 ;swap xtmpa from 1lo|2lo to 1lo|2hi + vperm2i128 x0, xgft3_lo, x0, 0x12 ;swap x0 from 1hi|2hi to 1hi|2lo + + vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} + ; " Ax{00}, Ax{10}, ..., Ax{f0} + vmovdqu xgft2_lo, [tmp+vskip1*1] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} + ; " Bx{00}, Bx{10}, ..., Bx{f0} + vmovdqu xgft3_lo, [tmp+vskip1*2] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} + ; " Cx{00}, Cx{10}, ..., Cx{f0} + lea ptr, [vskip1 + vskip1*4] ;ptr = vskip5 + + vperm2i128 xgft1_hi, xgft1_lo, xgft1_lo, 0x01 ; swapped to hi | lo + vperm2i128 xgft2_hi, xgft2_lo, xgft2_lo, 0x01 ; swapped to hi | lo + vperm2i128 xgft3_hi, xgft3_lo, xgft3_lo, 0x01 ; swapped to hi | lo + + vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft1_hi, xgft1_lo ;GF add high and low partials + vpxor xp1, xgft1_hi ;xp1 += partial + + vpshufb xgft2_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft2_hi, xgft2_lo ;GF add high and low partials + vpxor xp2, xgft2_hi ;xp2 += partial + + vpshufb xgft3_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft3_hi, xgft3_lo ;GF add high and low partials + vpxor xp3, xgft3_hi ;xp3 += partial + + + vmovdqu xgft1_lo, [tmp+vskip3] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} + ; " Dx{00}, Dx{10}, ..., Dx{f0} + vmovdqu xgft2_lo, [tmp+vskip1*4] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} + ; " Ex{00}, Ex{10}, ..., Ex{f0} + vmovdqu xgft3_lo, [tmp+ptr] ;Load array Fx{00}, Fx{01}, ..., Fx{0f} + ; " Fx{00}, Fx{10}, ..., Fx{f0} + add tmp, 32 + vperm2i128 xgft1_hi, xgft1_lo, xgft1_lo, 0x01 ; swapped to hi | lo + vperm2i128 xgft2_hi, xgft2_lo, xgft2_lo, 0x01 ; swapped to hi | lo + vperm2i128 xgft3_hi, xgft3_lo, xgft3_lo, 0x01 ; swapped to hi | lo + + vpshufb xgft1_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft1_hi, xgft1_lo ;GF add high and low partials + vpxor xp4, xgft1_hi ;xp4 += partial + + vpshufb xgft2_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft2_hi, xgft2_lo ;GF add high and low partials + vpxor xp5, xgft2_hi ;xp5 += partial + + vpshufb xgft3_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft3_hi, xgft3_lo ;GF add high and low partials + vpxor xp6, xgft3_hi ;xp6 += partial + + cmp vec_i, vec + jl .next_vect + + + mov tmp, [dest+2*PS] + mov ptr, [dest+3*PS] + mov vec_i, [dest+4*PS] + + XSTR [dest1+pos], xp1 + XSTR [dest2+pos], xp2 + XSTR [tmp+pos], xp3 + mov tmp, [dest+5*PS] + XSTR [ptr+pos], xp4 + XSTR [vec_i+pos], xp5 + XSTR [tmp+pos], xp6 + + add pos, 32 ;Loop on 32 bytes at a time + cmp pos, len + jle .loop32 + + lea tmp, [len + 32] + cmp pos, tmp + je .return_pass + + ;; Tail len + mov pos, len ;Overlapped offset length-16 + jmp .loop32 ;Do one more overlap pass + +.return_pass: + FUNC_RESTORE + mov return, 0 + ret + +.return_fail: + FUNC_RESTORE + mov return, 1 + ret + +endproc_frame + +section .data + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_6VECT_DOT_PROD_AVX2, 04, 03, 019a diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_6vect_dot_prod_sse.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_6vect_dot_prod_sse.asm new file mode 100644 index 000000000..b37480be9 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_6vect_dot_prod_sse.asm @@ -0,0 +1,360 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_6vect_dot_prod_sse(len, vec, *g_tbls, **buffs, **dests); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_6VECT_DOT_PROD_SSE _gf_6vect_dot_prod_sse +%else + %define GF_6VECT_DOT_PROD_SSE gf_6vect_dot_prod_sse +%endif + +%ifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r12 ; must be saved and restored + %define tmp5 r14 ; must be saved and restored + %define tmp6 r15 ; must be saved and restored + %define return rax + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + push r14 + push r15 + %endmacro + %macro FUNC_RESTORE 0 + pop r15 + pop r14 + pop r13 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r12 ; must be saved and restored + %define tmp5 r14 ; must be saved and restored + %define tmp6 r15 ; must be saved and restored + %define return rax + %define PS 8 + %define LOG_PS 3 + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + push r14 + push r15 + %endmacro + %macro FUNC_RESTORE 0 + pop r15 + pop r14 + pop r13 + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + + %define arg4 r12 ; must be saved, loaded and restored + %define arg5 r15 ; must be saved and restored + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 ; must be saved and restored + %define tmp4 r14 ; must be saved and restored + %define tmp5 rdi ; must be saved and restored + %define tmp6 rsi ; must be saved and restored + %define return rax + %define PS 8 + %define LOG_PS 3 + %define stack_size 10*16 + 7*8 ; must be an odd multiple of 8 + %define arg(x) [rsp + stack_size + PS + PS*x] + + %define func(x) proc_frame x + %macro FUNC_SAVE 0 + alloc_stack stack_size + save_xmm128 xmm6, 0*16 + save_xmm128 xmm7, 1*16 + save_xmm128 xmm8, 2*16 + save_xmm128 xmm9, 3*16 + save_xmm128 xmm10, 4*16 + save_xmm128 xmm11, 5*16 + save_xmm128 xmm12, 6*16 + save_xmm128 xmm13, 7*16 + save_xmm128 xmm14, 8*16 + save_xmm128 xmm15, 9*16 + save_reg r12, 10*16 + 0*8 + save_reg r13, 10*16 + 1*8 + save_reg r14, 10*16 + 2*8 + save_reg r15, 10*16 + 3*8 + save_reg rdi, 10*16 + 4*8 + save_reg rsi, 10*16 + 5*8 + end_prolog + mov arg4, arg(4) + %endmacro + + %macro FUNC_RESTORE 0 + movdqa xmm6, [rsp + 0*16] + movdqa xmm7, [rsp + 1*16] + movdqa xmm8, [rsp + 2*16] + movdqa xmm9, [rsp + 3*16] + movdqa xmm10, [rsp + 4*16] + movdqa xmm11, [rsp + 5*16] + movdqa xmm12, [rsp + 6*16] + movdqa xmm13, [rsp + 7*16] + movdqa xmm14, [rsp + 8*16] + movdqa xmm15, [rsp + 9*16] + mov r12, [rsp + 10*16 + 0*8] + mov r13, [rsp + 10*16 + 1*8] + mov r14, [rsp + 10*16 + 2*8] + mov r15, [rsp + 10*16 + 3*8] + mov rdi, [rsp + 10*16 + 4*8] + mov rsi, [rsp + 10*16 + 5*8] + add rsp, stack_size + %endmacro +%endif + +%define len arg0 +%define vec arg1 +%define mul_array arg2 +%define src arg3 +%define dest arg4 +%define ptr arg5 +%define vec_i tmp2 +%define dest1 tmp3 +%define dest2 tmp4 +%define vskip1 tmp5 +%define vskip3 tmp6 +%define pos return + + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR movdqu + %define XSTR movdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR movdqa + %define XSTR movdqa + %else + %define XLDR movntdqa + %define XSTR movntdq + %endif +%endif + + +default rel + +[bits 64] +section .text + +%define xmask0f xmm15 +%define xgft1_lo xmm2 +%define xgft1_hi xmm3 +%define xgft2_lo xmm4 +%define xgft2_hi xmm5 +%define xgft3_lo xmm6 +%define xgft3_hi xmm7 +%define x0 xmm0 +%define xtmpa xmm1 +%define xp1 xmm8 +%define xp2 xmm9 +%define xp3 xmm10 +%define xp4 xmm11 +%define xp5 xmm12 +%define xp6 xmm13 + +align 16 +global GF_6VECT_DOT_PROD_SSE:function +func(GF_6VECT_DOT_PROD_SSE) + FUNC_SAVE + sub len, 16 + jl .return_fail + xor pos, pos + movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + mov vskip1, vec + imul vskip1, 32 + mov vskip3, vec + imul vskip3, 96 + sal vec, LOG_PS ;vec *= PS. Make vec_i count by PS + mov dest1, [dest] + mov dest2, [dest+PS] + + +.loop16: + mov tmp, mul_array + xor vec_i, vec_i + pxor xp1, xp1 + pxor xp2, xp2 + pxor xp3, xp3 + pxor xp4, xp4 + pxor xp5, xp5 + pxor xp6, xp6 + +.next_vect: + mov ptr, [src+vec_i] + add vec_i, PS + XLDR x0, [ptr+pos] ;Get next source vector + + movdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} + movdqu xgft1_hi, [tmp+16] ; " Ax{00}, Ax{10}, ..., Ax{f0} + movdqu xgft2_lo, [tmp+vskip1*1] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} + movdqu xgft2_hi, [tmp+vskip1*1+16] ; " Bx{00}, Bx{10}, ..., Bx{f0} + movdqu xgft3_lo, [tmp+vskip1*2] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} + movdqu xgft3_hi, [tmp+vskip1*2+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} + lea ptr, [vskip1 + vskip1*4] ;ptr = vskip5 + + movdqa xtmpa, x0 ;Keep unshifted copy of src + psraw x0, 4 ;Shift to put high nibble into bits 4-0 + pand x0, xmask0f ;Mask high src nibble in bits 4-0 + pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 + + pshufb xgft1_hi, x0 ;Lookup mul table of high nibble + pshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft1_hi, xgft1_lo ;GF add high and low partials + pxor xp1, xgft1_hi ;xp1 += partial + + pshufb xgft2_hi, x0 ;Lookup mul table of high nibble + pshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft2_hi, xgft2_lo ;GF add high and low partials + pxor xp2, xgft2_hi ;xp2 += partial + + pshufb xgft3_hi, x0 ;Lookup mul table of high nibble + pshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft3_hi, xgft3_lo ;GF add high and low partials + pxor xp3, xgft3_hi ;xp3 += partial + + + movdqu xgft1_lo, [tmp+vskip3] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} + movdqu xgft1_hi, [tmp+vskip3+16] ; " Dx{00}, Dx{10}, ..., Dx{f0} + movdqu xgft2_lo, [tmp+vskip1*4] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} + movdqu xgft2_hi, [tmp+vskip1*4+16] ; " Ex{00}, Ex{10}, ..., Ex{f0} + movdqu xgft3_lo, [tmp+ptr] ;Load array Fx{00}, Fx{01}, ..., Fx{0f} + movdqu xgft3_hi, [tmp+ptr+16] ; " Fx{00}, Fx{10}, ..., Fx{f0} + add tmp, 32 + + + pshufb xgft1_hi, x0 ;Lookup mul table of high nibble + pshufb xgft1_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft1_hi, xgft1_lo ;GF add high and low partials + pxor xp4, xgft1_hi ;xp4 += partial + + pshufb xgft2_hi, x0 ;Lookup mul table of high nibble + pshufb xgft2_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft2_hi, xgft2_lo ;GF add high and low partials + pxor xp5, xgft2_hi ;xp5 += partial + + pshufb xgft3_hi, x0 ;Lookup mul table of high nibble + pshufb xgft3_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft3_hi, xgft3_lo ;GF add high and low partials + pxor xp6, xgft3_hi ;xp6 += partial + + cmp vec_i, vec + jl .next_vect + + + mov tmp, [dest+2*PS] + mov ptr, [dest+3*PS] + mov vec_i, [dest+4*PS] + + XSTR [dest1+pos], xp1 + XSTR [dest2+pos], xp2 + XSTR [tmp+pos], xp3 + mov tmp, [dest+5*PS] + XSTR [ptr+pos], xp4 + XSTR [vec_i+pos], xp5 + XSTR [tmp+pos], xp6 + + add pos, 16 ;Loop on 16 bytes at a time + cmp pos, len + jle .loop16 + + lea tmp, [len + 16] + cmp pos, tmp + je .return_pass + + ;; Tail len + mov pos, len ;Overlapped offset length-16 + jmp .loop16 ;Do one more overlap pass + +.return_pass: + FUNC_RESTORE + mov return, 0 + ret + +.return_fail: + FUNC_RESTORE + mov return, 1 + ret + +endproc_frame + +section .data + +align 16 +mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_6VECT_DOT_PROD_SSE, 00, 04, 0066 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_6vect_mad_avx.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_6vect_mad_avx.asm new file mode 100644 index 000000000..f82b96736 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_6vect_mad_avx.asm @@ -0,0 +1,433 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_6vect_mad_avx(len, vec, vec_i, mul_array, src, dest); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_6VECT_MAD_AVX _gf_6vect_mad_avx +%else + %define GF_6VECT_MAD_AVX gf_6vect_mad_avx +%endif + +%define PS 8 + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg0.w ecx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + %define arg4 r12 + %define arg5 r15 + %define tmp r11 + %define tmp2 r10 + %define tmp3 r13 + %define tmp4 r14 + %define tmp5 rdi + %define return rax + %define return.w eax + %define stack_size 16*10 + 5*8 + %define arg(x) [rsp + stack_size + PS + PS*x] + %define func(x) proc_frame x + +%macro FUNC_SAVE 0 + sub rsp, stack_size + movdqa [rsp+16*0],xmm6 + movdqa [rsp+16*1],xmm7 + movdqa [rsp+16*2],xmm8 + movdqa [rsp+16*3],xmm9 + movdqa [rsp+16*4],xmm10 + movdqa [rsp+16*5],xmm11 + movdqa [rsp+16*6],xmm12 + movdqa [rsp+16*7],xmm13 + movdqa [rsp+16*8],xmm14 + movdqa [rsp+16*9],xmm15 + save_reg r12, 10*16 + 0*8 + save_reg r13, 10*16 + 1*8 + save_reg r14, 10*16 + 2*8 + save_reg r15, 10*16 + 3*8 + save_reg rdi, 10*16 + 4*8 + end_prolog + mov arg4, arg(4) + mov arg5, arg(5) +%endmacro + +%macro FUNC_RESTORE 0 + movdqa xmm6, [rsp+16*0] + movdqa xmm7, [rsp+16*1] + movdqa xmm8, [rsp+16*2] + movdqa xmm9, [rsp+16*3] + movdqa xmm10, [rsp+16*4] + movdqa xmm11, [rsp+16*5] + movdqa xmm12, [rsp+16*6] + movdqa xmm13, [rsp+16*7] + movdqa xmm14, [rsp+16*8] + movdqa xmm15, [rsp+16*9] + mov r12, [rsp + 10*16 + 0*8] + mov r13, [rsp + 10*16 + 1*8] + mov r14, [rsp + 10*16 + 2*8] + mov r15, [rsp + 10*16 + 3*8] + mov rdi, [rsp + 10*16 + 4*8] + add rsp, stack_size +%endmacro + +%elifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define tmp2 r10 + %define tmp3 r12 + %define tmp4 r13 + %define tmp5 r14 + %define return rax + %define return.w eax + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + push r14 + %endmacro + %macro FUNC_RESTORE 0 + pop r14 + pop r13 + pop r12 + %endmacro +%elifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define tmp2 r10 + %define tmp3 r12 + %define tmp4 r13 + %define tmp5 r14 + %define return rax + %define return.w eax + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + push r14 + %endmacro + %macro FUNC_RESTORE 0 + pop r14 + pop r13 + pop r12 + %endmacro +%endif + +;;; gf_6vect_mad_avx(len, vec, vec_i, mul_array, src, dest) +%define len arg0 +%define len.w arg0.w +%define vec arg1 +%define vec_i arg2 +%define mul_array arg3 +%define src arg4 +%define dest1 arg5 +%define pos return +%define pos.w return.w + +%define dest2 tmp4 +%define dest3 tmp2 +%define dest4 mul_array +%define dest5 tmp5 +%define dest6 vec_i + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR vmovdqu + %define XSTR vmovdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR vmovdqa + %define XSTR vmovdqa + %else + %define XLDR vmovntdqa + %define XSTR vmovntdq + %endif +%endif + + +default rel + +[bits 64] +section .text + +%define xmask0f xmm15 +%define xgft4_lo xmm14 +%define xgft4_hi xmm13 +%define xgft5_lo xmm12 +%define xgft5_hi xmm11 +%define xgft6_lo xmm10 +%define xgft6_hi xmm9 + +%define x0 xmm0 +%define xtmpa xmm1 +%define xtmph1 xmm2 +%define xtmpl1 xmm3 +%define xtmph2 xmm4 +%define xtmpl2 xmm5 +%define xtmph3 xmm6 +%define xtmpl3 xmm7 +%define xd1 xmm8 +%define xd2 xtmpl1 +%define xd3 xtmph1 + + +align 16 +global GF_6VECT_MAD_AVX:function +func(GF_6VECT_MAD_AVX) + FUNC_SAVE + sub len, 16 + jl .return_fail + xor pos, pos + vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + mov tmp, vec + sal vec_i, 5 ;Multiply by 32 + lea tmp3, [mul_array + vec_i] + sal tmp, 6 ;Multiply by 64 + + sal vec, 5 ;Multiply by 32 + lea vec_i, [tmp + vec] ;vec_i = vec*96 + lea mul_array, [tmp + vec_i] ;mul_array = vec*160 + + vmovdqu xgft5_lo, [tmp3+2*tmp] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} + vmovdqu xgft5_hi, [tmp3+2*tmp+16] ; " Ex{00}, Ex{10}, ..., Ex{f0} + vmovdqu xgft4_lo, [tmp3+vec_i] ;Load array Dx{00}, Dx{01}, Dx{02}, ... + vmovdqu xgft4_hi, [tmp3+vec_i+16] ; " Dx{00}, Dx{10}, Dx{20}, ... , Dx{f0} + vmovdqu xgft6_lo, [tmp3+mul_array] ;Load array Fx{00}, Fx{01}, ..., Fx{0f} + vmovdqu xgft6_hi, [tmp3+mul_array+16] ; " Fx{00}, Fx{10}, ..., Fx{f0} + + mov dest2, [dest1+PS] + mov dest3, [dest1+2*PS] + mov dest4, [dest1+3*PS] ; reuse mul_array + mov dest5, [dest1+4*PS] + mov dest6, [dest1+5*PS] ; reuse vec_i + mov dest1, [dest1] + +.loop16: + XLDR x0, [src+pos] ;Get next source vector + + vmovdqu xtmpl1, [tmp3] ;Load array Ax{00}, Ax{01}, Ax{02}, ... + vmovdqu xtmph1, [tmp3+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} + vmovdqu xtmpl2, [tmp3+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... + vmovdqu xtmph2, [tmp3+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} + vmovdqu xtmpl3, [tmp3+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... + vmovdqu xtmph3, [tmp3+2*vec+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} + XLDR xd1, [dest1+pos] ;Get next dest vector + + vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + + + ;dest1 + vpshufb xtmph1, x0 ;Lookup mul table of high nibble + vpshufb xtmpl1, xtmpa ;Lookup mul table of low nibble + vpxor xtmph1, xtmpl1 ;GF add high and low partials + vpxor xd1, xtmph1 + + XLDR xd2, [dest2+pos] ;reuse xtmpl1. Get next dest vector + XLDR xd3, [dest3+pos] ;reuse xtmph1. Get next dest vector + + ;dest2 + vpshufb xtmph2, x0 ;Lookup mul table of high nibble + vpshufb xtmpl2, xtmpa ;Lookup mul table of low nibble + vpxor xtmph2, xtmpl2 ;GF add high and low partials + vpxor xd2, xtmph2 + + ;dest3 + vpshufb xtmph3, x0 ;Lookup mul table of high nibble + vpshufb xtmpl3, xtmpa ;Lookup mul table of low nibble + vpxor xtmph3, xtmpl3 ;GF add high and low partials + vpxor xd3, xtmph3 + + XSTR [dest1+pos], xd1 ;Store result into dest1 + XSTR [dest2+pos], xd2 ;Store result into dest2 + XSTR [dest3+pos], xd3 ;Store result into dest3 + + ;dest4 + XLDR xd1, [dest4+pos] ;Get next dest vector + vpshufb xtmph1, xgft4_hi, x0 ;Lookup mul table of high nibble + vpshufb xtmpl1, xgft4_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph1, xtmph1, xtmpl1 ;GF add high and low partials + vpxor xd1, xd1, xtmph1 + + XLDR xd2, [dest5+pos] ;reuse xtmpl1. Get next dest vector + XLDR xd3, [dest6+pos] ;reuse xtmph1. Get next dest vector + + ;dest5 + vpshufb xtmph2, xgft5_hi, x0 ;Lookup mul table of high nibble + vpshufb xtmpl2, xgft5_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph2, xtmph2, xtmpl2 ;GF add high and low partials + vpxor xd2, xd2, xtmph2 + + ;dest6 + vpshufb xtmph3, xgft6_hi, x0 ;Lookup mul table of high nibble + vpshufb xtmpl3, xgft6_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph3, xtmph3, xtmpl3 ;GF add high and low partials + vpxor xd3, xd3, xtmph3 + + XSTR [dest4+pos], xd1 ;Store result into dest4 + XSTR [dest5+pos], xd2 ;Store result into dest5 + XSTR [dest6+pos], xd3 ;Store result into dest6 + + add pos, 16 ;Loop on 16 bytes at a time + cmp pos, len + jle .loop16 + + lea tmp, [len + 16] + cmp pos, tmp + je .return_pass + +.lessthan16: + ;; Tail len + ;; Do one more overlap pass + ;; Overlapped offset length-16 + mov tmp, len ;Backup len as len=rdi + + XLDR x0, [src+tmp] ;Get next source vector + XLDR xd1, [dest4+tmp] ;Get next dest vector + XLDR xd2, [dest5+tmp] ;reuse xtmpl1. Get next dest vector + XLDR xd3, [dest6+tmp] ;reuse xtmph1. Get next dest vector + + sub len, pos + + vmovdqa xtmph3, [constip16] ;Load const of i + 16 + vpinsrb xtmpl3, len.w, 15 + vpshufb xtmpl3, xmask0f ;Broadcast len to all bytes + vpcmpgtb xtmpl3, xtmpl3, xtmph3 + + vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + + ;dest4 + vpshufb xgft4_hi, xgft4_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft4_lo, xgft4_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft4_hi, xgft4_hi, xgft4_lo ;GF add high and low partials + vpand xgft4_hi, xgft4_hi, xtmpl3 + vpxor xd1, xd1, xgft4_hi + + ;dest5 + vpshufb xgft5_hi, xgft5_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft5_lo, xgft5_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft5_hi, xgft5_hi, xgft5_lo ;GF add high and low partials + vpand xgft5_hi, xgft5_hi, xtmpl3 + vpxor xd2, xd2, xgft5_hi + + ;dest6 + vpshufb xgft6_hi, xgft6_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft6_lo, xgft6_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft6_hi, xgft6_hi, xgft6_lo ;GF add high and low partials + vpand xgft6_hi, xgft6_hi, xtmpl3 + vpxor xd3, xd3, xgft6_hi + + XSTR [dest4+tmp], xd1 ;Store result into dest4 + XSTR [dest5+tmp], xd2 ;Store result into dest5 + XSTR [dest6+tmp], xd3 ;Store result into dest6 + + vmovdqu xgft4_lo, [tmp3] ;Load array Ax{00}, Ax{01}, Ax{02}, ... + vmovdqu xgft4_hi, [tmp3+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} + vmovdqu xgft5_lo, [tmp3+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... + vmovdqu xgft5_hi, [tmp3+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} + vmovdqu xgft6_lo, [tmp3+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... + vmovdqu xgft6_hi, [tmp3+2*vec+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} + XLDR xd1, [dest1+tmp] ;Get next dest vector + XLDR xd2, [dest2+tmp] ;reuse xtmpl1. Get next dest vector + XLDR xd3, [dest3+tmp] ;reuse xtmph1. Get next dest3 vector + + ;dest1 + vpshufb xgft4_hi, xgft4_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft4_lo, xgft4_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft4_hi, xgft4_hi, xgft4_lo ;GF add high and low partials + vpand xgft4_hi, xgft4_hi, xtmpl3 + vpxor xd1, xd1, xgft4_hi + + ;dest2 + vpshufb xgft5_hi, xgft5_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft5_lo, xgft5_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft5_hi, xgft5_hi, xgft5_lo ;GF add high and low partials + vpand xgft5_hi, xgft5_hi, xtmpl3 + vpxor xd2, xd2, xgft5_hi + + ;dest3 + vpshufb xgft6_hi, xgft6_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft6_lo, xgft6_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft6_hi, xgft6_hi, xgft6_lo ;GF add high and low partials + vpand xgft6_hi, xgft6_hi, xtmpl3 + vpxor xd3, xd3, xgft6_hi + + XSTR [dest1+tmp], xd1 ;Store result into dest1 + XSTR [dest2+tmp], xd2 ;Store result into dest2 + XSTR [dest3+tmp], xd3 ;Store result into dest3 + +.return_pass: + FUNC_RESTORE + mov return, 0 + ret + +.return_fail: + FUNC_RESTORE + mov return, 1 + ret + +endproc_frame + +section .data + +align 16 +mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f +constip16: + ddq 0xf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_6VECT_MAD_AVX, 02, 00, 0210 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_6vect_mad_avx2.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_6vect_mad_avx2.asm new file mode 100644 index 000000000..86566b2a2 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_6vect_mad_avx2.asm @@ -0,0 +1,435 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_6vect_mad_avx2(len, vec, vec_i, mul_array, src, dest); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_6VECT_MAD_AVX2 _gf_6vect_mad_avx2 +%else + %define GF_6VECT_MAD_AVX2 gf_6vect_mad_avx2 +%endif + +%define PS 8 + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg0.w ecx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + %define arg4 r12 + %define arg5 r15 + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define tmp3 r13 + %define return rax + %define return.w eax + %define stack_size 16*10 + 3*8 + %define arg(x) [rsp + stack_size + PS + PS*x] + %define func(x) proc_frame x + +%macro FUNC_SAVE 0 + sub rsp, stack_size + movdqa [rsp+16*0],xmm6 + movdqa [rsp+16*1],xmm7 + movdqa [rsp+16*2],xmm8 + movdqa [rsp+16*3],xmm9 + movdqa [rsp+16*4],xmm10 + movdqa [rsp+16*5],xmm11 + movdqa [rsp+16*6],xmm12 + movdqa [rsp+16*7],xmm13 + movdqa [rsp+16*8],xmm14 + movdqa [rsp+16*9],xmm15 + save_reg r12, 10*16 + 0*8 + save_reg r13, 10*16 + 1*8 + save_reg r15, 10*16 + 2*8 + end_prolog + mov arg4, arg(4) + mov arg5, arg(5) +%endmacro + +%macro FUNC_RESTORE 0 + movdqa xmm6, [rsp+16*0] + movdqa xmm7, [rsp+16*1] + movdqa xmm8, [rsp+16*2] + movdqa xmm9, [rsp+16*3] + movdqa xmm10, [rsp+16*4] + movdqa xmm11, [rsp+16*5] + movdqa xmm12, [rsp+16*6] + movdqa xmm13, [rsp+16*7] + movdqa xmm14, [rsp+16*8] + movdqa xmm15, [rsp+16*9] + mov r12, [rsp + 10*16 + 0*8] + mov r13, [rsp + 10*16 + 1*8] + mov r15, [rsp + 10*16 + 3*8] + add rsp, stack_size +%endmacro + +%elifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define tmp3 r12 + %define return rax + %define return.w eax + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + %endmacro + %macro FUNC_RESTORE 0 + pop r12 + %endmacro +%elifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define tmp3 r12 + %define return rax + %define return.w eax + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + %endmacro + %macro FUNC_RESTORE 0 + pop r12 + %endmacro +%endif + +;;; gf_6vect_mad_avx2(len, vec, vec_i, mul_array, src, dest) +%define len arg0 +%define len.w arg0.w +%define vec arg1 +%define vec_i arg2 +%define mul_array arg3 +%define src arg4 +%define dest1 arg5 +%define pos return +%define pos.w return.w + +%define dest2 tmp3 +%define dest3 tmp2 +%define dest4 mul_array +%define dest5 vec +%define dest6 vec_i + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR vmovdqu + %define XSTR vmovdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR vmovdqa + %define XSTR vmovdqa + %else + %define XLDR vmovntdqa + %define XSTR vmovntdq + %endif +%endif + + +default rel + +[bits 64] +section .text + +%define xmask0f ymm15 +%define xmask0fx xmm15 +%define xgft1_lo ymm14 +%define xgft2_lo ymm13 +%define xgft3_lo ymm12 +%define xgft4_lo ymm11 +%define xgft5_lo ymm10 +%define xgft6_lo ymm9 + +%define x0 ymm0 +%define xtmpa ymm1 +%define xtmpl ymm2 +%define xtmplx xmm2 +%define xtmph ymm3 +%define xtmphx xmm3 +%define xd1 ymm4 +%define xd2 ymm5 +%define xd3 ymm6 +%define xd4 ymm7 +%define xd5 ymm8 +%define xd6 xd1 + +align 16 +global GF_6VECT_MAD_AVX2:function +func(GF_6VECT_MAD_AVX2) + FUNC_SAVE + sub len, 32 + jl .return_fail + xor pos, pos + mov tmp.b, 0x0f + vpinsrb xmask0fx, xmask0fx, tmp.w, 0 + vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f... + + sal vec_i, 5 ;Multiply by 32 + sal vec, 5 ;Multiply by 32 + lea tmp, [mul_array + vec_i] + mov vec_i, vec + mov mul_array, vec + sal vec_i, 1 + sal mul_array, 1 + add vec_i, vec ;vec_i=vec*96 + add mul_array, vec_i ;vec_i=vec*160 + + vmovdqu xgft1_lo, [tmp] ;Load array Ax{00}, Ax{01}, ..., Ax{0f} + ; " Ax{00}, Ax{10}, ..., Ax{f0} + vmovdqu xgft2_lo, [tmp+vec] ;Load array Bx{00}, Bx{01}, ..., Bx{0f} + ; " Bx{00}, Bx{10}, ..., Bx{f0} + vmovdqu xgft3_lo, [tmp+2*vec] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} + ; " Cx{00}, Cx{10}, ..., Cx{f0} + vmovdqu xgft4_lo, [tmp+vec_i] ;Load array Fx{00}, Fx{01}, ..., Fx{0f} + ; " Fx{00}, Fx{10}, ..., Fx{f0} + vmovdqu xgft5_lo, [tmp+4*vec] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} + ; " Ex{00}, Ex{10}, ..., Ex{f0} + vmovdqu xgft6_lo, [tmp+mul_array] ;Load array Dx{00}, Dx{01}, ..., Dx{0f} + ; " Dx{00}, Dx{10}, ..., Dx{f0} + + mov dest2, [dest1+PS] ; reuse tmp3 + mov dest3, [dest1+2*PS] ; reuse tmp2 + mov dest4, [dest1+3*PS] ; reuse mul_array + mov dest5, [dest1+4*PS] ; reuse vec + mov dest6, [dest1+5*PS] ; reuse vec_i + mov dest1, [dest1] + +.loop32: + XLDR x0, [src+pos] ;Get next source vector + XLDR xd1, [dest1+pos] ;Get next dest vector + XLDR xd2, [dest2+pos] ;Get next dest vector + XLDR xd3, [dest3+pos] ;Get next dest vector + XLDR xd4, [dest4+pos] ;Get next dest vector + XLDR xd5, [dest5+pos] ;Get next dest vector + + vpand xtmpl, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + vperm2i128 xtmpa, xtmpl, x0, 0x30 ;swap xtmpa from 1lo|2lo to 1lo|2hi + vperm2i128 x0, xtmpl, x0, 0x12 ;swap x0 from 1hi|2hi to 1hi|2lo + + ;dest1 + vperm2i128 xtmph, xgft1_lo, xgft1_lo, 0x01 ; swapped to hi | lo + vpshufb xtmph, xtmph, x0 ;Lookup mul table of high nibble + vpshufb xtmpl, xgft1_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph, xtmph, xtmpl ;GF add high and low partials + vpxor xd1, xd1, xtmph ;xd1 += partial + + XSTR [dest1+pos], xd1 ;Store result into dest1 + + ;dest2 + vperm2i128 xtmph, xgft2_lo, xgft2_lo, 0x01 ; swapped to hi | lo + vpshufb xtmph, xtmph, x0 ;Lookup mul table of high nibble + vpshufb xtmpl, xgft2_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph, xtmph, xtmpl ;GF add high and low partials + vpxor xd2, xd2, xtmph ;xd2 += partial + + ;dest3 + vperm2i128 xtmph, xgft3_lo, xgft3_lo, 0x01 ; swapped to hi | lo + vpshufb xtmph, xtmph, x0 ;Lookup mul table of high nibble + vpshufb xtmpl, xgft3_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph, xtmph, xtmpl ;GF add high and low partials + vpxor xd3, xd3, xtmph ;xd3 += partial + + XLDR xd6, [dest6+pos] ;reuse xd1. Get next dest vector + + ;dest4 + vperm2i128 xtmph, xgft4_lo, xgft4_lo, 0x01 ; swapped to hi | lo + vpshufb xtmph, xtmph, x0 ;Lookup mul table of high nibble + vpshufb xtmpl, xgft4_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph, xtmph, xtmpl ;GF add high and low partials + vpxor xd4, xd4, xtmph ;xd4 += partial + + ;dest5 + vperm2i128 xtmph, xgft5_lo, xgft5_lo, 0x01 ; swapped to hi | lo + vpshufb xtmph, xtmph, x0 ;Lookup mul table of high nibble + vpshufb xtmpl, xgft5_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph, xtmph, xtmpl ;GF add high and low partials + vpxor xd5, xd5, xtmph ;xd5 += partial + + ;dest6 + vperm2i128 xtmph, xgft6_lo, xgft6_lo, 0x01 ; swapped to hi | lo + vpshufb xtmph, xtmph, x0 ;Lookup mul table of high nibble + vpshufb xtmpl, xgft6_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph, xtmph, xtmpl ;GF add high and low partials + vpxor xd6, xd6, xtmph ;xd6 += partial + + XSTR [dest2+pos], xd2 ;Store result into dest2 + XSTR [dest3+pos], xd3 ;Store result into dest3 + XSTR [dest4+pos], xd4 ;Store result into dest4 + XSTR [dest5+pos], xd5 ;Store result into dest5 + XSTR [dest6+pos], xd6 ;Store result into dest6 + + add pos, 32 ;Loop on 32 bytes at a time + cmp pos, len + jle .loop32 + + lea tmp, [len + 32] + cmp pos, tmp + je .return_pass + +.lessthan32: + ;; Tail len + ;; Do one more overlap pass + mov tmp.b, 0x1f + vpinsrb xtmphx, xtmphx, tmp.w, 0 + vpbroadcastb xtmph, xtmphx ;Construct mask 0x1f1f1f... + + mov tmp, len ;Overlapped offset length-32 + + XLDR x0, [src+tmp] ;Get next source vector + XLDR xd1, [dest1+tmp] ;Get next dest vector + XLDR xd2, [dest2+tmp] ;Get next dest vector + XLDR xd3, [dest3+tmp] ;Get next dest vector + XLDR xd4, [dest4+tmp] ;Get next dest vector + XLDR xd5, [dest5+tmp] ;Get next dest vector + + sub len, pos + + vpinsrb xtmplx, xtmplx, len.w, 15 + vinserti128 xtmpl, xtmpl, xtmplx, 1 ;swapped to xtmplx | xtmplx + vpshufb xtmpl, xtmpl, xtmph ;Broadcast len to all bytes. xtmph=0x1f1f1f... + vpcmpgtb xtmpl, xtmpl, [constip32] + + vpand xtmph, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + vperm2i128 xtmpa, xtmph, x0, 0x30 ;swap xtmpa from 1lo|2lo to 1lo|2hi + vperm2i128 x0, xtmph, x0, 0x12 ;swap x0 from 1hi|2hi to 1hi|2lo + + ;dest1 + vperm2i128 xtmph, xgft1_lo, xgft1_lo, 0x01 ; swapped to hi | lo + vpshufb xtmph, xtmph, x0 ;Lookup mul table of high nibble + vpshufb xgft1_lo, xgft1_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph, xtmph, xgft1_lo ;GF add high and low partials + vpand xtmph, xtmph, xtmpl + vpxor xd1, xd1, xtmph ;xd1 += partial + + XSTR [dest1+tmp], xd1 ;Store result into dest1 + + ;dest2 + vperm2i128 xtmph, xgft2_lo, xgft2_lo, 0x01 ; swapped to hi | lo + vpshufb xtmph, xtmph, x0 ;Lookup mul table of high nibble + vpshufb xgft2_lo, xgft2_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph, xtmph, xgft2_lo ;GF add high and low partials + vpand xtmph, xtmph, xtmpl + vpxor xd2, xd2, xtmph ;xd2 += partial + + ;dest3 + vperm2i128 xtmph, xgft3_lo, xgft3_lo, 0x01 ; swapped to hi | lo + vpshufb xtmph, xtmph, x0 ;Lookup mul table of high nibble + vpshufb xgft3_lo, xgft3_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph, xtmph, xgft3_lo ;GF add high and low partials + vpand xtmph, xtmph, xtmpl + vpxor xd3, xd3, xtmph ;xd3 += partial + + XLDR xd6, [dest6+tmp] ;reuse xd1. Get next dest vector + + ;dest4 + vperm2i128 xtmph, xgft4_lo, xgft4_lo, 0x01 ; swapped to hi | lo + vpshufb xtmph, xtmph, x0 ;Lookup mul table of high nibble + vpshufb xgft4_lo, xgft4_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph, xtmph, xgft4_lo ;GF add high and low partials + vpand xtmph, xtmph, xtmpl + vpxor xd4, xd4, xtmph ;xd4 += partial + + ;dest5 + vperm2i128 xtmph, xgft5_lo, xgft5_lo, 0x01 ; swapped to hi | lo + vpshufb xtmph, xtmph, x0 ;Lookup mul table of high nibble + vpshufb xgft5_lo, xgft5_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph, xtmph, xgft5_lo ;GF add high and low partials + vpand xtmph, xtmph, xtmpl + vpxor xd5, xd5, xtmph ;xd5 += partial + + ;dest6 + vperm2i128 xtmph, xgft6_lo, xgft6_lo, 0x01 ; swapped to hi | lo + vpshufb xtmph, xtmph, x0 ;Lookup mul table of high nibble + vpshufb xgft6_lo, xgft6_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph, xtmph, xgft6_lo ;GF add high and low partials + vpand xtmph, xtmph, xtmpl + vpxor xd6, xd6, xtmph ;xd6 += partial + + XSTR [dest2+tmp], xd2 ;Store result into dest2 + XSTR [dest3+tmp], xd3 ;Store result into dest3 + XSTR [dest4+tmp], xd4 ;Store result into dest4 + XSTR [dest5+tmp], xd5 ;Store result into dest5 + XSTR [dest6+tmp], xd6 ;Store result into dest6 + +.return_pass: + FUNC_RESTORE + mov return, 0 + ret + +.return_fail: + FUNC_RESTORE + mov return, 1 + ret + +endproc_frame + +section .data +align 32 +constip32: + ddq 0xf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff + ddq 0xe0e1e2e3e4e5e6e7e8e9eaebecedeeef + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_6VECT_MAD_AVX2, 04, 00, 0211 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_6vect_mad_sse.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_6vect_mad_sse.asm new file mode 100644 index 000000000..9d8374b29 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_6vect_mad_sse.asm @@ -0,0 +1,446 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_6vect_mad_sse(len, vec, vec_i, mul_array, src, dest); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_6VECT_MAD_SSE _gf_6vect_mad_sse +%else + %define GF_6VECT_MAD_SSE gf_6vect_mad_sse +%endif + +%define PS 8 + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg0.w ecx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + %define arg4 r12 + %define arg5 r15 + %define tmp r11 + %define tmp.w r11d + %define tmp2 r10 + %define tmp3 r13 + %define tmp4 r14 + %define tmp5 rdi + %define return rax + %define return.w eax + %define stack_size 16*10 + 5*8 + %define arg(x) [rsp + stack_size + PS + PS*x] + %define func(x) proc_frame x + +%macro FUNC_SAVE 0 + sub rsp, stack_size + movdqa [rsp+16*0],xmm6 + movdqa [rsp+16*1],xmm7 + movdqa [rsp+16*2],xmm8 + movdqa [rsp+16*3],xmm9 + movdqa [rsp+16*4],xmm10 + movdqa [rsp+16*5],xmm11 + movdqa [rsp+16*6],xmm12 + movdqa [rsp+16*7],xmm13 + movdqa [rsp+16*8],xmm14 + movdqa [rsp+16*9],xmm15 + save_reg r12, 10*16 + 0*8 + save_reg r13, 10*16 + 1*8 + save_reg r14, 10*16 + 2*8 + save_reg r15, 10*16 + 3*8 + save_reg rdi, 10*16 + 4*8 + end_prolog + mov arg4, arg(4) + mov arg5, arg(5) +%endmacro + +%macro FUNC_RESTORE 0 + movdqa xmm6, [rsp+16*0] + movdqa xmm7, [rsp+16*1] + movdqa xmm8, [rsp+16*2] + movdqa xmm9, [rsp+16*3] + movdqa xmm10, [rsp+16*4] + movdqa xmm11, [rsp+16*5] + movdqa xmm12, [rsp+16*6] + movdqa xmm13, [rsp+16*7] + movdqa xmm14, [rsp+16*8] + movdqa xmm15, [rsp+16*9] + mov r12, [rsp + 10*16 + 0*8] + mov r13, [rsp + 10*16 + 1*8] + mov r14, [rsp + 10*16 + 2*8] + mov r15, [rsp + 10*16 + 3*8] + mov rdi, [rsp + 10*16 + 4*8] + add rsp, stack_size +%endmacro + +%elifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define tmp.w r11d + %define tmp2 r10 + %define tmp3 r12 + %define tmp4 r13 + %define tmp5 r14 + %define return rax + %define return.w eax + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + push r14 + %endmacro + %macro FUNC_RESTORE 0 + pop r14 + pop r13 + pop r12 + %endmacro +%elifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define tmp.w r11d + %define tmp2 r10 + %define tmp3 r12 + %define tmp4 r13 + %define tmp5 r14 + %define return rax + %define return.w eax + + %define func(x) x: + %macro FUNC_SAVE 0 + push r12 + push r13 + push r14 + %endmacro + %macro FUNC_RESTORE 0 + pop r14 + pop r13 + pop r12 + %endmacro +%endif + +;;; gf_6vect_mad_sse(len, vec, vec_i, mul_array, src, dest) +%define len arg0 +%define len.w arg0.w +%define vec arg1 +%define vec_i arg2 +%define mul_array arg3 +%define src arg4 +%define dest1 arg5 +%define pos return +%define pos.w return.w + +%define dest2 mul_array +%define dest3 tmp2 +%define dest4 tmp4 +%define dest5 tmp5 +%define dest6 vec_i + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR movdqu + %define XSTR movdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR movdqa + %define XSTR movdqa + %else + %define XLDR movntdqa + %define XSTR movntdq + %endif +%endif + +default rel + +[bits 64] +section .text + +%define xmask0f xmm15 +%define xgft4_lo xmm14 +%define xgft4_hi xmm13 +%define xgft5_lo xmm12 +%define xgft5_hi xmm11 +%define xgft6_lo xmm10 +%define xgft6_hi xmm9 + +%define x0 xmm0 +%define xtmpa xmm1 +%define xtmph1 xmm2 +%define xtmpl1 xmm3 +%define xtmph2 xmm4 +%define xtmpl2 xmm5 +%define xtmph3 xmm6 +%define xtmpl3 xmm7 +%define xd1 xmm8 +%define xd2 xtmpl1 +%define xd3 xtmph1 + + +align 16 +global GF_6VECT_MAD_SSE:function +func(GF_6VECT_MAD_SSE) + FUNC_SAVE + sub len, 16 + jl .return_fail + + xor pos, pos + movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + + mov tmp, vec + sal vec_i, 5 ;Multiply by 32 + lea tmp3, [mul_array + vec_i] + sal tmp, 6 ;Multiply by 64 + + sal vec, 5 ;Multiply by 32 + lea vec_i, [tmp + vec] ;vec_i = 96 + lea mul_array, [tmp + vec_i] ;mul_array = 160 + + movdqu xgft5_lo, [tmp3+2*tmp] ;Load array Ex{00}, Ex{01}, ..., Ex{0f} + movdqu xgft5_hi, [tmp3+2*tmp+16] ; " Ex{00}, Ex{10}, ..., Ex{f0} + movdqu xgft4_lo, [tmp3+vec_i] ;Load array Dx{00}, Dx{01}, Dx{02}, ... + movdqu xgft4_hi, [tmp3+vec_i+16] ; " Dx{00}, Dx{10}, Dx{20}, ... , Dx{f0} + movdqu xgft6_lo, [tmp3+mul_array] ;Load array Fx{00}, Fx{01}, ..., Fx{0f} + movdqu xgft6_hi, [tmp3+mul_array+16] ; " Fx{00}, Fx{10}, ..., Fx{f0} + + mov dest2, [dest1+PS] + mov dest3, [dest1+2*PS] + mov dest4, [dest1+3*PS] ; reuse mul_array + mov dest5, [dest1+4*PS] + mov dest6, [dest1+5*PS] ; reuse vec_i + mov dest1, [dest1] + +.loop16: + XLDR x0, [src+pos] ;Get next source vector + + movdqu xtmpl1, [tmp3] ;Load array Ax{00}, Ax{01}, Ax{02}, ... + movdqu xtmph1, [tmp3+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} + movdqu xtmpl2, [tmp3+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... + movdqu xtmph2, [tmp3+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} + movdqu xtmpl3, [tmp3+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... + movdqu xtmph3, [tmp3+2*vec+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} + XLDR xd1, [dest1+pos] ;Get next dest vector + + movdqa xtmpa, x0 ;Keep unshifted copy of src + psraw x0, 4 ;Shift to put high nibble into bits 4-0 + pand x0, xmask0f ;Mask high src nibble in bits 4-0 + pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 + + ;dest1 + pshufb xtmph1, x0 ;Lookup mul table of high nibble + pshufb xtmpl1, xtmpa ;Lookup mul table of low nibble + pxor xtmph1, xtmpl1 ;GF add high and low partials + pxor xd1, xtmph1 + + XLDR xd2, [dest2+pos] ;reuse xtmpl1. Get next dest vector + XLDR xd3, [dest3+pos] ;reuse xtmph1. Get next dest3 vector + + ;dest2 + pshufb xtmph2, x0 ;Lookup mul table of high nibble + pshufb xtmpl2, xtmpa ;Lookup mul table of low nibble + pxor xtmph2, xtmpl2 ;GF add high and low partials + pxor xd2, xtmph2 + + ;dest3 + pshufb xtmph3, x0 ;Lookup mul table of high nibble + pshufb xtmpl3, xtmpa ;Lookup mul table of low nibble + pxor xtmph3, xtmpl3 ;GF add high and low partials + pxor xd3, xtmph3 + + XSTR [dest1+pos], xd1 ;Store result into dest1 + XSTR [dest2+pos], xd2 ;Store result into dest2 + XSTR [dest3+pos], xd3 ;Store result into dest3 + + movdqa xtmph1, xgft4_hi ;Reload const array registers + movdqa xtmpl1, xgft4_lo ;Reload const array registers + movdqa xtmph2, xgft5_hi ;Reload const array registers + movdqa xtmpl2, xgft5_lo ;Reload const array registers + movdqa xtmph3, xgft6_hi ;Reload const array registers + movdqa xtmpl3, xgft6_lo ;Reload const array registers + + ;dest4 + XLDR xd1, [dest4+pos] ;Get next dest vector + pshufb xtmph1, x0 ;Lookup mul table of high nibble + pshufb xtmpl1, xtmpa ;Lookup mul table of low nibble + pxor xtmph1, xtmpl1 ;GF add high and low partials + pxor xd1, xtmph1 + + XLDR xd2, [dest5+pos] ;reuse xtmpl1. Get next dest vector + XLDR xd3, [dest6+pos] ;reuse xtmph1. Get next dest vector + + ;dest5 + pshufb xtmph2, x0 ;Lookup mul table of high nibble + pshufb xtmpl2, xtmpa ;Lookup mul table of low nibble + pxor xtmph2, xtmpl2 ;GF add high and low partials + pxor xd2, xtmph2 + + ;dest6 + pshufb xtmph3, x0 ;Lookup mul table of high nibble + pshufb xtmpl3, xtmpa ;Lookup mul table of low nibble + pxor xtmph3, xtmpl3 ;GF add high and low partials + pxor xd3, xtmph3 + + XSTR [dest4+pos], xd1 ;Store result into dest4 + XSTR [dest5+pos], xd2 ;Store result into dest5 + XSTR [dest6+pos], xd3 ;Store result into dest6 + + add pos, 16 ;Loop on 16 bytes at a time + cmp pos, len + jle .loop16 + + lea tmp, [len + 16] + cmp pos, tmp + je .return_pass + +.lessthan16: + ;; Tail len + ;; Do one more overlap pass + ;; Overlapped offset length-16 + mov tmp, len ;Backup len as len=rdi + + XLDR x0, [src+tmp] ;Get next source vector + XLDR xd1, [dest4+tmp] ;Get next dest vector + XLDR xd2, [dest5+tmp] ;reuse xtmpl1. Get next dest vector + XLDR xd3, [dest6+tmp] ;reuse xtmph1. Get next dest vector + + sub len, pos + + movdqa xtmph3, [constip16] ;Load const of i + 16 + pinsrb xtmpl3, len.w, 15 + pshufb xtmpl3, xmask0f ;Broadcast len to all bytes + pcmpgtb xtmpl3, xtmph3 + + movdqa xtmpa, x0 ;Keep unshifted copy of src + psraw x0, 4 ;Shift to put high nibble into bits 4-0 + pand x0, xmask0f ;Mask high src nibble in bits 4-0 + pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 + + ;dest4 + pshufb xgft4_hi, x0 ;Lookup mul table of high nibble + pshufb xgft4_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft4_hi, xgft4_lo ;GF add high and low partials + pand xgft4_hi, xtmpl3 + pxor xd1, xgft4_hi + + ;dest5 + pshufb xgft5_hi, x0 ;Lookup mul table of high nibble + pshufb xgft5_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft5_hi, xgft5_lo ;GF add high and low partials + pand xgft5_hi, xtmpl3 + pxor xd2, xgft5_hi + + ;dest6 + pshufb xgft6_hi, x0 ;Lookup mul table of high nibble + pshufb xgft6_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft6_hi, xgft6_lo ;GF add high and low partials + pand xgft6_hi, xtmpl3 + pxor xd3, xgft6_hi + + XSTR [dest4+tmp], xd1 ;Store result into dest4 + XSTR [dest5+tmp], xd2 ;Store result into dest5 + XSTR [dest6+tmp], xd3 ;Store result into dest6 + + movdqu xgft4_lo, [tmp3] ;Load array Ax{00}, Ax{01}, Ax{02}, ... + movdqu xgft4_hi, [tmp3+16] ; " Ax{00}, Ax{10}, Ax{20}, ... , Ax{f0} + movdqu xgft5_lo, [tmp3+vec] ;Load array Bx{00}, Bx{01}, Bx{02}, ... + movdqu xgft5_hi, [tmp3+vec+16] ; " Bx{00}, Bx{10}, Bx{20}, ... , Bx{f0} + movdqu xgft6_lo, [tmp3+2*vec] ;Load array Cx{00}, Cx{01}, Cx{02}, ... + movdqu xgft6_hi, [tmp3+2*vec+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} + XLDR xd1, [dest1+tmp] ;Get next dest vector + XLDR xd2, [dest2+tmp] ;reuse xtmpl1. Get next dest vector + XLDR xd3, [dest3+tmp] ;reuse xtmph1. Get next dest3 vector + + ;dest1 + pshufb xgft4_hi, x0 ;Lookup mul table of high nibble + pshufb xgft4_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft4_hi, xgft4_lo ;GF add high and low partials + pand xgft4_hi, xtmpl3 + pxor xd1, xgft4_hi + + ;dest2 + pshufb xgft5_hi, x0 ;Lookup mul table of high nibble + pshufb xgft5_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft5_hi, xgft5_lo ;GF add high and low partials + pand xgft5_hi, xtmpl3 + pxor xd2, xgft5_hi + + ;dest3 + pshufb xgft6_hi, x0 ;Lookup mul table of high nibble + pshufb xgft6_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft6_hi, xgft6_lo ;GF add high and low partials + pand xgft6_hi, xtmpl3 + pxor xd3, xgft6_hi + + XSTR [dest1+tmp], xd1 ;Store result into dest1 + XSTR [dest2+tmp], xd2 ;Store result into dest2 + XSTR [dest3+tmp], xd3 ;Store result into dest3 + +.return_pass: + FUNC_RESTORE + mov return, 0 + ret + +.return_fail: + FUNC_RESTORE + mov return, 1 + ret + +endproc_frame + +section .data + +align 16 + +mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f +constip16: + ddq 0xf0f1f2f3f4f5f6f7f8f9fafbfcfdfeff + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_6VECT_MAD_SSE, 00, 00, 020f diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_vect_dot_prod_avx.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_vect_dot_prod_avx.asm new file mode 100644 index 000000000..dfe0e1f95 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_vect_dot_prod_avx.asm @@ -0,0 +1,303 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_vect_dot_prod_avx(len, vec, *g_tbls, **buffs, *dest); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_VECT_DOT_PROD_AVX _gf_vect_dot_prod_avx +%else + %define GF_VECT_DOT_PROD_AVX gf_vect_dot_prod_avx +%endif + +%ifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + + %define tmp r11 + %define tmp2 r10 + %define tmp3 r9 + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%endif + +%ifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + + %define tmp r11 + %define tmp2 r10 + %define tmp3 r9 + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%endif + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + + %define arg4 r12 ; must be saved and loaded + %define tmp r11 + %define tmp2 r10 + %define tmp3 rdi ; must be saved and loaded + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define frame_size 2*8 + %define arg(x) [rsp + frame_size + PS + PS*x] + + %define func(x) proc_frame x + %macro FUNC_SAVE 0 + rex_push_reg r12 + push_reg rdi + end_prolog + mov arg4, arg(4) + %endmacro + + %macro FUNC_RESTORE 0 + pop rdi + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, elf32 + +;;;================== High Address; +;;; arg4 +;;; arg3 +;;; arg2 +;;; arg1 +;;; arg0 +;;; return +;;;<================= esp of caller +;;; ebp +;;;<================= ebp = esp +;;; esi +;;; edi +;;; ebx +;;;<================= esp of callee +;;; +;;;================== Low Address; + + %define PS 4 + %define LOG_PS 2 + %define func(x) x: + %define arg(x) [ebp + PS*2 + PS*x] + + %define trans ecx ;trans is for the variables in stack + %define arg0 trans + %define arg0_m arg(0) + %define arg1 trans + %define arg1_m arg(1) + %define arg2 arg2_m + %define arg2_m arg(2) + %define arg3 ebx + %define arg4 trans + %define arg4_m arg(4) + %define tmp edx + %define tmp2 edi + %define tmp3 esi + %define return eax + %macro SLDR 2 ;; stack load/restore + mov %1, %2 + %endmacro + %define SSTR SLDR + + %macro FUNC_SAVE 0 + push ebp + mov ebp, esp + push esi + push edi + push ebx + mov arg3, arg(3) + %endmacro + + %macro FUNC_RESTORE 0 + pop ebx + pop edi + pop esi + mov esp, ebp + pop ebp + %endmacro + +%endif ; output formats + +%define len arg0 +%define vec arg1 +%define mul_array arg2 +%define src arg3 +%define dest arg4 + +%define vec_i tmp2 +%define ptr tmp3 +%define pos return + + %ifidn PS,4 ;32-bit code + %define vec_m arg1_m + %define len_m arg0_m + %define dest_m arg4_m + %endif + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR vmovdqu + %define XSTR vmovdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR vmovdqa + %define XSTR vmovdqa + %else + %define XLDR vmovntdqa + %define XSTR vmovntdq + %endif +%endif + +%ifidn PS,8 ; 64-bit code + default rel + [bits 64] +%endif + +section .text + +%define xmask0f xmm5 +%define xgft_lo xmm4 +%define xgft_hi xmm3 + +%define x0 xmm0 +%define xtmpa xmm1 +%define xp xmm2 + +align 16 +global GF_VECT_DOT_PROD_AVX:function +func(GF_VECT_DOT_PROD_AVX) + FUNC_SAVE + SLDR len, len_m + sub len, 16 + SSTR len_m, len + jl .return_fail + xor pos, pos + vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + +.loop16: + vpxor xp, xp + mov tmp, mul_array + xor vec_i, vec_i + +.next_vect: + + mov ptr, [src+vec_i*PS] + vmovdqu xgft_lo, [tmp] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} + vmovdqu xgft_hi, [tmp+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} + XLDR x0, [ptr+pos] ;Get next source vector + + add tmp, 32 + add vec_i, 1 + + vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + + vpshufb xgft_hi, xgft_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft_lo, xgft_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft_hi, xgft_hi, xgft_lo ;GF add high and low partials + vpxor xp, xp, xgft_hi ;xp += partial + + SLDR vec, vec_m + cmp vec_i, vec + jl .next_vect + + SLDR dest, dest_m + XSTR [dest+pos], xp + + add pos, 16 ;Loop on 16 bytes at a time + SLDR len, len_m + cmp pos, len + jle .loop16 + + lea tmp, [len + 16] + cmp pos, tmp + je .return_pass + + ;; Tail len + mov pos, len ;Overlapped offset length-16 + jmp .loop16 ;Do one more overlap pass + +.return_pass: + mov return, 0 + FUNC_RESTORE + ret + +.return_fail: + mov return, 1 + FUNC_RESTORE + ret + +endproc_frame + +section .data + +align 16 + +mask0f: +ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_VECT_DOT_PROD_AVX, 02, 04, 0061 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_vect_dot_prod_avx2.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_vect_dot_prod_avx2.asm new file mode 100644 index 000000000..8744318f5 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_vect_dot_prod_avx2.asm @@ -0,0 +1,315 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_vect_dot_prod_avx2(len, vec, *g_tbls, **buffs, *dest); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_VECT_DOT_PROD_AVX2 _gf_vect_dot_prod_avx2 +%else + %define GF_VECT_DOT_PROD_AVX2 gf_vect_dot_prod_avx2 +%endif + +%ifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define tmp3 r9 + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%endif + +%ifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define tmp3 r9 + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%endif + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + + %define arg4 r12 ; must be saved and loaded + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define tmp2 r10 + %define tmp3 rdi ; must be saved and loaded + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define frame_size 2*8 + %define arg(x) [rsp + frame_size + PS + PS*x] + + %define func(x) proc_frame x + %macro FUNC_SAVE 0 + rex_push_reg r12 + push_reg rdi + end_prolog + mov arg4, arg(4) + %endmacro + + %macro FUNC_RESTORE 0 + pop rdi + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, elf32 + +;;;================== High Address; +;;; arg4 +;;; arg3 +;;; arg2 +;;; arg1 +;;; arg0 +;;; return +;;;<================= esp of caller +;;; ebp +;;;<================= ebp = esp +;;; esi +;;; edi +;;; ebx +;;;<================= esp of callee +;;; +;;;================== Low Address; + + %define PS 4 + %define LOG_PS 2 + %define func(x) x: + %define arg(x) [ebp + PS*2 + PS*x] + + %define trans ecx ;trans is for the variables in stack + %define arg0 trans + %define arg0_m arg(0) + %define arg1 trans + %define arg1_m arg(1) + %define arg2 arg2_m + %define arg2_m arg(2) + %define arg3 ebx + %define arg4 trans + %define arg4_m arg(4) + %define tmp edx + %define tmp.w edx + %define tmp.b dl + %define tmp2 edi + %define tmp3 esi + %define return eax + %macro SLDR 2 ;stack load/restore + mov %1, %2 + %endmacro + %define SSTR SLDR + + %macro FUNC_SAVE 0 + push ebp + mov ebp, esp + push esi + push edi + push ebx + mov arg3, arg(3) + %endmacro + + %macro FUNC_RESTORE 0 + pop ebx + pop edi + pop esi + mov esp, ebp + pop ebp + %endmacro + +%endif ; output formats + +%define len arg0 +%define vec arg1 +%define mul_array arg2 +%define src arg3 +%define dest arg4 + +%define vec_i tmp2 +%define ptr tmp3 +%define pos return + +%ifidn PS,4 ;32-bit code + %define vec_m arg1_m + %define len_m arg0_m + %define dest_m arg4_m +%endif + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR vmovdqu + %define XSTR vmovdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR vmovdqa + %define XSTR vmovdqa + %else + %define XLDR vmovntdqa + %define XSTR vmovntdq + %endif +%endif + +%ifidn PS,8 ;64-bit code + default rel + [bits 64] +%endif + +section .text + +%define xmask0f ymm3 +%define xmask0fx xmm3 +%define xgft_lo ymm4 +%define xgft_hi ymm5 + +%define x0 ymm0 +%define xtmpa ymm1 +%define xp ymm2 + +align 16 +global GF_VECT_DOT_PROD_AVX2:function +func(GF_VECT_DOT_PROD_AVX2) + FUNC_SAVE + SLDR len, len_m + sub len, 32 + SSTR len_m, len + jl .return_fail + xor pos, pos + mov tmp.b, 0x0f + vpinsrb xmask0fx, xmask0fx, tmp.w, 0 + vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f... + +.loop32: + vpxor xp, xp + mov tmp, mul_array + xor vec_i, vec_i + +.next_vect: + + mov ptr, [src+vec_i*PS] + + vmovdqu xgft_lo, [tmp] ;Load array Cx{00}, Cx{01}, Cx{02}, ... + ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} + vperm2i128 xgft_hi, xgft_lo, xgft_lo, 0x11 ; swapped to hi | hi + vperm2i128 xgft_lo, xgft_lo, xgft_lo, 0x00 ; swapped to lo | lo + + XLDR x0, [ptr+pos] ;Get next source vector + + add tmp, 32 + add vec_i, 1 + + vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + + vpshufb xgft_hi, xgft_hi, x0 ;Lookup mul table of high nibble + vpshufb xgft_lo, xgft_lo, xtmpa ;Lookup mul table of low nibble + vpxor xgft_hi, xgft_hi, xgft_lo ;GF add high and low partials + vpxor xp, xp, xgft_hi ;xp += partial + + SLDR vec, vec_m + cmp vec_i, vec + jl .next_vect + + SLDR dest, dest_m + XSTR [dest+pos], xp + + add pos, 32 ;Loop on 32 bytes at a time + SLDR len, len_m + cmp pos, len + jle .loop32 + + lea tmp, [len + 32] + cmp pos, tmp + je .return_pass + + ;; Tail len + mov pos, len ;Overlapped offset length-32 + jmp .loop32 ;Do one more overlap pass + +.return_pass: + mov return, 0 + FUNC_RESTORE + ret + +.return_fail: + mov return, 1 + FUNC_RESTORE + ret + +endproc_frame + +section .data + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_VECT_DOT_PROD_AVX2, 04, 04, 0190 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_vect_dot_prod_sse.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_vect_dot_prod_sse.asm new file mode 100644 index 000000000..9045fd826 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_vect_dot_prod_sse.asm @@ -0,0 +1,303 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_vect_dot_prod_sse(len, vec, *g_tbls, **buffs, *dest); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_VECT_DOT_PROD_SSE _gf_vect_dot_prod_sse +%else + %define GF_VECT_DOT_PROD_SSE gf_vect_dot_prod_sse +%endif + +%ifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + + %define tmp r11 + %define tmp2 r10 + %define tmp3 r9 + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%endif + +%ifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + + %define tmp r11 + %define tmp2 r10 + %define tmp3 r9 + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%endif + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + + %define arg4 r12 ; must be saved and loaded + %define tmp r11 + %define tmp2 r10 + %define tmp3 rdi ; must be saved and loaded + %define return rax + %macro SLDR 2 + %endmacro + %define SSTR SLDR + %define PS 8 + %define frame_size 2*8 + %define arg(x) [rsp + frame_size + PS + PS*x] + + %define func(x) proc_frame x + %macro FUNC_SAVE 0 + rex_push_reg r12 + push_reg rdi + end_prolog + mov arg4, arg(4) + %endmacro + + %macro FUNC_RESTORE 0 + pop rdi + pop r12 + %endmacro +%endif + +%ifidn __OUTPUT_FORMAT__, elf32 + +;;;================== High Address; +;;; arg4 +;;; arg3 +;;; arg2 +;;; arg1 +;;; arg0 +;;; return +;;;<================= esp of caller +;;; ebp +;;;<================= ebp = esp +;;; esi +;;; edi +;;; ebx +;;;<================= esp of callee +;;; +;;;================== Low Address; + + %define PS 4 + %define LOG_PS 2 + %define func(x) x: + %define arg(x) [ebp + PS*2 + PS*x] + + %define trans ecx ;trans is for the variables in stack + %define arg0 trans + %define arg0_m arg(0) + %define arg1 trans + %define arg1_m arg(1) + %define arg2 arg2_m + %define arg2_m arg(2) + %define arg3 ebx + %define arg4 trans + %define arg4_m arg(4) + %define tmp edx + %define tmp2 edi + %define tmp3 esi + %define return eax + %macro SLDR 2 ;; stack load/restore + mov %1, %2 + %endmacro + %define SSTR SLDR + + %macro FUNC_SAVE 0 + push ebp + mov ebp, esp + push esi + push edi + push ebx + mov arg3, arg(3) + %endmacro + + %macro FUNC_RESTORE 0 + pop ebx + pop edi + pop esi + mov esp, ebp + pop ebp + %endmacro + +%endif ; output formats + +%define len arg0 +%define vec arg1 +%define mul_array arg2 +%define src arg3 +%define dest arg4 + +%define vec_i tmp2 +%define ptr tmp3 +%define pos return + + %ifidn PS,4 ;32-bit code + %define vec_m arg1_m + %define len_m arg0_m + %define dest_m arg4_m + %endif + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR movdqu + %define XSTR movdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR movdqa + %define XSTR movdqa + %else + %define XLDR movntdqa + %define XSTR movntdq + %endif +%endif + +%ifidn PS,8 ;64-bit code + default rel + [bits 64] +%endif + +section .text + +%define xmask0f xmm5 +%define xgft_lo xmm4 +%define xgft_hi xmm3 + +%define x0 xmm0 +%define xtmpa xmm1 +%define xp xmm2 + +align 16 +global GF_VECT_DOT_PROD_SSE:function +func(GF_VECT_DOT_PROD_SSE) + FUNC_SAVE + SLDR len, len_m + sub len, 16 + SSTR len_m, len + jl .return_fail + xor pos, pos + movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + +.loop16: + pxor xp, xp + mov tmp, mul_array + xor vec_i, vec_i + +.next_vect: + + mov ptr, [src+vec_i*PS] + movdqu xgft_lo, [tmp] ;Load array Cx{00}, Cx{01}, ..., Cx{0f} + movdqu xgft_hi, [tmp+16] ; " Cx{00}, Cx{10}, ..., Cx{f0} + XLDR x0, [ptr+pos] ;Get next source vector + + add tmp, 32 + add vec_i, 1 + + movdqa xtmpa, x0 ;Keep unshifted copy of src + psraw x0, 4 ;Shift to put high nibble into bits 4-0 + pand x0, xmask0f ;Mask high src nibble in bits 4-0 + pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 + + pshufb xgft_hi, x0 ;Lookup mul table of high nibble + pshufb xgft_lo, xtmpa ;Lookup mul table of low nibble + pxor xgft_hi, xgft_lo ;GF add high and low partials + pxor xp, xgft_hi ;xp += partial + + SLDR vec, vec_m + cmp vec_i, vec + jl .next_vect + + SLDR dest, dest_m + XSTR [dest+pos], xp + + add pos, 16 ;Loop on 16 bytes at a time + SLDR len, len_m + cmp pos, len + jle .loop16 + + lea tmp, [len + 16] + cmp pos, tmp + je .return_pass + + ;; Tail len + mov pos, len ;Overlapped offset length-16 + jmp .loop16 ;Do one more overlap pass + +.return_pass: + mov return, 0 + FUNC_RESTORE + ret + +.return_fail: + mov return, 1 + FUNC_RESTORE + ret + +endproc_frame + +section .data + +align 16 + +mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_VECT_DOT_PROD_SSE, 00, 04, 0060 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_vect_mad_avx.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_vect_mad_avx.asm new file mode 100644 index 000000000..531701a2a --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_vect_mad_avx.asm @@ -0,0 +1,223 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_vect_mad_avx(len, vec, vec_i, mul_array, src, dest); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_VECT_MAD_AVX _gf_vect_mad_avx +%else + %define GF_VECT_MAD_AVX gf_vect_mad_avx +%endif + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg0.w ecx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + %define arg4 r12 + %define arg5 r15 + %define tmp r11 + %define return rax + %define return.w eax + %define PS 8 + %define stack_size 16*3 + 3*8 + %define arg(x) [rsp + stack_size + PS + PS*x] + %define func(x) proc_frame x + +%macro FUNC_SAVE 0 + sub rsp, stack_size + vmovdqa [rsp+16*0],xmm6 + vmovdqa [rsp+16*1],xmm7 + vmovdqa [rsp+16*2],xmm8 + save_reg r12, 3*16 + 0*8 + save_reg r15, 3*16 + 1*8 + end_prolog + mov arg4, arg(4) + mov arg5, arg(5) +%endmacro + +%macro FUNC_RESTORE 0 + vmovdqa xmm6, [rsp+16*0] + vmovdqa xmm7, [rsp+16*1] + vmovdqa xmm8, [rsp+16*2] + mov r12, [rsp + 3*16 + 0*8] + mov r15, [rsp + 3*16 + 1*8] + add rsp, stack_size +%endmacro + +%elifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define return rax + %define return.w eax + + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%elifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define return rax + %define return.w eax + + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%endif + +;;; gf_vect_mad_avx(len, vec, vec_i, mul_array, src, dest) +%define len arg0 +%define len.w arg0.w +%define vec arg1 +%define vec_i arg2 +%define mul_array arg3 +%define src arg4 +%define dest arg5 +%define pos return +%define pos.w return.w + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR vmovdqu + %define XSTR vmovdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR vmovdqa + %define XSTR vmovdqa + %else + %define XLDR vmovntdqa + %define XSTR vmovntdq + %endif +%endif + + +default rel + +[bits 64] +section .text + +%define xmask0f xmm8 +%define xgft_lo xmm7 +%define xgft_hi xmm6 + +%define x0 xmm0 +%define xtmpa xmm1 +%define xtmph xmm2 +%define xtmpl xmm3 +%define xd xmm4 +%define xtmpd xmm5 + +align 16 +global GF_VECT_MAD_AVX:function +func(GF_VECT_MAD_AVX) + FUNC_SAVE + sub len, 16 + jl .return_fail + + xor pos, pos + vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + + sal vec_i, 5 ;Multiply by 32 + vmovdqu xgft_lo, [vec_i+mul_array] ;Load array Cx{00}, Cx{01}, Cx{02}, ... + vmovdqu xgft_hi, [vec_i+mul_array+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} + + XLDR xtmpd, [dest+len] ;backup the last 16 bytes in dest + +.loop16: + XLDR xd, [dest+pos] ;Get next dest vector +.loop16_overlap: + XLDR x0, [src+pos] ;Get next source vector + + vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + + vpshufb xtmph, xgft_hi, x0 ;Lookup mul table of high nibble + vpshufb xtmpl, xgft_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph, xtmph, xtmpl ;GF add high and low partials + vpxor xd, xd, xtmph ;xd += partial + + XSTR [dest+pos], xd + add pos, 16 ;Loop on 16 bytes at a time + cmp pos, len + jle .loop16 + + lea tmp, [len + 16] + cmp pos, tmp + je .return_pass + + ;; Tail len + mov pos, len ;Overlapped offset length-16 + vmovdqa xd, xtmpd ;Restore xd + jmp .loop16_overlap ;Do one more overlap pass + +.return_pass: + mov return, 0 + FUNC_RESTORE + ret + +.return_fail: + mov return, 1 + FUNC_RESTORE + ret + +endproc_frame + +section .data + +align 16 + +mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_VECT_MAD_AVX, 02, 00, 0201 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_vect_mad_avx2.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_vect_mad_avx2.asm new file mode 100644 index 000000000..81b10175d --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_vect_mad_avx2.asm @@ -0,0 +1,233 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_vect_mad_avx2(len, vec, vec_i, mul_array, src, dest); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_VECT_MAD_AVX2 _gf_vect_mad_avx2 +%else + %define GF_VECT_MAD_AVX2 gf_vect_mad_avx2 +%endif + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg0.w ecx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + %define arg4 r12 ; must be saved and loaded + %define arg5 r15 + + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define return rax + %define return.w eax + %define PS 8 + %define stack_size 16*3 + 3*8 + %define arg(x) [rsp + stack_size + PS + PS*x] + %define func(x) proc_frame x + + %macro FUNC_SAVE 0 + sub rsp, stack_size + vmovdqa [rsp+16*0],xmm6 + vmovdqa [rsp+16*1],xmm7 + vmovdqa [rsp+16*2],xmm8 + save_reg r12, 3*16 + 0*8 + save_reg r15, 3*16 + 1*8 + end_prolog + mov arg4, arg(4) + mov arg5, arg(5) + %endmacro + + %macro FUNC_RESTORE 0 + vmovdqa xmm6, [rsp+16*0] + vmovdqa xmm7, [rsp+16*1] + vmovdqa xmm8, [rsp+16*2] + mov r12, [rsp + 3*16 + 0*8] + mov r15, [rsp + 3*16 + 1*8] + add rsp, stack_size + %endmacro + +%elifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define return rax + %define return.w eax + + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%elifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + + %define tmp r11 + %define tmp.w r11d + %define tmp.b r11b + %define return rax + %define return.w eax + + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%endif + + +;;; gf_vect_mad_avx2(len, vec, vec_i, mul_array, src, dest) +%define len arg0 +%define len.w arg0.w +%define vec arg1 +%define vec_i arg2 +%define mul_array arg3 +%define src arg4 +%define dest arg5 +%define pos return +%define pos.w return.w + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR vmovdqu + %define XSTR vmovdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR vmovdqa + %define XSTR vmovdqa + %else + %define XLDR vmovntdqa + %define XSTR vmovntdq + %endif +%endif + + +default rel + +[bits 64] +section .text + +%define xmask0f ymm8 +%define xmask0fx xmm8 +%define xgft_lo ymm7 +%define xgft_hi ymm6 + +%define x0 ymm0 +%define xtmpa ymm1 +%define xtmph ymm2 +%define xtmpl ymm3 +%define xd ymm4 +%define xtmpd ymm5 + +align 16 +global GF_VECT_MAD_AVX2:function +func(GF_VECT_MAD_AVX2) + FUNC_SAVE + sub len, 32 + jl .return_fail + xor pos, pos + mov tmp.b, 0x0f + vpinsrb xmask0fx, xmask0fx, tmp.w, 0 + vpbroadcastb xmask0f, xmask0fx ;Construct mask 0x0f0f0f... + + sal vec_i, 5 ;Multiply by 32 + vmovdqu xgft_lo, [vec_i+mul_array] ;Load array Cx{00}, Cx{01}, Cx{02}, ... + ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} + vperm2i128 xgft_hi, xgft_lo, xgft_lo, 0x11 ; swapped to hi | hi + vperm2i128 xgft_lo, xgft_lo, xgft_lo, 0x00 ; swapped to lo | lo + + XLDR xtmpd, [dest+len] ;backup the last 32 bytes in dest + +.loop32: + XLDR xd, [dest+pos] ;Get next dest vector +.loop32_overlap: + XLDR x0, [src+pos] ;Get next source vector + + vpand xtmpa, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + + vpshufb xtmph, xgft_hi, x0 ;Lookup mul table of high nibble + vpshufb xtmpl, xgft_lo, xtmpa ;Lookup mul table of low nibble + vpxor xtmph, xtmph, xtmpl ;GF add high and low partials + vpxor xd, xd, xtmph ;xd += partial + + XSTR [dest+pos], xd + add pos, 32 ;Loop on 32 bytes at a time + cmp pos, len + jle .loop32 + + lea tmp, [len + 32] + cmp pos, tmp + je .return_pass + + ;; Tail len + mov pos, len ;Overlapped offset length-32 + vmovdqa xd, xtmpd ;Restore xd + jmp .loop32_overlap ;Do one more overlap pass + +.return_pass: + mov return, 0 + FUNC_RESTORE + ret + +.return_fail: + mov return, 1 + FUNC_RESTORE + ret + +endproc_frame + +section .data + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_VECT_MAD_AVX2, 04, 00, 0202 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_vect_mad_sse.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_vect_mad_sse.asm new file mode 100644 index 000000000..d9484d2d9 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_vect_mad_sse.asm @@ -0,0 +1,224 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_vect_mad_sse(len, vec, vec_i, mul_array, src, dest); +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_VECT_MAD_SSE _gf_vect_mad_sse +%else + %define GF_VECT_MAD_SSE gf_vect_mad_sse +%endif + +%ifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg0.w ecx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + %define arg4 r12 + %define arg5 r15 + %define tmp r11 + %define return rax + %define return.w eax + %define PS 8 + %define stack_size 16*3 + 3*8 + %define arg(x) [rsp + stack_size + PS + PS*x] + %define func(x) proc_frame x + +%macro FUNC_SAVE 0 + sub rsp, stack_size + movdqa [rsp+16*0],xmm6 + movdqa [rsp+16*1],xmm7 + movdqa [rsp+16*2],xmm8 + save_reg r12, 3*16 + 0*8 + save_reg r15, 3*16 + 1*8 + end_prolog + mov arg4, arg(4) + mov arg5, arg(5) +%endmacro + +%macro FUNC_RESTORE 0 + movdqa xmm6, [rsp+16*0] + movdqa xmm7, [rsp+16*1] + movdqa xmm8, [rsp+16*2] + mov r12, [rsp + 3*16 + 0*8] + mov r15, [rsp + 3*16 + 1*8] + add rsp, stack_size +%endmacro + +%elifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define return rax + %define return.w eax + + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%elifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg0.w edi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define return rax + %define return.w eax + + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE +%endif + +;;; gf_vect_mad_sse(len, vec, vec_i, mul_array, src, dest) +%define len arg0 +%define len.w arg0.w +%define vec arg1 +%define vec_i arg2 +%define mul_array arg3 +%define src arg4 +%define dest arg5 +%define pos return +%define pos.w return.w + +%ifndef EC_ALIGNED_ADDR +;;; Use Un-aligned load/store + %define XLDR movdqu + %define XSTR movdqu +%else +;;; Use Non-temporal load/stor + %ifdef NO_NT_LDST + %define XLDR movdqa + %define XSTR movdqa + %else + %define XLDR movntdqa + %define XSTR movntdq + %endif +%endif + +default rel + +[bits 64] +section .text + +%define xmask0f xmm8 +%define xgft_lo xmm7 +%define xgft_hi xmm6 + +%define x0 xmm0 +%define xtmpa xmm1 +%define xtmph xmm2 +%define xtmpl xmm3 +%define xd xmm4 +%define xtmpd xmm5 + + +align 16 +global GF_VECT_MAD_SSE:function +func(GF_VECT_MAD_SSE) + FUNC_SAVE + sub len, 16 + jl .return_fail + + xor pos, pos + movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + sal vec_i, 5 ;Multiply by 32 + movdqu xgft_lo, [vec_i+mul_array] ;Load array Cx{00}, Cx{01}, Cx{02}, ... + movdqu xgft_hi, [vec_i+mul_array+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} + + XLDR xtmpd, [dest+len] ;backup the last 16 bytes in dest + +.loop16: + XLDR xd, [dest+pos] ;Get next dest vector +.loop16_overlap: + XLDR x0, [src+pos] ;Get next source vector + movdqa xtmph, xgft_hi ;Reload const array registers + movdqa xtmpl, xgft_lo + movdqa xtmpa, x0 ;Keep unshifted copy of src + psraw x0, 4 ;Shift to put high nibble into bits 4-0 + pand x0, xmask0f ;Mask high src nibble in bits 4-0 + pand xtmpa, xmask0f ;Mask low src nibble in bits 4-0 + pshufb xtmph, x0 ;Lookup mul table of high nibble + pshufb xtmpl, xtmpa ;Lookup mul table of low nibble + pxor xtmph, xtmpl ;GF add high and low partials + + pxor xd, xtmph + XSTR [dest+pos], xd ;Store result + + add pos, 16 ;Loop on 16 bytes at a time + cmp pos, len + jle .loop16 + + lea tmp, [len + 16] + cmp pos, tmp + je .return_pass + + ;; Tail len + mov pos, len ;Overlapped offset length-16 + movdqa xd, xtmpd ;Restore xd + jmp .loop16_overlap ;Do one more overlap pass + +.return_pass: + mov return, 0 + FUNC_RESTORE + ret + +.return_fail: + mov return, 1 + FUNC_RESTORE + ret + +endproc_frame + +section .data + +align 16 + +mask0f: ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_VECT_MAD_SSE, 00, 00, 0200 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_vect_mul.h b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_vect_mul.h new file mode 100644 index 000000000..42aa0a456 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_vect_mul.h @@ -0,0 +1,148 @@ +/********************************************************************** + Copyright(c) 2011-2015 Intel Corporation All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**********************************************************************/ + + +#ifndef _GF_VECT_MUL_H +#define _GF_VECT_MUL_H + +/** + * @file gf_vect_mul.h + * @brief Interface to functions for vector (block) multiplication in GF(2^8). + * + * This file defines the interface to routines used in fast RAID rebuild and + * erasure codes. + */ + +#ifdef __cplusplus +extern "C" { +#endif + + /** + * @brief GF(2^8) vector multiply by constant. + * + * Does a GF(2^8) vector multiply b = Ca where a and b are arrays and C + * is a single field element in GF(2^8). Can be used for RAID6 rebuild + * and partial write functions. Function requires pre-calculation of a + * 32-element constant array based on constant C. gftbl(C) = {C{00}, + * C{01}, C{02}, ... , C{0f} }, {C{00}, C{10}, C{20}, ... , C{f0} }. Len + * and src must be aligned to 32B. + * @requires SSE4.1 + * + * @param len Length of vector in bytes. Must be aligned to 32B. + * @param gftbl Pointer to 32-byte array of pre-calculated constants based on C. + * @param src Pointer to src data array. Must be aligned to 32B. + * @param dest Pointer to destination data array. Must be aligned to 32B. + * @returns 0 pass, other fail + */ + +int gf_vect_mul_sse(int len, unsigned char *gftbl, void *src, void *dest); + + + /** + * @brief GF(2^8) vector multiply by constant. + * + * Does a GF(2^8) vector multiply b = Ca where a and b are arrays and C + * is a single field element in GF(2^8). Can be used for RAID6 rebuild + * and partial write functions. Function requires pre-calculation of a + * 32-element constant array based on constant C. gftbl(C) = {C{00}, + * C{01}, C{02}, ... , C{0f} }, {C{00}, C{10}, C{20}, ... , C{f0} }. Len + * and src must be aligned to 32B. + * @requires AVX + * + * @param len Length of vector in bytes. Must be aligned to 32B. + * @param gftbl Pointer to 32-byte array of pre-calculated constants based on C. + * @param src Pointer to src data array. Must be aligned to 32B. + * @param dest Pointer to destination data array. Must be aligned to 32B. + * @returns 0 pass, other fail + */ + +int gf_vect_mul_avx(int len, unsigned char *gftbl, void *src, void *dest); + + +/** + * @brief GF(2^8) vector multiply by constant, runs appropriate version. + * + * Does a GF(2^8) vector multiply b = Ca where a and b are arrays and C + * is a single field element in GF(2^8). Can be used for RAID6 rebuild + * and partial write functions. Function requires pre-calculation of a + * 32-element constant array based on constant C. gftbl(C) = {C{00}, + * C{01}, C{02}, ... , C{0f} }, {C{00}, C{10}, C{20}, ... , C{f0} }. + * Len and src must be aligned to 32B. + * + * This function determines what instruction sets are enabled + * and selects the appropriate version at runtime. + * + * @param len Length of vector in bytes. Must be aligned to 32B. + * @param gftbl Pointer to 32-byte array of pre-calculated constants based on C. + * @param src Pointer to src data array. Must be aligned to 32B. + * @param dest Pointer to destination data array. Must be aligned to 32B. + * @returns 0 pass, other fail + */ + +int gf_vect_mul(int len, unsigned char *gftbl, void *src, void *dest); + + +/** + * @brief Initialize 32-byte constant array for GF(2^8) vector multiply + * + * Calculates array {C{00}, C{01}, C{02}, ... , C{0f} }, {C{00}, C{10}, + * C{20}, ... , C{f0} } as required by other fast vector multiply + * functions. + * @param c Constant input. + * @param gftbl Table output. + */ + +void gf_vect_mul_init(unsigned char c, unsigned char* gftbl); + + +/** + * @brief GF(2^8) vector multiply by constant, runs baseline version. + * + * Does a GF(2^8) vector multiply b = Ca where a and b are arrays and C + * is a single field element in GF(2^8). Can be used for RAID6 rebuild + * and partial write functions. Function requires pre-calculation of a + * 32-element constant array based on constant C. gftbl(C) = {C{00}, + * C{01}, C{02}, ... , C{0f} }, {C{00}, C{10}, C{20}, ... , C{f0} }. Len + * and src must be aligned to 32B. + * + * @param len Length of vector in bytes. Must be aligned to 32B. + * @param a Pointer to 32-byte array of pre-calculated constants based on C. + * only use 2nd element is used. + * @param src Pointer to src data array. Must be aligned to 32B. + * @param dest Pointer to destination data array. Must be aligned to 32B. + */ + +void gf_vect_mul_base(int len, unsigned char *a, unsigned char *src, + unsigned char *dest); + +#ifdef __cplusplus +} +#endif + +#endif //_GF_VECT_MUL_H diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_vect_mul_avx.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_vect_mul_avx.asm new file mode 100644 index 000000000..80155ba0e --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_vect_mul_avx.asm @@ -0,0 +1,189 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_vect_mul_avx(len, mul_array, src, dest) +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_VECT_MUL_AVX _gf_vect_mul_avx +%else + %define GF_VECT_MUL_AVX gf_vect_mul_avx +%endif + +%ifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define return rax + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE + +%elifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define return rax + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE + +%elifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + %define return rax + %define stack_size 5*16 + 8 ; must be an odd multiple of 8 + %define func(x) proc_frame x + %macro FUNC_SAVE 0 + alloc_stack stack_size + save_xmm128 xmm6, 0*16 + save_xmm128 xmm7, 1*16 + save_xmm128 xmm13, 2*16 + save_xmm128 xmm14, 3*16 + save_xmm128 xmm15, 4*16 + end_prolog + %endmacro + + %macro FUNC_RESTORE 0 + vmovdqa xmm6, [rsp + 0*16] + vmovdqa xmm7, [rsp + 1*16] + vmovdqa xmm13, [rsp + 2*16] + vmovdqa xmm14, [rsp + 3*16] + vmovdqa xmm15, [rsp + 4*16] + add rsp, stack_size + %endmacro + +%endif + + +%define len arg0 +%define mul_array arg1 +%define src arg2 +%define dest arg3 +%define pos return + + +;;; Use Non-temporal load/stor +%ifdef NO_NT_LDST + %define XLDR vmovdqa + %define XSTR vmovdqa +%else + %define XLDR vmovntdqa + %define XSTR vmovntdq +%endif + +default rel + +[bits 64] +section .text + +%define xmask0f xmm15 +%define xgft_lo xmm14 +%define xgft_hi xmm13 + +%define x0 xmm0 +%define xtmp1a xmm1 +%define xtmp1b xmm2 +%define xtmp1c xmm3 +%define x1 xmm4 +%define xtmp2a xmm5 +%define xtmp2b xmm6 +%define xtmp2c xmm7 + +align 16 +global GF_VECT_MUL_AVX:function +func(GF_VECT_MUL_AVX) + FUNC_SAVE + mov pos, 0 + vmovdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + vmovdqu xgft_lo, [mul_array] ;Load array Cx{00}, Cx{01}, Cx{02}, ... + vmovdqu xgft_hi, [mul_array+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} + +loop32: + XLDR x0, [src+pos] ;Get next source vector + XLDR x1, [src+pos+16] ;Get next source vector + 16B ahead + add pos, 32 ;Loop on 16 bytes at a time + cmp pos, len + vpand xtmp1a, x0, xmask0f ;Mask low src nibble in bits 4-0 + vpand xtmp2a, x1, xmask0f + vpsraw x0, x0, 4 ;Shift to put high nibble into bits 4-0 + vpsraw x1, x1, 4 + vpand x0, x0, xmask0f ;Mask high src nibble in bits 4-0 + vpand x1, x1, xmask0f + vpshufb xtmp1b, xgft_hi, x0 ;Lookup mul table of high nibble + vpshufb xtmp1c, xgft_lo, xtmp1a ;Lookup mul table of low nibble + vpshufb xtmp2b, xgft_hi, x1 ;Lookup mul table of high nibble + vpshufb xtmp2c, xgft_lo, xtmp2a ;Lookup mul table of low nibble + vpxor xtmp1b, xtmp1b, xtmp1c ;GF add high and low partials + vpxor xtmp2b, xtmp2b, xtmp2c + XSTR [dest+pos-32], xtmp1b ;Store result + XSTR [dest+pos-16], xtmp2b ;Store +16B result + jl loop32 + + +return_pass: + FUNC_RESTORE + sub pos, len + ret + +return_fail: + FUNC_RESTORE + mov return, 1 + ret + +endproc_frame + +section .data + +align 16 + +mask0f: +ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_VECT_MUL_AVX, 01, 02, 0036 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_vect_mul_sse.asm b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_vect_mul_sse.asm new file mode 100644 index 000000000..30d9acea7 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/gf_vect_mul_sse.asm @@ -0,0 +1,195 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Copyright(c) 2011-2015 Intel Corporation All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in +; the documentation and/or other materials provided with the +; distribution. +; * Neither the name of Intel Corporation nor the names of its +; contributors may be used to endorse or promote products derived +; from this software without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; +;;; gf_vect_mul_sse(len, mul_array, src, dest) +;;; + +%ifidn __OUTPUT_FORMAT__, macho64 + %define GF_VECT_MUL_SSE _gf_vect_mul_sse +%else + %define GF_VECT_MUL_SSE gf_vect_mul_sse +%endif + +%ifidn __OUTPUT_FORMAT__, elf64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define return rax + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE + +%elifidn __OUTPUT_FORMAT__, macho64 + %define arg0 rdi + %define arg1 rsi + %define arg2 rdx + %define arg3 rcx + %define arg4 r8 + %define arg5 r9 + %define tmp r11 + %define return rax + %define func(x) x: + %define FUNC_SAVE + %define FUNC_RESTORE + +%elifidn __OUTPUT_FORMAT__, win64 + %define arg0 rcx + %define arg1 rdx + %define arg2 r8 + %define arg3 r9 + %define return rax + %define stack_size 5*16 + 8 ; must be an odd multiple of 8 + %define func(x) proc_frame x + %macro FUNC_SAVE 0 + alloc_stack stack_size + save_xmm128 xmm6, 0*16 + save_xmm128 xmm7, 1*16 + save_xmm128 xmm13, 2*16 + save_xmm128 xmm14, 3*16 + save_xmm128 xmm15, 4*16 + end_prolog + %endmacro + + %macro FUNC_RESTORE 0 + movdqa xmm6, [rsp + 0*16] + movdqa xmm7, [rsp + 1*16] + movdqa xmm13, [rsp + 2*16] + movdqa xmm14, [rsp + 3*16] + movdqa xmm15, [rsp + 4*16] + add rsp, stack_size + %endmacro + +%endif + + +%define len arg0 +%define mul_array arg1 +%define src arg2 +%define dest arg3 +%define pos return + + +;;; Use Non-temporal load/stor +%ifdef NO_NT_LDST + %define XLDR movdqa + %define XSTR movdqa +%else + %define XLDR movntdqa + %define XSTR movntdq +%endif + +default rel + +[bits 64] +section .text + +%define xmask0f xmm15 +%define xgft_lo xmm14 +%define xgft_hi xmm13 + +%define x0 xmm0 +%define xtmp1a xmm1 +%define xtmp1b xmm2 +%define xtmp1c xmm3 +%define x1 xmm4 +%define xtmp2a xmm5 +%define xtmp2b xmm6 +%define xtmp2c xmm7 + + +align 16 +global GF_VECT_MUL_SSE:function +func(GF_VECT_MUL_SSE) + FUNC_SAVE + mov pos, 0 + movdqa xmask0f, [mask0f] ;Load mask of lower nibble in each byte + movdqu xgft_lo, [mul_array] ;Load array Cx{00}, Cx{01}, Cx{02}, ... + movdqu xgft_hi, [mul_array+16] ; " Cx{00}, Cx{10}, Cx{20}, ... , Cx{f0} + +loop32: + XLDR x0, [src+pos] ;Get next source vector + XLDR x1, [src+pos+16] ;Get next source vector + 16B ahead + movdqa xtmp1b, xgft_hi ;Reload const array registers + movdqa xtmp1c, xgft_lo + movdqa xtmp2b, xgft_hi + movdqa xtmp2c, xgft_lo + movdqa xtmp1a, x0 ;Keep unshifted copy of src + movdqa xtmp2a, x1 + psraw x0, 4 ;Shift to put high nibble into bits 4-0 + psraw x1, 4 + pand xtmp1a, xmask0f ;Mask low src nibble in bits 4-0 + pand xtmp2a, xmask0f + pand x0, xmask0f ;Mask high src nibble in bits 4-0 + pand x1, xmask0f + pshufb xtmp1b, x0 ;Lookup mul table of high nibble + pshufb xtmp1c, xtmp1a ;Lookup mul table of low nibble + pshufb xtmp2b, x1 + pshufb xtmp2c, xtmp2a + pxor xtmp1b, xtmp1c ;GF add high and low partials + pxor xtmp2b, xtmp2c + XSTR [dest+pos], xtmp1b ;Store result + XSTR [dest+pos+16], xtmp2b ;Store +16B result + add pos, 32 ;Loop on 32 bytes at at time + cmp pos, len + jl loop32 + + +return_pass: + sub pos, len + FUNC_RESTORE + ret + +return_fail: + mov return, 1 + FUNC_RESTORE + ret + +endproc_frame + +section .data + +align 16 +mask0f: +ddq 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f + +%macro slversion 4 +global %1_slver_%2%3%4 +global %1_slver +%1_slver: +%1_slver_%2%3%4: + dw 0x%4 + db 0x%3, 0x%2 +%endmacro +;;; func core, ver, snum +slversion GF_VECT_MUL_SSE, 00, 02, 0034 diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/stdint.go b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/stdint.go new file mode 100644 index 000000000..72f6e86ae --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/stdint.go @@ -0,0 +1,38 @@ +/* + * Minimalist Object Storage, (C) 2014 Minio, 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 erasure + +// +// int sizeInt() +// { +// return sizeof(int); +// } +import "C" +import "unsafe" + +var ( + // See http://golang.org/ref/spec#Numeric_types + sizeInt = int(C.sizeInt()) + // SizeInt8 is the byte size of a int8. + sizeInt8 = int(unsafe.Sizeof(int8(0))) + // SizeInt16 is the byte size of a int16. + sizeInt16 = int(unsafe.Sizeof(int16(0))) + // SizeInt32 is the byte size of a int32. + sizeInt32 = int(unsafe.Sizeof(int32(0))) + // SizeInt64 is the byte size of a int64. + sizeInt64 = int(unsafe.Sizeof(int64(0))) +) diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/vandermonde_test.go b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/vandermonde_test.go new file mode 100644 index 000000000..490830557 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/erasure/vandermonde_test.go @@ -0,0 +1,66 @@ +/* + * Minimalist Object Storage, (C) 2014 Minio, 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 erasure + +import ( + "bytes" + + . "gopkg.in/check.v1" +) + +func corruptChunks(chunks [][]byte, errorIndex []int) [][]byte { + for _, err := range errorIndex { + chunks[err] = nil + } + return chunks +} + +func (s *MySuite) TestVanderMondeEncodeDecodeFailure(c *C) { + ep, _ := ValidateParams(k, m, Vandermonde) + + data := []byte("Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.") + + e := NewErasure(ep) + chunks, err := e.Encode(data) + c.Assert(err, IsNil) + + errorIndex := []int{0, 3, 5, 9, 11, 13} + chunks = corruptChunks(chunks, errorIndex) + + _, err = e.Decode(chunks, len(data)) + c.Assert(err, Not(IsNil)) +} + +func (s *MySuite) TestVanderMondeEncodeDecodeSuccess(c *C) { + ep, _ := ValidateParams(k, m, Vandermonde) + + data := []byte("Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.") + + e := NewErasure(ep) + chunks, err := e.Encode(data) + c.Assert(err, IsNil) + + errorIndex := []int{0, 3, 5, 9, 13} + chunks = corruptChunks(chunks, errorIndex) + + recoveredData, err := e.Decode(chunks, len(data)) + c.Assert(err, IsNil) + + if !bytes.Equal(recoveredData, data) { + c.Fatalf("Recovered data mismatches with original data") + } +} diff --git a/Godeps/_workspace/src/github.com/fatih/structs/.gitignore b/pkg/api/Godeps/_workspace/src/github.com/minio-io/iodine/.gitignore similarity index 97% rename from Godeps/_workspace/src/github.com/fatih/structs/.gitignore rename to pkg/api/Godeps/_workspace/src/github.com/minio-io/iodine/.gitignore index 836562412..daf913b1b 100644 --- a/Godeps/_workspace/src/github.com/fatih/structs/.gitignore +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/iodine/.gitignore @@ -21,3 +21,4 @@ _testmain.go *.exe *.test +*.prof diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/iodine/LICENSE b/pkg/api/Godeps/_workspace/src/github.com/minio-io/iodine/LICENSE new file mode 100644 index 000000000..e06d20818 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/iodine/LICENSE @@ -0,0 +1,202 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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. + diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/iodine/README.md b/pkg/api/Godeps/_workspace/src/github.com/minio-io/iodine/README.md new file mode 100644 index 000000000..d7391ea49 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/iodine/README.md @@ -0,0 +1,2 @@ +# iodine +Iodine is an error logging framework for tracing errors. diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/iodine/iodine.go b/pkg/api/Godeps/_workspace/src/github.com/minio-io/iodine/iodine.go new file mode 100644 index 000000000..f1eead9f6 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/iodine/iodine.go @@ -0,0 +1,201 @@ +/* + * Iodine, (C) 2015 Minio, 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 iodine + +import ( + "bytes" + "encoding/json" + "fmt" + "os" + "path" + "reflect" + "runtime" + "strconv" + "strings" + "sync" +) + +// WrappedError is the iodine error which contains a pointer to the original error +// and stack traces. +type Error struct { + EmbeddedError error `json:"-"` + ErrorMessage string + ErrorType string + + Stack []StackEntry +} + +// StackEntry contains the entry in the stack trace +type StackEntry struct { + Host string + File string + Line int + Data map[string]string +} + +var gopath string + +var globalState = struct { + sync.RWMutex + m map[string]string +}{m: make(map[string]string)} + +// SetGlobalState - set global state +func SetGlobalState(key, value string) { + globalState.Lock() + globalState.m[key] = value + globalState.Unlock() +} + +// ClearGlobalState - clear info in globalState struct +func ClearGlobalState() { + globalState.Lock() + for k := range globalState.m { + delete(globalState.m, k) + } + globalState.Unlock() +} + +// GetGlobalState - get map from globalState struct +func GetGlobalState() map[string]string { + result := make(map[string]string) + globalState.RLock() + for k, v := range globalState.m { + result[k] = v + } + globalState.RUnlock() + return result +} + +// GetGlobalStateKey - get value for key from globalState struct +func GetGlobalStateKey(k string) string { + result, ok := globalState.m[k] + if !ok { + return "" + } + return result +} + +// Error - instantiate an error, turning it into an iodine error. +// Adds an initial stack trace. +func New(err error, data map[string]string) error { + if err != nil { + entry := createStackEntry() + var newErr Error + + // check if error is wrapped + switch typedError := err.(type) { + case Error: + { + newErr = typedError + } + default: + { + newErr = Error{ + EmbeddedError: err, + ErrorMessage: err.Error(), + ErrorType: reflect.TypeOf(err).String(), + Stack: []StackEntry{}, + } + } + } + for k, v := range data { + entry.Data[k] = v + } + newErr.Stack = append(newErr.Stack, entry) + return newErr + } + return nil +} + +// createStackEntry - create stack entries +func createStackEntry() StackEntry { + host, _ := os.Hostname() + _, file, line, _ := runtime.Caller(2) + file = strings.TrimPrefix(file, gopath) // trim gopath from file + + data := GetGlobalState() + for k, v := range getSystemData() { + data[k] = v + } + + entry := StackEntry{ + Host: host, + File: file, + Line: line, + Data: data, + } + return entry +} + +func getSystemData() map[string]string { + host, err := os.Hostname() + if err != nil { + host = "" + } + memstats := &runtime.MemStats{} + runtime.ReadMemStats(memstats) + return map[string]string{ + "sys.host": host, + "sys.os": runtime.GOOS, + "sys.arch": runtime.GOARCH, + "sys.go": runtime.Version(), + "sys.cpus": strconv.Itoa(runtime.NumCPU()), + "sys.mem.used": strconv.FormatUint(memstats.Alloc, 10), + "sys.mem.allocated": strconv.FormatUint(memstats.TotalAlloc, 10), + "sys.mem.heap.used": strconv.FormatUint(memstats.HeapAlloc, 10), + "sys.mem.heap.allocated": strconv.FormatUint(memstats.HeapSys, 10), + } +} + +// Annotate an error with a stack entry and returns itself +//func (err *WrappedError) Annotate(info map[string]string) *WrappedError { +// entry := createStackEntry() +// for k, v := range info { +// entry.Data[k] = v +// } +// err.Stack = append(err.Stack, entry) +// return err +//} + +// EmitJSON writes JSON output for the error +func (err Error) EmitJSON() ([]byte, error) { + return json.Marshal(err) +} + +// EmitHumanReadable returns a human readable error message +func (err Error) EmitHumanReadable() string { + var errorBuffer bytes.Buffer + fmt.Fprintln(&errorBuffer, err.ErrorMessage) + for i, entry := range err.Stack { + fmt.Fprintln(&errorBuffer, "-", i, entry.Host+":"+entry.File+":"+strconv.Itoa(entry.Line), entry.Data) + } + return string(errorBuffer.Bytes()) +} + +// Emits the original error message +func (err Error) Error() string { + return err.EmitHumanReadable() +} + +func init() { + _, iodineFile, _, _ := runtime.Caller(0) + iodineFile = path.Dir(iodineFile) // trim iodine.go + iodineFile = path.Dir(iodineFile) // trim iodine + iodineFile = path.Dir(iodineFile) // trim minio-io + gopath = path.Dir(iodineFile) + "/" // trim github.com +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/minio-io/iodine/iodine_test.go b/pkg/api/Godeps/_workspace/src/github.com/minio-io/iodine/iodine_test.go new file mode 100644 index 000000000..9b8ddc0c5 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/minio-io/iodine/iodine_test.go @@ -0,0 +1,97 @@ +/* + * Iodine, (C) 2015 Minio, 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 iodine + +import ( + "encoding/json" + "errors" + "testing" +) + +func TestIodine(t *testing.T) { + iodineError := New(errors.New("Hello"), nil) + iodineError = New(iodineError, nil) + iodineError = New(iodineError, nil) + iodineError = New(iodineError, nil) + switch typedError := iodineError.(type) { + case Error: + { + if len(typedError.Stack) != 4 { + t.Fail() + } + _, err := json.MarshalIndent(typedError, "", " ") + if err != nil { + t.Fail() + } + } + default: + { + t.Fail() + } + } +} + +func TestState(t *testing.T) { + SetGlobalState("hello", "world") + result := GetGlobalStateKey("hello") + if result != "world" { + t.Error("global state not set: hello->world") + t.Fail() + } + ClearGlobalState() + if len(GetGlobalState()) != 0 { + t.Fail() + } + SetGlobalState("foo", "bar") + err := New(errors.New("a simple error"), nil) + switch typedError := err.(type) { + case Error: + { + if res, ok := typedError.Stack[0].Data["foo"]; ok { + if res != "bar" { + t.Error("global state not set: foo->bar") + } + } else { + t.Fail() + } + typedError = New(typedError, map[string]string{"foo2": "bar2"}).(Error) + if res, ok := typedError.Stack[0].Data["foo"]; ok { + if res != "bar" { + t.Error("annotate should not modify previous data entries") + } + } else { + t.Error("annotate should not remove previous data entries") + } + if res, ok := typedError.Stack[1].Data["foo"]; ok { + if res != "bar" { + t.Error("global state should set value properly in annotate") + } + } else { + t.Error("global state should set key properly in annotate") + } + if res, ok := typedError.Stack[1].Data["foo2"]; ok { + if res != "bar2" { + // typedError = Error(typedError, nil).(WrappedError) + t.Error("foo2 -> bar should be set") + } + } else { + // typedError = Error(typedError, nil).(WrappedError) + t.Error("foo2 should be set") + } + } + } +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/.gitignore b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/.gitignore new file mode 100644 index 000000000..00268614f --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/.gitignore @@ -0,0 +1,22 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe diff --git a/Godeps/_workspace/src/github.com/fatih/structs/LICENSE b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/LICENSE.md similarity index 92% rename from Godeps/_workspace/src/github.com/fatih/structs/LICENSE rename to pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/LICENSE.md index 34504e4b3..219994581 100644 --- a/Godeps/_workspace/src/github.com/fatih/structs/LICENSE +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/LICENSE.md @@ -1,6 +1,8 @@ +objx - by Mat Ryer and Tyler Bunnell + The MIT License (MIT) -Copyright (c) 2014 Fatih Arslan +Copyright (c) 2014 Stretchr, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +20,4 @@ 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. \ No newline at end of file +SOFTWARE. diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/README.md b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/README.md new file mode 100644 index 000000000..4aa180687 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/README.md @@ -0,0 +1,3 @@ +# objx + + * Jump into the [API Documentation](http://godoc.org/github.com/stretchr/objx) diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/accessors.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/accessors.go new file mode 100644 index 000000000..721bcac79 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/accessors.go @@ -0,0 +1,179 @@ +package objx + +import ( + "fmt" + "regexp" + "strconv" + "strings" +) + +// arrayAccesRegexString is the regex used to extract the array number +// from the access path +const arrayAccesRegexString = `^(.+)\[([0-9]+)\]$` + +// arrayAccesRegex is the compiled arrayAccesRegexString +var arrayAccesRegex = regexp.MustCompile(arrayAccesRegexString) + +// Get gets the value using the specified selector and +// returns it inside a new Obj object. +// +// If it cannot find the value, Get will return a nil +// value inside an instance of Obj. +// +// Get can only operate directly on map[string]interface{} and []interface. +// +// Example +// +// To access the title of the third chapter of the second book, do: +// +// o.Get("books[1].chapters[2].title") +func (m Map) Get(selector string) *Value { + rawObj := access(m, selector, nil, false, false) + return &Value{data: rawObj} +} + +// Set sets the value using the specified selector and +// returns the object on which Set was called. +// +// Set can only operate directly on map[string]interface{} and []interface +// +// Example +// +// To set the title of the third chapter of the second book, do: +// +// o.Set("books[1].chapters[2].title","Time to Go") +func (m Map) Set(selector string, value interface{}) Map { + access(m, selector, value, true, false) + return m +} + +// access accesses the object using the selector and performs the +// appropriate action. +func access(current, selector, value interface{}, isSet, panics bool) interface{} { + + switch selector.(type) { + case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64: + + if array, ok := current.([]interface{}); ok { + index := intFromInterface(selector) + + if index >= len(array) { + if panics { + panic(fmt.Sprintf("objx: Index %d is out of range. Slice only contains %d items.", index, len(array))) + } + return nil + } + + return array[index] + } + + return nil + + case string: + + selStr := selector.(string) + selSegs := strings.SplitN(selStr, PathSeparator, 2) + thisSel := selSegs[0] + index := -1 + var err error + + // https://github.com/stretchr/objx/issues/12 + if strings.Contains(thisSel, "[") { + + arrayMatches := arrayAccesRegex.FindStringSubmatch(thisSel) + + if len(arrayMatches) > 0 { + + // Get the key into the map + thisSel = arrayMatches[1] + + // Get the index into the array at the key + index, err = strconv.Atoi(arrayMatches[2]) + + if err != nil { + // This should never happen. If it does, something has gone + // seriously wrong. Panic. + panic("objx: Array index is not an integer. Must use array[int].") + } + + } + } + + if curMap, ok := current.(Map); ok { + current = map[string]interface{}(curMap) + } + + // get the object in question + switch current.(type) { + case map[string]interface{}: + curMSI := current.(map[string]interface{}) + if len(selSegs) <= 1 && isSet { + curMSI[thisSel] = value + return nil + } else { + current = curMSI[thisSel] + } + default: + current = nil + } + + if current == nil && panics { + panic(fmt.Sprintf("objx: '%v' invalid on object.", selector)) + } + + // do we need to access the item of an array? + if index > -1 { + if array, ok := current.([]interface{}); ok { + if index < len(array) { + current = array[index] + } else { + if panics { + panic(fmt.Sprintf("objx: Index %d is out of range. Slice only contains %d items.", index, len(array))) + } + current = nil + } + } + } + + if len(selSegs) > 1 { + current = access(current, selSegs[1], value, isSet, panics) + } + + } + + return current + +} + +// intFromInterface converts an interface object to the largest +// representation of an unsigned integer using a type switch and +// assertions +func intFromInterface(selector interface{}) int { + var value int + switch selector.(type) { + case int: + value = selector.(int) + case int8: + value = int(selector.(int8)) + case int16: + value = int(selector.(int16)) + case int32: + value = int(selector.(int32)) + case int64: + value = int(selector.(int64)) + case uint: + value = int(selector.(uint)) + case uint8: + value = int(selector.(uint8)) + case uint16: + value = int(selector.(uint16)) + case uint32: + value = int(selector.(uint32)) + case uint64: + value = int(selector.(uint64)) + default: + panic("objx: array access argument is not an integer type (this should never happen)") + } + + return value +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/accessors_test.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/accessors_test.go new file mode 100644 index 000000000..ce5d8e4aa --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/accessors_test.go @@ -0,0 +1,145 @@ +package objx + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestAccessorsAccessGetSingleField(t *testing.T) { + + current := map[string]interface{}{"name": "Tyler"} + assert.Equal(t, "Tyler", access(current, "name", nil, false, true)) + +} +func TestAccessorsAccessGetDeep(t *testing.T) { + + current := map[string]interface{}{"name": map[string]interface{}{"first": "Tyler", "last": "Bunnell"}} + assert.Equal(t, "Tyler", access(current, "name.first", nil, false, true)) + assert.Equal(t, "Bunnell", access(current, "name.last", nil, false, true)) + +} +func TestAccessorsAccessGetDeepDeep(t *testing.T) { + + current := map[string]interface{}{"one": map[string]interface{}{"two": map[string]interface{}{"three": map[string]interface{}{"four": 4}}}} + assert.Equal(t, 4, access(current, "one.two.three.four", nil, false, true)) + +} +func TestAccessorsAccessGetInsideArray(t *testing.T) { + + current := map[string]interface{}{"names": []interface{}{map[string]interface{}{"first": "Tyler", "last": "Bunnell"}, map[string]interface{}{"first": "Capitol", "last": "Bollocks"}}} + assert.Equal(t, "Tyler", access(current, "names[0].first", nil, false, true)) + assert.Equal(t, "Bunnell", access(current, "names[0].last", nil, false, true)) + assert.Equal(t, "Capitol", access(current, "names[1].first", nil, false, true)) + assert.Equal(t, "Bollocks", access(current, "names[1].last", nil, false, true)) + + assert.Panics(t, func() { + access(current, "names[2]", nil, false, true) + }) + assert.Nil(t, access(current, "names[2]", nil, false, false)) + +} + +func TestAccessorsAccessGetFromArrayWithInt(t *testing.T) { + + current := []interface{}{map[string]interface{}{"first": "Tyler", "last": "Bunnell"}, map[string]interface{}{"first": "Capitol", "last": "Bollocks"}} + one := access(current, 0, nil, false, false) + two := access(current, 1, nil, false, false) + three := access(current, 2, nil, false, false) + + assert.Equal(t, "Tyler", one.(map[string]interface{})["first"]) + assert.Equal(t, "Capitol", two.(map[string]interface{})["first"]) + assert.Nil(t, three) + +} + +func TestAccessorsGet(t *testing.T) { + + current := New(map[string]interface{}{"name": "Tyler"}) + assert.Equal(t, "Tyler", current.Get("name").data) + +} + +func TestAccessorsAccessSetSingleField(t *testing.T) { + + current := map[string]interface{}{"name": "Tyler"} + access(current, "name", "Mat", true, false) + assert.Equal(t, current["name"], "Mat") + + access(current, "age", 29, true, true) + assert.Equal(t, current["age"], 29) + +} + +func TestAccessorsAccessSetSingleFieldNotExisting(t *testing.T) { + + current := map[string]interface{}{} + access(current, "name", "Mat", true, false) + assert.Equal(t, current["name"], "Mat") + +} + +func TestAccessorsAccessSetDeep(t *testing.T) { + + current := map[string]interface{}{"name": map[string]interface{}{"first": "Tyler", "last": "Bunnell"}} + + access(current, "name.first", "Mat", true, true) + access(current, "name.last", "Ryer", true, true) + + assert.Equal(t, "Mat", access(current, "name.first", nil, false, true)) + assert.Equal(t, "Ryer", access(current, "name.last", nil, false, true)) + +} +func TestAccessorsAccessSetDeepDeep(t *testing.T) { + + current := map[string]interface{}{"one": map[string]interface{}{"two": map[string]interface{}{"three": map[string]interface{}{"four": 4}}}} + + access(current, "one.two.three.four", 5, true, true) + + assert.Equal(t, 5, access(current, "one.two.three.four", nil, false, true)) + +} +func TestAccessorsAccessSetArray(t *testing.T) { + + current := map[string]interface{}{"names": []interface{}{"Tyler"}} + + access(current, "names[0]", "Mat", true, true) + + assert.Equal(t, "Mat", access(current, "names[0]", nil, false, true)) + +} +func TestAccessorsAccessSetInsideArray(t *testing.T) { + + current := map[string]interface{}{"names": []interface{}{map[string]interface{}{"first": "Tyler", "last": "Bunnell"}, map[string]interface{}{"first": "Capitol", "last": "Bollocks"}}} + + access(current, "names[0].first", "Mat", true, true) + access(current, "names[0].last", "Ryer", true, true) + access(current, "names[1].first", "Captain", true, true) + access(current, "names[1].last", "Underpants", true, true) + + assert.Equal(t, "Mat", access(current, "names[0].first", nil, false, true)) + assert.Equal(t, "Ryer", access(current, "names[0].last", nil, false, true)) + assert.Equal(t, "Captain", access(current, "names[1].first", nil, false, true)) + assert.Equal(t, "Underpants", access(current, "names[1].last", nil, false, true)) + +} + +func TestAccessorsAccessSetFromArrayWithInt(t *testing.T) { + + current := []interface{}{map[string]interface{}{"first": "Tyler", "last": "Bunnell"}, map[string]interface{}{"first": "Capitol", "last": "Bollocks"}} + one := access(current, 0, nil, false, false) + two := access(current, 1, nil, false, false) + three := access(current, 2, nil, false, false) + + assert.Equal(t, "Tyler", one.(map[string]interface{})["first"]) + assert.Equal(t, "Capitol", two.(map[string]interface{})["first"]) + assert.Nil(t, three) + +} + +func TestAccessorsSet(t *testing.T) { + + current := New(map[string]interface{}{"name": "Tyler"}) + current.Set("name", "Mat") + assert.Equal(t, "Mat", current.Get("name").data) + +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/codegen/array-access.txt b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/codegen/array-access.txt new file mode 100644 index 000000000..306023475 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/codegen/array-access.txt @@ -0,0 +1,14 @@ + case []{1}: + a := object.([]{1}) + if isSet { + a[index] = value.({1}) + } else { + if index >= len(a) { + if panics { + panic(fmt.Sprintf("objx: Index %d is out of range because the []{1} only contains %d items.", index, len(a))) + } + return nil + } else { + return a[index] + } + } diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/codegen/index.html b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/codegen/index.html new file mode 100644 index 000000000..379ffc3c0 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/codegen/index.html @@ -0,0 +1,86 @@ + + + + Codegen + + + + + +

+ Template +

+

+ Use {x} as a placeholder for each argument. +

+ + +

+ Arguments (comma separated) +

+

+ One block per line +

+ + +

+ Output +

+ + + + + + + + diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/codegen/template.txt b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/codegen/template.txt new file mode 100644 index 000000000..b396900b8 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/codegen/template.txt @@ -0,0 +1,286 @@ +/* + {4} ({1} and []{1}) + -------------------------------------------------- +*/ + +// {4} gets the value as a {1}, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) {4}(optionalDefault ...{1}) {1} { + if s, ok := v.data.({1}); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return {3} +} + +// Must{4} gets the value as a {1}. +// +// Panics if the object is not a {1}. +func (v *Value) Must{4}() {1} { + return v.data.({1}) +} + +// {4}Slice gets the value as a []{1}, returns the optionalDefault +// value or nil if the value is not a []{1}. +func (v *Value) {4}Slice(optionalDefault ...[]{1}) []{1} { + if s, ok := v.data.([]{1}); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// Must{4}Slice gets the value as a []{1}. +// +// Panics if the object is not a []{1}. +func (v *Value) Must{4}Slice() []{1} { + return v.data.([]{1}) +} + +// Is{4} gets whether the object contained is a {1} or not. +func (v *Value) Is{4}() bool { + _, ok := v.data.({1}) + return ok +} + +// Is{4}Slice gets whether the object contained is a []{1} or not. +func (v *Value) Is{4}Slice() bool { + _, ok := v.data.([]{1}) + return ok +} + +// Each{4} calls the specified callback for each object +// in the []{1}. +// +// Panics if the object is the wrong type. +func (v *Value) Each{4}(callback func(int, {1}) bool) *Value { + + for index, val := range v.Must{4}Slice() { + carryon := callback(index, val) + if carryon == false { + break + } + } + + return v + +} + +// Where{4} uses the specified decider function to select items +// from the []{1}. The object contained in the result will contain +// only the selected items. +func (v *Value) Where{4}(decider func(int, {1}) bool) *Value { + + var selected []{1} + + v.Each{4}(func(index int, val {1}) bool { + shouldSelect := decider(index, val) + if shouldSelect == false { + selected = append(selected, val) + } + return true + }) + + return &Value{data:selected} + +} + +// Group{4} uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]{1}. +func (v *Value) Group{4}(grouper func(int, {1}) string) *Value { + + groups := make(map[string][]{1}) + + v.Each{4}(func(index int, val {1}) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]{1}, 0) + } + groups[group] = append(groups[group], val) + return true + }) + + return &Value{data:groups} + +} + +// Replace{4} uses the specified function to replace each {1}s +// by iterating each item. The data in the returned result will be a +// []{1} containing the replaced items. +func (v *Value) Replace{4}(replacer func(int, {1}) {1}) *Value { + + arr := v.Must{4}Slice() + replaced := make([]{1}, len(arr)) + + v.Each{4}(func(index int, val {1}) bool { + replaced[index] = replacer(index, val) + return true + }) + + return &Value{data:replaced} + +} + +// Collect{4} uses the specified collector function to collect a value +// for each of the {1}s in the slice. The data returned will be a +// []interface{}. +func (v *Value) Collect{4}(collector func(int, {1}) interface{}) *Value { + + arr := v.Must{4}Slice() + collected := make([]interface{}, len(arr)) + + v.Each{4}(func(index int, val {1}) bool { + collected[index] = collector(index, val) + return true + }) + + return &Value{data:collected} +} + +// ************************************************************ +// TESTS +// ************************************************************ + +func Test{4}(t *testing.T) { + + val := {1}( {2} ) + m := map[string]interface{}{"value": val, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").{4}()) + assert.Equal(t, val, New(m).Get("value").Must{4}()) + assert.Equal(t, {1}({3}), New(m).Get("nothing").{4}()) + assert.Equal(t, val, New(m).Get("nothing").{4}({2})) + + assert.Panics(t, func() { + New(m).Get("age").Must{4}() + }) + +} + +func Test{4}Slice(t *testing.T) { + + val := {1}( {2} ) + m := map[string]interface{}{"value": []{1}{ val }, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").{4}Slice()[0]) + assert.Equal(t, val, New(m).Get("value").Must{4}Slice()[0]) + assert.Equal(t, []{1}(nil), New(m).Get("nothing").{4}Slice()) + assert.Equal(t, val, New(m).Get("nothing").{4}Slice( []{1}{ {1}({2}) } )[0]) + + assert.Panics(t, func() { + New(m).Get("nothing").Must{4}Slice() + }) + +} + +func TestIs{4}(t *testing.T) { + + var v *Value + + v = &Value{data: {1}({2})} + assert.True(t, v.Is{4}()) + + v = &Value{data: []{1}{ {1}({2}) }} + assert.True(t, v.Is{4}Slice()) + +} + +func TestEach{4}(t *testing.T) { + + v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }} + count := 0 + replacedVals := make([]{1}, 0) + assert.Equal(t, v, v.Each{4}(func(i int, val {1}) bool { + + count++ + replacedVals = append(replacedVals, val) + + // abort early + if i == 2 { + return false + } + + return true + + })) + + assert.Equal(t, count, 3) + assert.Equal(t, replacedVals[0], v.Must{4}Slice()[0]) + assert.Equal(t, replacedVals[1], v.Must{4}Slice()[1]) + assert.Equal(t, replacedVals[2], v.Must{4}Slice()[2]) + +} + +func TestWhere{4}(t *testing.T) { + + v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }} + + selected := v.Where{4}(func(i int, val {1}) bool { + return i%2==0 + }).Must{4}Slice() + + assert.Equal(t, 3, len(selected)) + +} + +func TestGroup{4}(t *testing.T) { + + v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }} + + grouped := v.Group{4}(func(i int, val {1}) string { + return fmt.Sprintf("%v", i%2==0) + }).data.(map[string][]{1}) + + assert.Equal(t, 2, len(grouped)) + assert.Equal(t, 3, len(grouped["true"])) + assert.Equal(t, 3, len(grouped["false"])) + +} + +func TestReplace{4}(t *testing.T) { + + v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }} + + rawArr := v.Must{4}Slice() + + replaced := v.Replace{4}(func(index int, val {1}) {1} { + if index < len(rawArr)-1 { + return rawArr[index+1] + } + return rawArr[0] + }) + + replacedArr := replaced.Must{4}Slice() + if assert.Equal(t, 6, len(replacedArr)) { + assert.Equal(t, replacedArr[0], rawArr[1]) + assert.Equal(t, replacedArr[1], rawArr[2]) + assert.Equal(t, replacedArr[2], rawArr[3]) + assert.Equal(t, replacedArr[3], rawArr[4]) + assert.Equal(t, replacedArr[4], rawArr[5]) + assert.Equal(t, replacedArr[5], rawArr[0]) + } + +} + +func TestCollect{4}(t *testing.T) { + + v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }} + + collected := v.Collect{4}(func(index int, val {1}) interface{} { + return index + }) + + collectedArr := collected.MustInterSlice() + if assert.Equal(t, 6, len(collectedArr)) { + assert.Equal(t, collectedArr[0], 0) + assert.Equal(t, collectedArr[1], 1) + assert.Equal(t, collectedArr[2], 2) + assert.Equal(t, collectedArr[3], 3) + assert.Equal(t, collectedArr[4], 4) + assert.Equal(t, collectedArr[5], 5) + } + +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/codegen/types_list.txt b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/codegen/types_list.txt new file mode 100644 index 000000000..069d43d8e --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/codegen/types_list.txt @@ -0,0 +1,20 @@ +Interface,interface{},"something",nil,Inter +Map,map[string]interface{},map[string]interface{}{"name":"Tyler"},nil,MSI +ObjxMap,(Map),New(1),New(nil),ObjxMap +Bool,bool,true,false,Bool +String,string,"hello","",Str +Int,int,1,0,Int +Int8,int8,1,0,Int8 +Int16,int16,1,0,Int16 +Int32,int32,1,0,Int32 +Int64,int64,1,0,Int64 +Uint,uint,1,0,Uint +Uint8,uint8,1,0,Uint8 +Uint16,uint16,1,0,Uint16 +Uint32,uint32,1,0,Uint32 +Uint64,uint64,1,0,Uint64 +Uintptr,uintptr,1,0,Uintptr +Float32,float32,1,0,Float32 +Float64,float64,1,0,Float64 +Complex64,complex64,1,0,Complex64 +Complex128,complex128,1,0,Complex128 diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/constants.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/constants.go new file mode 100644 index 000000000..f9eb42a25 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/constants.go @@ -0,0 +1,13 @@ +package objx + +const ( + // PathSeparator is the character used to separate the elements + // of the keypath. + // + // For example, `location.address.city` + PathSeparator string = "." + + // SignatureSeparator is the character that is used to + // separate the Base64 string from the security signature. + SignatureSeparator = "_" +) diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/conversions.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/conversions.go new file mode 100644 index 000000000..9cdfa9f9f --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/conversions.go @@ -0,0 +1,117 @@ +package objx + +import ( + "bytes" + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "net/url" +) + +// JSON converts the contained object to a JSON string +// representation +func (m Map) JSON() (string, error) { + + result, err := json.Marshal(m) + + if err != nil { + err = errors.New("objx: JSON encode failed with: " + err.Error()) + } + + return string(result), err + +} + +// MustJSON converts the contained object to a JSON string +// representation and panics if there is an error +func (m Map) MustJSON() string { + result, err := m.JSON() + if err != nil { + panic(err.Error()) + } + return result +} + +// Base64 converts the contained object to a Base64 string +// representation of the JSON string representation +func (m Map) Base64() (string, error) { + + var buf bytes.Buffer + + jsonData, err := m.JSON() + if err != nil { + return "", err + } + + encoder := base64.NewEncoder(base64.StdEncoding, &buf) + encoder.Write([]byte(jsonData)) + encoder.Close() + + return buf.String(), nil + +} + +// MustBase64 converts the contained object to a Base64 string +// representation of the JSON string representation and panics +// if there is an error +func (m Map) MustBase64() string { + result, err := m.Base64() + if err != nil { + panic(err.Error()) + } + return result +} + +// SignedBase64 converts the contained object to a Base64 string +// representation of the JSON string representation and signs it +// using the provided key. +func (m Map) SignedBase64(key string) (string, error) { + + base64, err := m.Base64() + if err != nil { + return "", err + } + + sig := HashWithKey(base64, key) + + return base64 + SignatureSeparator + sig, nil + +} + +// MustSignedBase64 converts the contained object to a Base64 string +// representation of the JSON string representation and signs it +// using the provided key and panics if there is an error +func (m Map) MustSignedBase64(key string) string { + result, err := m.SignedBase64(key) + if err != nil { + panic(err.Error()) + } + return result +} + +/* + URL Query + ------------------------------------------------ +*/ + +// URLValues creates a url.Values object from an Obj. This +// function requires that the wrapped object be a map[string]interface{} +func (m Map) URLValues() url.Values { + + vals := make(url.Values) + + for k, v := range m { + //TODO: can this be done without sprintf? + vals.Set(k, fmt.Sprintf("%v", v)) + } + + return vals +} + +// URLQuery gets an encoded URL query representing the given +// Obj. This function requires that the wrapped object be a +// map[string]interface{} +func (m Map) URLQuery() (string, error) { + return m.URLValues().Encode(), nil +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/conversions_test.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/conversions_test.go new file mode 100644 index 000000000..e9ccd2987 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/conversions_test.go @@ -0,0 +1,94 @@ +package objx + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestConversionJSON(t *testing.T) { + + jsonString := `{"name":"Mat"}` + o := MustFromJSON(jsonString) + + result, err := o.JSON() + + if assert.NoError(t, err) { + assert.Equal(t, jsonString, result) + } + + assert.Equal(t, jsonString, o.MustJSON()) + +} + +func TestConversionJSONWithError(t *testing.T) { + + o := MSI() + o["test"] = func() {} + + assert.Panics(t, func() { + o.MustJSON() + }) + + _, err := o.JSON() + + assert.Error(t, err) + +} + +func TestConversionBase64(t *testing.T) { + + o := New(map[string]interface{}{"name": "Mat"}) + + result, err := o.Base64() + + if assert.NoError(t, err) { + assert.Equal(t, "eyJuYW1lIjoiTWF0In0=", result) + } + + assert.Equal(t, "eyJuYW1lIjoiTWF0In0=", o.MustBase64()) + +} + +func TestConversionBase64WithError(t *testing.T) { + + o := MSI() + o["test"] = func() {} + + assert.Panics(t, func() { + o.MustBase64() + }) + + _, err := o.Base64() + + assert.Error(t, err) + +} + +func TestConversionSignedBase64(t *testing.T) { + + o := New(map[string]interface{}{"name": "Mat"}) + + result, err := o.SignedBase64("key") + + if assert.NoError(t, err) { + assert.Equal(t, "eyJuYW1lIjoiTWF0In0=_67ee82916f90b2c0d68c903266e8998c9ef0c3d6", result) + } + + assert.Equal(t, "eyJuYW1lIjoiTWF0In0=_67ee82916f90b2c0d68c903266e8998c9ef0c3d6", o.MustSignedBase64("key")) + +} + +func TestConversionSignedBase64WithError(t *testing.T) { + + o := MSI() + o["test"] = func() {} + + assert.Panics(t, func() { + o.MustSignedBase64("key") + }) + + _, err := o.SignedBase64("key") + + assert.Error(t, err) + +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/doc.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/doc.go new file mode 100644 index 000000000..47bf85e46 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/doc.go @@ -0,0 +1,72 @@ +// objx - Go package for dealing with maps, slices, JSON and other data. +// +// Overview +// +// Objx provides the `objx.Map` type, which is a `map[string]interface{}` that exposes +// a powerful `Get` method (among others) that allows you to easily and quickly get +// access to data within the map, without having to worry too much about type assertions, +// missing data, default values etc. +// +// Pattern +// +// Objx uses a preditable pattern to make access data from within `map[string]interface{}'s +// easy. +// +// Call one of the `objx.` functions to create your `objx.Map` to get going: +// +// m, err := objx.FromJSON(json) +// +// NOTE: Any methods or functions with the `Must` prefix will panic if something goes wrong, +// the rest will be optimistic and try to figure things out without panicking. +// +// Use `Get` to access the value you're interested in. You can use dot and array +// notation too: +// +// m.Get("places[0].latlng") +// +// Once you have saught the `Value` you're interested in, you can use the `Is*` methods +// to determine its type. +// +// if m.Get("code").IsStr() { /* ... */ } +// +// Or you can just assume the type, and use one of the strong type methods to +// extract the real value: +// +// m.Get("code").Int() +// +// If there's no value there (or if it's the wrong type) then a default value +// will be returned, or you can be explicit about the default value. +// +// Get("code").Int(-1) +// +// If you're dealing with a slice of data as a value, Objx provides many useful +// methods for iterating, manipulating and selecting that data. You can find out more +// by exploring the index below. +// +// Reading data +// +// A simple example of how to use Objx: +// +// // use MustFromJSON to make an objx.Map from some JSON +// m := objx.MustFromJSON(`{"name": "Mat", "age": 30}`) +// +// // get the details +// name := m.Get("name").Str() +// age := m.Get("age").Int() +// +// // get their nickname (or use their name if they +// // don't have one) +// nickname := m.Get("nickname").Str(name) +// +// Ranging +// +// Since `objx.Map` is a `map[string]interface{}` you can treat it as such. For +// example, to `range` the data, do what you would expect: +// +// m := objx.MustFromJSON(json) +// for key, value := range m { +// +// /* ... do your magic ... */ +// +// } +package objx diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/fixture_test.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/fixture_test.go new file mode 100644 index 000000000..27f7d9049 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/fixture_test.go @@ -0,0 +1,98 @@ +package objx + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +var fixtures = []struct { + // name is the name of the fixture (used for reporting + // failures) + name string + // data is the JSON data to be worked on + data string + // get is the argument(s) to pass to Get + get interface{} + // output is the expected output + output interface{} +}{ + { + name: "Simple get", + data: `{"name": "Mat"}`, + get: "name", + output: "Mat", + }, + { + name: "Get with dot notation", + data: `{"address": {"city": "Boulder"}}`, + get: "address.city", + output: "Boulder", + }, + { + name: "Deep get with dot notation", + data: `{"one": {"two": {"three": {"four": "hello"}}}}`, + get: "one.two.three.four", + output: "hello", + }, + { + name: "Get missing with dot notation", + data: `{"one": {"two": {"three": {"four": "hello"}}}}`, + get: "one.ten", + output: nil, + }, + { + name: "Get with array notation", + data: `{"tags": ["one", "two", "three"]}`, + get: "tags[1]", + output: "two", + }, + { + name: "Get with array and dot notation", + data: `{"types": { "tags": ["one", "two", "three"]}}`, + get: "types.tags[1]", + output: "two", + }, + { + name: "Get with array and dot notation - field after array", + data: `{"tags": [{"name":"one"}, {"name":"two"}, {"name":"three"}]}`, + get: "tags[1].name", + output: "two", + }, + { + name: "Complex get with array and dot notation", + data: `{"tags": [{"list": [{"one":"pizza"}]}]}`, + get: "tags[0].list[0].one", + output: "pizza", + }, + { + name: "Get field from within string should be nil", + data: `{"name":"Tyler"}`, + get: "name.something", + output: nil, + }, + { + name: "Get field from within string (using array accessor) should be nil", + data: `{"numbers":["one", "two", "three"]}`, + get: "numbers[0].nope", + output: nil, + }, +} + +func TestFixtures(t *testing.T) { + + for _, fixture := range fixtures { + + m := MustFromJSON(fixture.data) + + // get the value + t.Logf("Running get fixture: \"%s\" (%v)", fixture.name, fixture) + value := m.Get(fixture.get.(string)) + + // make sure it matches + assert.Equal(t, fixture.output, value.data, + "Get fixture \"%s\" failed: %v", fixture.name, fixture, + ) + + } + +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/map.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/map.go new file mode 100644 index 000000000..eb6ed8e28 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/map.go @@ -0,0 +1,222 @@ +package objx + +import ( + "encoding/base64" + "encoding/json" + "errors" + "io/ioutil" + "net/url" + "strings" +) + +// MSIConvertable is an interface that defines methods for converting your +// custom types to a map[string]interface{} representation. +type MSIConvertable interface { + // MSI gets a map[string]interface{} (msi) representing the + // object. + MSI() map[string]interface{} +} + +// Map provides extended functionality for working with +// untyped data, in particular map[string]interface (msi). +type Map map[string]interface{} + +// Value returns the internal value instance +func (m Map) Value() *Value { + return &Value{data: m} +} + +// Nil represents a nil Map. +var Nil Map = New(nil) + +// New creates a new Map containing the map[string]interface{} in the data argument. +// If the data argument is not a map[string]interface, New attempts to call the +// MSI() method on the MSIConvertable interface to create one. +func New(data interface{}) Map { + if _, ok := data.(map[string]interface{}); !ok { + if converter, ok := data.(MSIConvertable); ok { + data = converter.MSI() + } else { + return nil + } + } + return Map(data.(map[string]interface{})) +} + +// MSI creates a map[string]interface{} and puts it inside a new Map. +// +// The arguments follow a key, value pattern. +// +// Panics +// +// Panics if any key arugment is non-string or if there are an odd number of arguments. +// +// Example +// +// To easily create Maps: +// +// m := objx.MSI("name", "Mat", "age", 29, "subobj", objx.MSI("active", true)) +// +// // creates an Map equivalent to +// m := objx.New(map[string]interface{}{"name": "Mat", "age": 29, "subobj": map[string]interface{}{"active": true}}) +func MSI(keyAndValuePairs ...interface{}) Map { + + newMap := make(map[string]interface{}) + keyAndValuePairsLen := len(keyAndValuePairs) + + if keyAndValuePairsLen%2 != 0 { + panic("objx: MSI must have an even number of arguments following the 'key, value' pattern.") + } + + for i := 0; i < keyAndValuePairsLen; i = i + 2 { + + key := keyAndValuePairs[i] + value := keyAndValuePairs[i+1] + + // make sure the key is a string + keyString, keyStringOK := key.(string) + if !keyStringOK { + panic("objx: MSI must follow 'string, interface{}' pattern. " + keyString + " is not a valid key.") + } + + newMap[keyString] = value + + } + + return New(newMap) +} + +// ****** Conversion Constructors + +// MustFromJSON creates a new Map containing the data specified in the +// jsonString. +// +// Panics if the JSON is invalid. +func MustFromJSON(jsonString string) Map { + o, err := FromJSON(jsonString) + + if err != nil { + panic("objx: MustFromJSON failed with error: " + err.Error()) + } + + return o +} + +// FromJSON creates a new Map containing the data specified in the +// jsonString. +// +// Returns an error if the JSON is invalid. +func FromJSON(jsonString string) (Map, error) { + + var data interface{} + err := json.Unmarshal([]byte(jsonString), &data) + + if err != nil { + return Nil, err + } + + return New(data), nil + +} + +// FromBase64 creates a new Obj containing the data specified +// in the Base64 string. +// +// The string is an encoded JSON string returned by Base64 +func FromBase64(base64String string) (Map, error) { + + decoder := base64.NewDecoder(base64.StdEncoding, strings.NewReader(base64String)) + + decoded, err := ioutil.ReadAll(decoder) + if err != nil { + return nil, err + } + + return FromJSON(string(decoded)) +} + +// MustFromBase64 creates a new Obj containing the data specified +// in the Base64 string and panics if there is an error. +// +// The string is an encoded JSON string returned by Base64 +func MustFromBase64(base64String string) Map { + + result, err := FromBase64(base64String) + + if err != nil { + panic("objx: MustFromBase64 failed with error: " + err.Error()) + } + + return result +} + +// FromSignedBase64 creates a new Obj containing the data specified +// in the Base64 string. +// +// The string is an encoded JSON string returned by SignedBase64 +func FromSignedBase64(base64String, key string) (Map, error) { + parts := strings.Split(base64String, SignatureSeparator) + if len(parts) != 2 { + return nil, errors.New("objx: Signed base64 string is malformed.") + } + + sig := HashWithKey(parts[0], key) + if parts[1] != sig { + return nil, errors.New("objx: Signature for base64 data does not match.") + } + + return FromBase64(parts[0]) +} + +// MustFromSignedBase64 creates a new Obj containing the data specified +// in the Base64 string and panics if there is an error. +// +// The string is an encoded JSON string returned by Base64 +func MustFromSignedBase64(base64String, key string) Map { + + result, err := FromSignedBase64(base64String, key) + + if err != nil { + panic("objx: MustFromSignedBase64 failed with error: " + err.Error()) + } + + return result +} + +// FromURLQuery generates a new Obj by parsing the specified +// query. +// +// For queries with multiple values, the first value is selected. +func FromURLQuery(query string) (Map, error) { + + vals, err := url.ParseQuery(query) + + if err != nil { + return nil, err + } + + m := make(map[string]interface{}) + for k, vals := range vals { + m[k] = vals[0] + } + + return New(m), nil +} + +// MustFromURLQuery generates a new Obj by parsing the specified +// query. +// +// For queries with multiple values, the first value is selected. +// +// Panics if it encounters an error +func MustFromURLQuery(query string) Map { + + o, err := FromURLQuery(query) + + if err != nil { + panic("objx: MustFromURLQuery failed with error: " + err.Error()) + } + + return o + +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/map_for_test.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/map_for_test.go new file mode 100644 index 000000000..6beb50675 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/map_for_test.go @@ -0,0 +1,10 @@ +package objx + +var TestMap map[string]interface{} = map[string]interface{}{ + "name": "Tyler", + "address": map[string]interface{}{ + "city": "Salt Lake City", + "state": "UT", + }, + "numbers": []interface{}{"one", "two", "three", "four", "five"}, +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/map_test.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/map_test.go new file mode 100644 index 000000000..1f8b45c61 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/map_test.go @@ -0,0 +1,147 @@ +package objx + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +type Convertable struct { + name string +} + +func (c *Convertable) MSI() map[string]interface{} { + return map[string]interface{}{"name": c.name} +} + +type Unconvertable struct { + name string +} + +func TestMapCreation(t *testing.T) { + + o := New(nil) + assert.Nil(t, o) + + o = New("Tyler") + assert.Nil(t, o) + + unconvertable := &Unconvertable{name: "Tyler"} + o = New(unconvertable) + assert.Nil(t, o) + + convertable := &Convertable{name: "Tyler"} + o = New(convertable) + if assert.NotNil(t, convertable) { + assert.Equal(t, "Tyler", o["name"], "Tyler") + } + + o = MSI() + if assert.NotNil(t, o) { + assert.NotNil(t, o) + } + + o = MSI("name", "Tyler") + if assert.NotNil(t, o) { + if assert.NotNil(t, o) { + assert.Equal(t, o["name"], "Tyler") + } + } + +} + +func TestMapMustFromJSONWithError(t *testing.T) { + + _, err := FromJSON(`"name":"Mat"}`) + assert.Error(t, err) + +} + +func TestMapFromJSON(t *testing.T) { + + o := MustFromJSON(`{"name":"Mat"}`) + + if assert.NotNil(t, o) { + if assert.NotNil(t, o) { + assert.Equal(t, "Mat", o["name"]) + } + } + +} + +func TestMapFromJSONWithError(t *testing.T) { + + var m Map + + assert.Panics(t, func() { + m = MustFromJSON(`"name":"Mat"}`) + }) + + assert.Nil(t, m) + +} + +func TestMapFromBase64String(t *testing.T) { + + base64String := "eyJuYW1lIjoiTWF0In0=" + + o, err := FromBase64(base64String) + + if assert.NoError(t, err) { + assert.Equal(t, o.Get("name").Str(), "Mat") + } + + assert.Equal(t, MustFromBase64(base64String).Get("name").Str(), "Mat") + +} + +func TestMapFromBase64StringWithError(t *testing.T) { + + base64String := "eyJuYW1lIjoiTWFasd0In0=" + + _, err := FromBase64(base64String) + + assert.Error(t, err) + + assert.Panics(t, func() { + MustFromBase64(base64String) + }) + +} + +func TestMapFromSignedBase64String(t *testing.T) { + + base64String := "eyJuYW1lIjoiTWF0In0=_67ee82916f90b2c0d68c903266e8998c9ef0c3d6" + + o, err := FromSignedBase64(base64String, "key") + + if assert.NoError(t, err) { + assert.Equal(t, o.Get("name").Str(), "Mat") + } + + assert.Equal(t, MustFromSignedBase64(base64String, "key").Get("name").Str(), "Mat") + +} + +func TestMapFromSignedBase64StringWithError(t *testing.T) { + + base64String := "eyJuYW1lasdIjoiTWF0In0=_67ee82916f90b2c0d68c903266e8998c9ef0c3d6" + + _, err := FromSignedBase64(base64String, "key") + + assert.Error(t, err) + + assert.Panics(t, func() { + MustFromSignedBase64(base64String, "key") + }) + +} + +func TestMapFromURLQuery(t *testing.T) { + + m, err := FromURLQuery("name=tyler&state=UT") + if assert.NoError(t, err) && assert.NotNil(t, m) { + assert.Equal(t, "tyler", m.Get("name").Str()) + assert.Equal(t, "UT", m.Get("state").Str()) + } + +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/mutations.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/mutations.go new file mode 100644 index 000000000..b35c86392 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/mutations.go @@ -0,0 +1,81 @@ +package objx + +// Exclude returns a new Map with the keys in the specified []string +// excluded. +func (d Map) Exclude(exclude []string) Map { + + excluded := make(Map) + for k, v := range d { + var shouldInclude bool = true + for _, toExclude := range exclude { + if k == toExclude { + shouldInclude = false + break + } + } + if shouldInclude { + excluded[k] = v + } + } + + return excluded +} + +// Copy creates a shallow copy of the Obj. +func (m Map) Copy() Map { + copied := make(map[string]interface{}) + for k, v := range m { + copied[k] = v + } + return New(copied) +} + +// Merge blends the specified map with a copy of this map and returns the result. +// +// Keys that appear in both will be selected from the specified map. +// This method requires that the wrapped object be a map[string]interface{} +func (m Map) Merge(merge Map) Map { + return m.Copy().MergeHere(merge) +} + +// Merge blends the specified map with this map and returns the current map. +// +// Keys that appear in both will be selected from the specified map. The original map +// will be modified. This method requires that +// the wrapped object be a map[string]interface{} +func (m Map) MergeHere(merge Map) Map { + + for k, v := range merge { + m[k] = v + } + + return m + +} + +// Transform builds a new Obj giving the transformer a chance +// to change the keys and values as it goes. This method requires that +// the wrapped object be a map[string]interface{} +func (m Map) Transform(transformer func(key string, value interface{}) (string, interface{})) Map { + newMap := make(map[string]interface{}) + for k, v := range m { + modifiedKey, modifiedVal := transformer(k, v) + newMap[modifiedKey] = modifiedVal + } + return New(newMap) +} + +// TransformKeys builds a new map using the specified key mapping. +// +// Unspecified keys will be unaltered. +// This method requires that the wrapped object be a map[string]interface{} +func (m Map) TransformKeys(mapping map[string]string) Map { + return m.Transform(func(key string, value interface{}) (string, interface{}) { + + if newKey, ok := mapping[key]; ok { + return newKey, value + } + + return key, value + }) +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/mutations_test.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/mutations_test.go new file mode 100644 index 000000000..e20ee23bc --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/mutations_test.go @@ -0,0 +1,77 @@ +package objx + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestExclude(t *testing.T) { + + d := make(Map) + d["name"] = "Mat" + d["age"] = 29 + d["secret"] = "ABC" + + excluded := d.Exclude([]string{"secret"}) + + assert.Equal(t, d["name"], excluded["name"]) + assert.Equal(t, d["age"], excluded["age"]) + assert.False(t, excluded.Has("secret"), "secret should be excluded") + +} + +func TestCopy(t *testing.T) { + + d1 := make(map[string]interface{}) + d1["name"] = "Tyler" + d1["location"] = "UT" + + d1Obj := New(d1) + d2Obj := d1Obj.Copy() + + d2Obj["name"] = "Mat" + + assert.Equal(t, d1Obj.Get("name").Str(), "Tyler") + assert.Equal(t, d2Obj.Get("name").Str(), "Mat") + +} + +func TestMerge(t *testing.T) { + + d := make(map[string]interface{}) + d["name"] = "Mat" + + d1 := make(map[string]interface{}) + d1["name"] = "Tyler" + d1["location"] = "UT" + + dObj := New(d) + d1Obj := New(d1) + + merged := dObj.Merge(d1Obj) + + assert.Equal(t, merged.Get("name").Str(), d1Obj.Get("name").Str()) + assert.Equal(t, merged.Get("location").Str(), d1Obj.Get("location").Str()) + assert.Empty(t, dObj.Get("location").Str()) + +} + +func TestMergeHere(t *testing.T) { + + d := make(map[string]interface{}) + d["name"] = "Mat" + + d1 := make(map[string]interface{}) + d1["name"] = "Tyler" + d1["location"] = "UT" + + dObj := New(d) + d1Obj := New(d1) + + merged := dObj.MergeHere(d1Obj) + + assert.Equal(t, dObj, merged, "With MergeHere, it should return the first modified map") + assert.Equal(t, merged.Get("name").Str(), d1Obj.Get("name").Str()) + assert.Equal(t, merged.Get("location").Str(), d1Obj.Get("location").Str()) + assert.Equal(t, merged.Get("location").Str(), dObj.Get("location").Str()) +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/security.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/security.go new file mode 100644 index 000000000..fdd6be9cf --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/security.go @@ -0,0 +1,14 @@ +package objx + +import ( + "crypto/sha1" + "encoding/hex" +) + +// HashWithKey hashes the specified string using the security +// key. +func HashWithKey(data, key string) string { + hash := sha1.New() + hash.Write([]byte(data + ":" + key)) + return hex.EncodeToString(hash.Sum(nil)) +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/security_test.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/security_test.go new file mode 100644 index 000000000..8f0898f62 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/security_test.go @@ -0,0 +1,12 @@ +package objx + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestHashWithKey(t *testing.T) { + + assert.Equal(t, "0ce84d8d01f2c7b6e0882b784429c54d280ea2d9", HashWithKey("abc", "def")) + +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/simple_example_test.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/simple_example_test.go new file mode 100644 index 000000000..5408c7fd3 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/simple_example_test.go @@ -0,0 +1,41 @@ +package objx + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestSimpleExample(t *testing.T) { + + // build a map from a JSON object + o := MustFromJSON(`{"name":"Mat","foods":["indian","chinese"], "location":{"county":"hobbiton","city":"the shire"}}`) + + // Map can be used as a straight map[string]interface{} + assert.Equal(t, o["name"], "Mat") + + // Get an Value object + v := o.Get("name") + assert.Equal(t, v, &Value{data: "Mat"}) + + // Test the contained value + assert.False(t, v.IsInt()) + assert.False(t, v.IsBool()) + assert.True(t, v.IsStr()) + + // Get the contained value + assert.Equal(t, v.Str(), "Mat") + + // Get a default value if the contained value is not of the expected type or does not exist + assert.Equal(t, 1, v.Int(1)) + + // Get a value by using array notation + assert.Equal(t, "indian", o.Get("foods[0]").Data()) + + // Set a value by using array notation + o.Set("foods[0]", "italian") + assert.Equal(t, "italian", o.Get("foods[0]").Str()) + + // Get a value by using dot notation + assert.Equal(t, "hobbiton", o.Get("location.county").Str()) + +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/tests.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/tests.go new file mode 100644 index 000000000..d9e0b479a --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/tests.go @@ -0,0 +1,17 @@ +package objx + +// Has gets whether there is something at the specified selector +// or not. +// +// If m is nil, Has will always return false. +func (m Map) Has(selector string) bool { + if m == nil { + return false + } + return !m.Get(selector).IsNil() +} + +// IsNil gets whether the data is nil or not. +func (v *Value) IsNil() bool { + return v == nil || v.data == nil +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/tests_test.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/tests_test.go new file mode 100644 index 000000000..bcc1eb03d --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/tests_test.go @@ -0,0 +1,24 @@ +package objx + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestHas(t *testing.T) { + + m := New(TestMap) + + assert.True(t, m.Has("name")) + assert.True(t, m.Has("address.state")) + assert.True(t, m.Has("numbers[4]")) + + assert.False(t, m.Has("address.state.nope")) + assert.False(t, m.Has("address.nope")) + assert.False(t, m.Has("nope")) + assert.False(t, m.Has("numbers[5]")) + + m = nil + assert.False(t, m.Has("nothing")) + +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/type_specific_codegen.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/type_specific_codegen.go new file mode 100644 index 000000000..f3ecb29b9 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/type_specific_codegen.go @@ -0,0 +1,2881 @@ +package objx + +/* + Inter (interface{} and []interface{}) + -------------------------------------------------- +*/ + +// Inter gets the value as a interface{}, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Inter(optionalDefault ...interface{}) interface{} { + if s, ok := v.data.(interface{}); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustInter gets the value as a interface{}. +// +// Panics if the object is not a interface{}. +func (v *Value) MustInter() interface{} { + return v.data.(interface{}) +} + +// InterSlice gets the value as a []interface{}, returns the optionalDefault +// value or nil if the value is not a []interface{}. +func (v *Value) InterSlice(optionalDefault ...[]interface{}) []interface{} { + if s, ok := v.data.([]interface{}); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustInterSlice gets the value as a []interface{}. +// +// Panics if the object is not a []interface{}. +func (v *Value) MustInterSlice() []interface{} { + return v.data.([]interface{}) +} + +// IsInter gets whether the object contained is a interface{} or not. +func (v *Value) IsInter() bool { + _, ok := v.data.(interface{}) + return ok +} + +// IsInterSlice gets whether the object contained is a []interface{} or not. +func (v *Value) IsInterSlice() bool { + _, ok := v.data.([]interface{}) + return ok +} + +// EachInter calls the specified callback for each object +// in the []interface{}. +// +// Panics if the object is the wrong type. +func (v *Value) EachInter(callback func(int, interface{}) bool) *Value { + + for index, val := range v.MustInterSlice() { + carryon := callback(index, val) + if carryon == false { + break + } + } + + return v + +} + +// WhereInter uses the specified decider function to select items +// from the []interface{}. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereInter(decider func(int, interface{}) bool) *Value { + + var selected []interface{} + + v.EachInter(func(index int, val interface{}) bool { + shouldSelect := decider(index, val) + if shouldSelect == false { + selected = append(selected, val) + } + return true + }) + + return &Value{data: selected} + +} + +// GroupInter uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]interface{}. +func (v *Value) GroupInter(grouper func(int, interface{}) string) *Value { + + groups := make(map[string][]interface{}) + + v.EachInter(func(index int, val interface{}) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]interface{}, 0) + } + groups[group] = append(groups[group], val) + return true + }) + + return &Value{data: groups} + +} + +// ReplaceInter uses the specified function to replace each interface{}s +// by iterating each item. The data in the returned result will be a +// []interface{} containing the replaced items. +func (v *Value) ReplaceInter(replacer func(int, interface{}) interface{}) *Value { + + arr := v.MustInterSlice() + replaced := make([]interface{}, len(arr)) + + v.EachInter(func(index int, val interface{}) bool { + replaced[index] = replacer(index, val) + return true + }) + + return &Value{data: replaced} + +} + +// CollectInter uses the specified collector function to collect a value +// for each of the interface{}s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectInter(collector func(int, interface{}) interface{}) *Value { + + arr := v.MustInterSlice() + collected := make([]interface{}, len(arr)) + + v.EachInter(func(index int, val interface{}) bool { + collected[index] = collector(index, val) + return true + }) + + return &Value{data: collected} +} + +/* + MSI (map[string]interface{} and []map[string]interface{}) + -------------------------------------------------- +*/ + +// MSI gets the value as a map[string]interface{}, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) MSI(optionalDefault ...map[string]interface{}) map[string]interface{} { + if s, ok := v.data.(map[string]interface{}); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustMSI gets the value as a map[string]interface{}. +// +// Panics if the object is not a map[string]interface{}. +func (v *Value) MustMSI() map[string]interface{} { + return v.data.(map[string]interface{}) +} + +// MSISlice gets the value as a []map[string]interface{}, returns the optionalDefault +// value or nil if the value is not a []map[string]interface{}. +func (v *Value) MSISlice(optionalDefault ...[]map[string]interface{}) []map[string]interface{} { + if s, ok := v.data.([]map[string]interface{}); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustMSISlice gets the value as a []map[string]interface{}. +// +// Panics if the object is not a []map[string]interface{}. +func (v *Value) MustMSISlice() []map[string]interface{} { + return v.data.([]map[string]interface{}) +} + +// IsMSI gets whether the object contained is a map[string]interface{} or not. +func (v *Value) IsMSI() bool { + _, ok := v.data.(map[string]interface{}) + return ok +} + +// IsMSISlice gets whether the object contained is a []map[string]interface{} or not. +func (v *Value) IsMSISlice() bool { + _, ok := v.data.([]map[string]interface{}) + return ok +} + +// EachMSI calls the specified callback for each object +// in the []map[string]interface{}. +// +// Panics if the object is the wrong type. +func (v *Value) EachMSI(callback func(int, map[string]interface{}) bool) *Value { + + for index, val := range v.MustMSISlice() { + carryon := callback(index, val) + if carryon == false { + break + } + } + + return v + +} + +// WhereMSI uses the specified decider function to select items +// from the []map[string]interface{}. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereMSI(decider func(int, map[string]interface{}) bool) *Value { + + var selected []map[string]interface{} + + v.EachMSI(func(index int, val map[string]interface{}) bool { + shouldSelect := decider(index, val) + if shouldSelect == false { + selected = append(selected, val) + } + return true + }) + + return &Value{data: selected} + +} + +// GroupMSI uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]map[string]interface{}. +func (v *Value) GroupMSI(grouper func(int, map[string]interface{}) string) *Value { + + groups := make(map[string][]map[string]interface{}) + + v.EachMSI(func(index int, val map[string]interface{}) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]map[string]interface{}, 0) + } + groups[group] = append(groups[group], val) + return true + }) + + return &Value{data: groups} + +} + +// ReplaceMSI uses the specified function to replace each map[string]interface{}s +// by iterating each item. The data in the returned result will be a +// []map[string]interface{} containing the replaced items. +func (v *Value) ReplaceMSI(replacer func(int, map[string]interface{}) map[string]interface{}) *Value { + + arr := v.MustMSISlice() + replaced := make([]map[string]interface{}, len(arr)) + + v.EachMSI(func(index int, val map[string]interface{}) bool { + replaced[index] = replacer(index, val) + return true + }) + + return &Value{data: replaced} + +} + +// CollectMSI uses the specified collector function to collect a value +// for each of the map[string]interface{}s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectMSI(collector func(int, map[string]interface{}) interface{}) *Value { + + arr := v.MustMSISlice() + collected := make([]interface{}, len(arr)) + + v.EachMSI(func(index int, val map[string]interface{}) bool { + collected[index] = collector(index, val) + return true + }) + + return &Value{data: collected} +} + +/* + ObjxMap ((Map) and [](Map)) + -------------------------------------------------- +*/ + +// ObjxMap gets the value as a (Map), returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) ObjxMap(optionalDefault ...(Map)) Map { + if s, ok := v.data.((Map)); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return New(nil) +} + +// MustObjxMap gets the value as a (Map). +// +// Panics if the object is not a (Map). +func (v *Value) MustObjxMap() Map { + return v.data.((Map)) +} + +// ObjxMapSlice gets the value as a [](Map), returns the optionalDefault +// value or nil if the value is not a [](Map). +func (v *Value) ObjxMapSlice(optionalDefault ...[](Map)) [](Map) { + if s, ok := v.data.([](Map)); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustObjxMapSlice gets the value as a [](Map). +// +// Panics if the object is not a [](Map). +func (v *Value) MustObjxMapSlice() [](Map) { + return v.data.([](Map)) +} + +// IsObjxMap gets whether the object contained is a (Map) or not. +func (v *Value) IsObjxMap() bool { + _, ok := v.data.((Map)) + return ok +} + +// IsObjxMapSlice gets whether the object contained is a [](Map) or not. +func (v *Value) IsObjxMapSlice() bool { + _, ok := v.data.([](Map)) + return ok +} + +// EachObjxMap calls the specified callback for each object +// in the [](Map). +// +// Panics if the object is the wrong type. +func (v *Value) EachObjxMap(callback func(int, Map) bool) *Value { + + for index, val := range v.MustObjxMapSlice() { + carryon := callback(index, val) + if carryon == false { + break + } + } + + return v + +} + +// WhereObjxMap uses the specified decider function to select items +// from the [](Map). The object contained in the result will contain +// only the selected items. +func (v *Value) WhereObjxMap(decider func(int, Map) bool) *Value { + + var selected [](Map) + + v.EachObjxMap(func(index int, val Map) bool { + shouldSelect := decider(index, val) + if shouldSelect == false { + selected = append(selected, val) + } + return true + }) + + return &Value{data: selected} + +} + +// GroupObjxMap uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][](Map). +func (v *Value) GroupObjxMap(grouper func(int, Map) string) *Value { + + groups := make(map[string][](Map)) + + v.EachObjxMap(func(index int, val Map) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([](Map), 0) + } + groups[group] = append(groups[group], val) + return true + }) + + return &Value{data: groups} + +} + +// ReplaceObjxMap uses the specified function to replace each (Map)s +// by iterating each item. The data in the returned result will be a +// [](Map) containing the replaced items. +func (v *Value) ReplaceObjxMap(replacer func(int, Map) Map) *Value { + + arr := v.MustObjxMapSlice() + replaced := make([](Map), len(arr)) + + v.EachObjxMap(func(index int, val Map) bool { + replaced[index] = replacer(index, val) + return true + }) + + return &Value{data: replaced} + +} + +// CollectObjxMap uses the specified collector function to collect a value +// for each of the (Map)s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectObjxMap(collector func(int, Map) interface{}) *Value { + + arr := v.MustObjxMapSlice() + collected := make([]interface{}, len(arr)) + + v.EachObjxMap(func(index int, val Map) bool { + collected[index] = collector(index, val) + return true + }) + + return &Value{data: collected} +} + +/* + Bool (bool and []bool) + -------------------------------------------------- +*/ + +// Bool gets the value as a bool, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Bool(optionalDefault ...bool) bool { + if s, ok := v.data.(bool); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return false +} + +// MustBool gets the value as a bool. +// +// Panics if the object is not a bool. +func (v *Value) MustBool() bool { + return v.data.(bool) +} + +// BoolSlice gets the value as a []bool, returns the optionalDefault +// value or nil if the value is not a []bool. +func (v *Value) BoolSlice(optionalDefault ...[]bool) []bool { + if s, ok := v.data.([]bool); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustBoolSlice gets the value as a []bool. +// +// Panics if the object is not a []bool. +func (v *Value) MustBoolSlice() []bool { + return v.data.([]bool) +} + +// IsBool gets whether the object contained is a bool or not. +func (v *Value) IsBool() bool { + _, ok := v.data.(bool) + return ok +} + +// IsBoolSlice gets whether the object contained is a []bool or not. +func (v *Value) IsBoolSlice() bool { + _, ok := v.data.([]bool) + return ok +} + +// EachBool calls the specified callback for each object +// in the []bool. +// +// Panics if the object is the wrong type. +func (v *Value) EachBool(callback func(int, bool) bool) *Value { + + for index, val := range v.MustBoolSlice() { + carryon := callback(index, val) + if carryon == false { + break + } + } + + return v + +} + +// WhereBool uses the specified decider function to select items +// from the []bool. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereBool(decider func(int, bool) bool) *Value { + + var selected []bool + + v.EachBool(func(index int, val bool) bool { + shouldSelect := decider(index, val) + if shouldSelect == false { + selected = append(selected, val) + } + return true + }) + + return &Value{data: selected} + +} + +// GroupBool uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]bool. +func (v *Value) GroupBool(grouper func(int, bool) string) *Value { + + groups := make(map[string][]bool) + + v.EachBool(func(index int, val bool) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]bool, 0) + } + groups[group] = append(groups[group], val) + return true + }) + + return &Value{data: groups} + +} + +// ReplaceBool uses the specified function to replace each bools +// by iterating each item. The data in the returned result will be a +// []bool containing the replaced items. +func (v *Value) ReplaceBool(replacer func(int, bool) bool) *Value { + + arr := v.MustBoolSlice() + replaced := make([]bool, len(arr)) + + v.EachBool(func(index int, val bool) bool { + replaced[index] = replacer(index, val) + return true + }) + + return &Value{data: replaced} + +} + +// CollectBool uses the specified collector function to collect a value +// for each of the bools in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectBool(collector func(int, bool) interface{}) *Value { + + arr := v.MustBoolSlice() + collected := make([]interface{}, len(arr)) + + v.EachBool(func(index int, val bool) bool { + collected[index] = collector(index, val) + return true + }) + + return &Value{data: collected} +} + +/* + Str (string and []string) + -------------------------------------------------- +*/ + +// Str gets the value as a string, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Str(optionalDefault ...string) string { + if s, ok := v.data.(string); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return "" +} + +// MustStr gets the value as a string. +// +// Panics if the object is not a string. +func (v *Value) MustStr() string { + return v.data.(string) +} + +// StrSlice gets the value as a []string, returns the optionalDefault +// value or nil if the value is not a []string. +func (v *Value) StrSlice(optionalDefault ...[]string) []string { + if s, ok := v.data.([]string); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustStrSlice gets the value as a []string. +// +// Panics if the object is not a []string. +func (v *Value) MustStrSlice() []string { + return v.data.([]string) +} + +// IsStr gets whether the object contained is a string or not. +func (v *Value) IsStr() bool { + _, ok := v.data.(string) + return ok +} + +// IsStrSlice gets whether the object contained is a []string or not. +func (v *Value) IsStrSlice() bool { + _, ok := v.data.([]string) + return ok +} + +// EachStr calls the specified callback for each object +// in the []string. +// +// Panics if the object is the wrong type. +func (v *Value) EachStr(callback func(int, string) bool) *Value { + + for index, val := range v.MustStrSlice() { + carryon := callback(index, val) + if carryon == false { + break + } + } + + return v + +} + +// WhereStr uses the specified decider function to select items +// from the []string. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereStr(decider func(int, string) bool) *Value { + + var selected []string + + v.EachStr(func(index int, val string) bool { + shouldSelect := decider(index, val) + if shouldSelect == false { + selected = append(selected, val) + } + return true + }) + + return &Value{data: selected} + +} + +// GroupStr uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]string. +func (v *Value) GroupStr(grouper func(int, string) string) *Value { + + groups := make(map[string][]string) + + v.EachStr(func(index int, val string) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]string, 0) + } + groups[group] = append(groups[group], val) + return true + }) + + return &Value{data: groups} + +} + +// ReplaceStr uses the specified function to replace each strings +// by iterating each item. The data in the returned result will be a +// []string containing the replaced items. +func (v *Value) ReplaceStr(replacer func(int, string) string) *Value { + + arr := v.MustStrSlice() + replaced := make([]string, len(arr)) + + v.EachStr(func(index int, val string) bool { + replaced[index] = replacer(index, val) + return true + }) + + return &Value{data: replaced} + +} + +// CollectStr uses the specified collector function to collect a value +// for each of the strings in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectStr(collector func(int, string) interface{}) *Value { + + arr := v.MustStrSlice() + collected := make([]interface{}, len(arr)) + + v.EachStr(func(index int, val string) bool { + collected[index] = collector(index, val) + return true + }) + + return &Value{data: collected} +} + +/* + Int (int and []int) + -------------------------------------------------- +*/ + +// Int gets the value as a int, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Int(optionalDefault ...int) int { + if s, ok := v.data.(int); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustInt gets the value as a int. +// +// Panics if the object is not a int. +func (v *Value) MustInt() int { + return v.data.(int) +} + +// IntSlice gets the value as a []int, returns the optionalDefault +// value or nil if the value is not a []int. +func (v *Value) IntSlice(optionalDefault ...[]int) []int { + if s, ok := v.data.([]int); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustIntSlice gets the value as a []int. +// +// Panics if the object is not a []int. +func (v *Value) MustIntSlice() []int { + return v.data.([]int) +} + +// IsInt gets whether the object contained is a int or not. +func (v *Value) IsInt() bool { + _, ok := v.data.(int) + return ok +} + +// IsIntSlice gets whether the object contained is a []int or not. +func (v *Value) IsIntSlice() bool { + _, ok := v.data.([]int) + return ok +} + +// EachInt calls the specified callback for each object +// in the []int. +// +// Panics if the object is the wrong type. +func (v *Value) EachInt(callback func(int, int) bool) *Value { + + for index, val := range v.MustIntSlice() { + carryon := callback(index, val) + if carryon == false { + break + } + } + + return v + +} + +// WhereInt uses the specified decider function to select items +// from the []int. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereInt(decider func(int, int) bool) *Value { + + var selected []int + + v.EachInt(func(index int, val int) bool { + shouldSelect := decider(index, val) + if shouldSelect == false { + selected = append(selected, val) + } + return true + }) + + return &Value{data: selected} + +} + +// GroupInt uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]int. +func (v *Value) GroupInt(grouper func(int, int) string) *Value { + + groups := make(map[string][]int) + + v.EachInt(func(index int, val int) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]int, 0) + } + groups[group] = append(groups[group], val) + return true + }) + + return &Value{data: groups} + +} + +// ReplaceInt uses the specified function to replace each ints +// by iterating each item. The data in the returned result will be a +// []int containing the replaced items. +func (v *Value) ReplaceInt(replacer func(int, int) int) *Value { + + arr := v.MustIntSlice() + replaced := make([]int, len(arr)) + + v.EachInt(func(index int, val int) bool { + replaced[index] = replacer(index, val) + return true + }) + + return &Value{data: replaced} + +} + +// CollectInt uses the specified collector function to collect a value +// for each of the ints in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectInt(collector func(int, int) interface{}) *Value { + + arr := v.MustIntSlice() + collected := make([]interface{}, len(arr)) + + v.EachInt(func(index int, val int) bool { + collected[index] = collector(index, val) + return true + }) + + return &Value{data: collected} +} + +/* + Int8 (int8 and []int8) + -------------------------------------------------- +*/ + +// Int8 gets the value as a int8, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Int8(optionalDefault ...int8) int8 { + if s, ok := v.data.(int8); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustInt8 gets the value as a int8. +// +// Panics if the object is not a int8. +func (v *Value) MustInt8() int8 { + return v.data.(int8) +} + +// Int8Slice gets the value as a []int8, returns the optionalDefault +// value or nil if the value is not a []int8. +func (v *Value) Int8Slice(optionalDefault ...[]int8) []int8 { + if s, ok := v.data.([]int8); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustInt8Slice gets the value as a []int8. +// +// Panics if the object is not a []int8. +func (v *Value) MustInt8Slice() []int8 { + return v.data.([]int8) +} + +// IsInt8 gets whether the object contained is a int8 or not. +func (v *Value) IsInt8() bool { + _, ok := v.data.(int8) + return ok +} + +// IsInt8Slice gets whether the object contained is a []int8 or not. +func (v *Value) IsInt8Slice() bool { + _, ok := v.data.([]int8) + return ok +} + +// EachInt8 calls the specified callback for each object +// in the []int8. +// +// Panics if the object is the wrong type. +func (v *Value) EachInt8(callback func(int, int8) bool) *Value { + + for index, val := range v.MustInt8Slice() { + carryon := callback(index, val) + if carryon == false { + break + } + } + + return v + +} + +// WhereInt8 uses the specified decider function to select items +// from the []int8. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereInt8(decider func(int, int8) bool) *Value { + + var selected []int8 + + v.EachInt8(func(index int, val int8) bool { + shouldSelect := decider(index, val) + if shouldSelect == false { + selected = append(selected, val) + } + return true + }) + + return &Value{data: selected} + +} + +// GroupInt8 uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]int8. +func (v *Value) GroupInt8(grouper func(int, int8) string) *Value { + + groups := make(map[string][]int8) + + v.EachInt8(func(index int, val int8) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]int8, 0) + } + groups[group] = append(groups[group], val) + return true + }) + + return &Value{data: groups} + +} + +// ReplaceInt8 uses the specified function to replace each int8s +// by iterating each item. The data in the returned result will be a +// []int8 containing the replaced items. +func (v *Value) ReplaceInt8(replacer func(int, int8) int8) *Value { + + arr := v.MustInt8Slice() + replaced := make([]int8, len(arr)) + + v.EachInt8(func(index int, val int8) bool { + replaced[index] = replacer(index, val) + return true + }) + + return &Value{data: replaced} + +} + +// CollectInt8 uses the specified collector function to collect a value +// for each of the int8s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectInt8(collector func(int, int8) interface{}) *Value { + + arr := v.MustInt8Slice() + collected := make([]interface{}, len(arr)) + + v.EachInt8(func(index int, val int8) bool { + collected[index] = collector(index, val) + return true + }) + + return &Value{data: collected} +} + +/* + Int16 (int16 and []int16) + -------------------------------------------------- +*/ + +// Int16 gets the value as a int16, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Int16(optionalDefault ...int16) int16 { + if s, ok := v.data.(int16); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustInt16 gets the value as a int16. +// +// Panics if the object is not a int16. +func (v *Value) MustInt16() int16 { + return v.data.(int16) +} + +// Int16Slice gets the value as a []int16, returns the optionalDefault +// value or nil if the value is not a []int16. +func (v *Value) Int16Slice(optionalDefault ...[]int16) []int16 { + if s, ok := v.data.([]int16); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustInt16Slice gets the value as a []int16. +// +// Panics if the object is not a []int16. +func (v *Value) MustInt16Slice() []int16 { + return v.data.([]int16) +} + +// IsInt16 gets whether the object contained is a int16 or not. +func (v *Value) IsInt16() bool { + _, ok := v.data.(int16) + return ok +} + +// IsInt16Slice gets whether the object contained is a []int16 or not. +func (v *Value) IsInt16Slice() bool { + _, ok := v.data.([]int16) + return ok +} + +// EachInt16 calls the specified callback for each object +// in the []int16. +// +// Panics if the object is the wrong type. +func (v *Value) EachInt16(callback func(int, int16) bool) *Value { + + for index, val := range v.MustInt16Slice() { + carryon := callback(index, val) + if carryon == false { + break + } + } + + return v + +} + +// WhereInt16 uses the specified decider function to select items +// from the []int16. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereInt16(decider func(int, int16) bool) *Value { + + var selected []int16 + + v.EachInt16(func(index int, val int16) bool { + shouldSelect := decider(index, val) + if shouldSelect == false { + selected = append(selected, val) + } + return true + }) + + return &Value{data: selected} + +} + +// GroupInt16 uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]int16. +func (v *Value) GroupInt16(grouper func(int, int16) string) *Value { + + groups := make(map[string][]int16) + + v.EachInt16(func(index int, val int16) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]int16, 0) + } + groups[group] = append(groups[group], val) + return true + }) + + return &Value{data: groups} + +} + +// ReplaceInt16 uses the specified function to replace each int16s +// by iterating each item. The data in the returned result will be a +// []int16 containing the replaced items. +func (v *Value) ReplaceInt16(replacer func(int, int16) int16) *Value { + + arr := v.MustInt16Slice() + replaced := make([]int16, len(arr)) + + v.EachInt16(func(index int, val int16) bool { + replaced[index] = replacer(index, val) + return true + }) + + return &Value{data: replaced} + +} + +// CollectInt16 uses the specified collector function to collect a value +// for each of the int16s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectInt16(collector func(int, int16) interface{}) *Value { + + arr := v.MustInt16Slice() + collected := make([]interface{}, len(arr)) + + v.EachInt16(func(index int, val int16) bool { + collected[index] = collector(index, val) + return true + }) + + return &Value{data: collected} +} + +/* + Int32 (int32 and []int32) + -------------------------------------------------- +*/ + +// Int32 gets the value as a int32, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Int32(optionalDefault ...int32) int32 { + if s, ok := v.data.(int32); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustInt32 gets the value as a int32. +// +// Panics if the object is not a int32. +func (v *Value) MustInt32() int32 { + return v.data.(int32) +} + +// Int32Slice gets the value as a []int32, returns the optionalDefault +// value or nil if the value is not a []int32. +func (v *Value) Int32Slice(optionalDefault ...[]int32) []int32 { + if s, ok := v.data.([]int32); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustInt32Slice gets the value as a []int32. +// +// Panics if the object is not a []int32. +func (v *Value) MustInt32Slice() []int32 { + return v.data.([]int32) +} + +// IsInt32 gets whether the object contained is a int32 or not. +func (v *Value) IsInt32() bool { + _, ok := v.data.(int32) + return ok +} + +// IsInt32Slice gets whether the object contained is a []int32 or not. +func (v *Value) IsInt32Slice() bool { + _, ok := v.data.([]int32) + return ok +} + +// EachInt32 calls the specified callback for each object +// in the []int32. +// +// Panics if the object is the wrong type. +func (v *Value) EachInt32(callback func(int, int32) bool) *Value { + + for index, val := range v.MustInt32Slice() { + carryon := callback(index, val) + if carryon == false { + break + } + } + + return v + +} + +// WhereInt32 uses the specified decider function to select items +// from the []int32. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereInt32(decider func(int, int32) bool) *Value { + + var selected []int32 + + v.EachInt32(func(index int, val int32) bool { + shouldSelect := decider(index, val) + if shouldSelect == false { + selected = append(selected, val) + } + return true + }) + + return &Value{data: selected} + +} + +// GroupInt32 uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]int32. +func (v *Value) GroupInt32(grouper func(int, int32) string) *Value { + + groups := make(map[string][]int32) + + v.EachInt32(func(index int, val int32) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]int32, 0) + } + groups[group] = append(groups[group], val) + return true + }) + + return &Value{data: groups} + +} + +// ReplaceInt32 uses the specified function to replace each int32s +// by iterating each item. The data in the returned result will be a +// []int32 containing the replaced items. +func (v *Value) ReplaceInt32(replacer func(int, int32) int32) *Value { + + arr := v.MustInt32Slice() + replaced := make([]int32, len(arr)) + + v.EachInt32(func(index int, val int32) bool { + replaced[index] = replacer(index, val) + return true + }) + + return &Value{data: replaced} + +} + +// CollectInt32 uses the specified collector function to collect a value +// for each of the int32s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectInt32(collector func(int, int32) interface{}) *Value { + + arr := v.MustInt32Slice() + collected := make([]interface{}, len(arr)) + + v.EachInt32(func(index int, val int32) bool { + collected[index] = collector(index, val) + return true + }) + + return &Value{data: collected} +} + +/* + Int64 (int64 and []int64) + -------------------------------------------------- +*/ + +// Int64 gets the value as a int64, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Int64(optionalDefault ...int64) int64 { + if s, ok := v.data.(int64); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustInt64 gets the value as a int64. +// +// Panics if the object is not a int64. +func (v *Value) MustInt64() int64 { + return v.data.(int64) +} + +// Int64Slice gets the value as a []int64, returns the optionalDefault +// value or nil if the value is not a []int64. +func (v *Value) Int64Slice(optionalDefault ...[]int64) []int64 { + if s, ok := v.data.([]int64); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustInt64Slice gets the value as a []int64. +// +// Panics if the object is not a []int64. +func (v *Value) MustInt64Slice() []int64 { + return v.data.([]int64) +} + +// IsInt64 gets whether the object contained is a int64 or not. +func (v *Value) IsInt64() bool { + _, ok := v.data.(int64) + return ok +} + +// IsInt64Slice gets whether the object contained is a []int64 or not. +func (v *Value) IsInt64Slice() bool { + _, ok := v.data.([]int64) + return ok +} + +// EachInt64 calls the specified callback for each object +// in the []int64. +// +// Panics if the object is the wrong type. +func (v *Value) EachInt64(callback func(int, int64) bool) *Value { + + for index, val := range v.MustInt64Slice() { + carryon := callback(index, val) + if carryon == false { + break + } + } + + return v + +} + +// WhereInt64 uses the specified decider function to select items +// from the []int64. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereInt64(decider func(int, int64) bool) *Value { + + var selected []int64 + + v.EachInt64(func(index int, val int64) bool { + shouldSelect := decider(index, val) + if shouldSelect == false { + selected = append(selected, val) + } + return true + }) + + return &Value{data: selected} + +} + +// GroupInt64 uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]int64. +func (v *Value) GroupInt64(grouper func(int, int64) string) *Value { + + groups := make(map[string][]int64) + + v.EachInt64(func(index int, val int64) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]int64, 0) + } + groups[group] = append(groups[group], val) + return true + }) + + return &Value{data: groups} + +} + +// ReplaceInt64 uses the specified function to replace each int64s +// by iterating each item. The data in the returned result will be a +// []int64 containing the replaced items. +func (v *Value) ReplaceInt64(replacer func(int, int64) int64) *Value { + + arr := v.MustInt64Slice() + replaced := make([]int64, len(arr)) + + v.EachInt64(func(index int, val int64) bool { + replaced[index] = replacer(index, val) + return true + }) + + return &Value{data: replaced} + +} + +// CollectInt64 uses the specified collector function to collect a value +// for each of the int64s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectInt64(collector func(int, int64) interface{}) *Value { + + arr := v.MustInt64Slice() + collected := make([]interface{}, len(arr)) + + v.EachInt64(func(index int, val int64) bool { + collected[index] = collector(index, val) + return true + }) + + return &Value{data: collected} +} + +/* + Uint (uint and []uint) + -------------------------------------------------- +*/ + +// Uint gets the value as a uint, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Uint(optionalDefault ...uint) uint { + if s, ok := v.data.(uint); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustUint gets the value as a uint. +// +// Panics if the object is not a uint. +func (v *Value) MustUint() uint { + return v.data.(uint) +} + +// UintSlice gets the value as a []uint, returns the optionalDefault +// value or nil if the value is not a []uint. +func (v *Value) UintSlice(optionalDefault ...[]uint) []uint { + if s, ok := v.data.([]uint); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustUintSlice gets the value as a []uint. +// +// Panics if the object is not a []uint. +func (v *Value) MustUintSlice() []uint { + return v.data.([]uint) +} + +// IsUint gets whether the object contained is a uint or not. +func (v *Value) IsUint() bool { + _, ok := v.data.(uint) + return ok +} + +// IsUintSlice gets whether the object contained is a []uint or not. +func (v *Value) IsUintSlice() bool { + _, ok := v.data.([]uint) + return ok +} + +// EachUint calls the specified callback for each object +// in the []uint. +// +// Panics if the object is the wrong type. +func (v *Value) EachUint(callback func(int, uint) bool) *Value { + + for index, val := range v.MustUintSlice() { + carryon := callback(index, val) + if carryon == false { + break + } + } + + return v + +} + +// WhereUint uses the specified decider function to select items +// from the []uint. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereUint(decider func(int, uint) bool) *Value { + + var selected []uint + + v.EachUint(func(index int, val uint) bool { + shouldSelect := decider(index, val) + if shouldSelect == false { + selected = append(selected, val) + } + return true + }) + + return &Value{data: selected} + +} + +// GroupUint uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]uint. +func (v *Value) GroupUint(grouper func(int, uint) string) *Value { + + groups := make(map[string][]uint) + + v.EachUint(func(index int, val uint) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]uint, 0) + } + groups[group] = append(groups[group], val) + return true + }) + + return &Value{data: groups} + +} + +// ReplaceUint uses the specified function to replace each uints +// by iterating each item. The data in the returned result will be a +// []uint containing the replaced items. +func (v *Value) ReplaceUint(replacer func(int, uint) uint) *Value { + + arr := v.MustUintSlice() + replaced := make([]uint, len(arr)) + + v.EachUint(func(index int, val uint) bool { + replaced[index] = replacer(index, val) + return true + }) + + return &Value{data: replaced} + +} + +// CollectUint uses the specified collector function to collect a value +// for each of the uints in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectUint(collector func(int, uint) interface{}) *Value { + + arr := v.MustUintSlice() + collected := make([]interface{}, len(arr)) + + v.EachUint(func(index int, val uint) bool { + collected[index] = collector(index, val) + return true + }) + + return &Value{data: collected} +} + +/* + Uint8 (uint8 and []uint8) + -------------------------------------------------- +*/ + +// Uint8 gets the value as a uint8, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Uint8(optionalDefault ...uint8) uint8 { + if s, ok := v.data.(uint8); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustUint8 gets the value as a uint8. +// +// Panics if the object is not a uint8. +func (v *Value) MustUint8() uint8 { + return v.data.(uint8) +} + +// Uint8Slice gets the value as a []uint8, returns the optionalDefault +// value or nil if the value is not a []uint8. +func (v *Value) Uint8Slice(optionalDefault ...[]uint8) []uint8 { + if s, ok := v.data.([]uint8); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustUint8Slice gets the value as a []uint8. +// +// Panics if the object is not a []uint8. +func (v *Value) MustUint8Slice() []uint8 { + return v.data.([]uint8) +} + +// IsUint8 gets whether the object contained is a uint8 or not. +func (v *Value) IsUint8() bool { + _, ok := v.data.(uint8) + return ok +} + +// IsUint8Slice gets whether the object contained is a []uint8 or not. +func (v *Value) IsUint8Slice() bool { + _, ok := v.data.([]uint8) + return ok +} + +// EachUint8 calls the specified callback for each object +// in the []uint8. +// +// Panics if the object is the wrong type. +func (v *Value) EachUint8(callback func(int, uint8) bool) *Value { + + for index, val := range v.MustUint8Slice() { + carryon := callback(index, val) + if carryon == false { + break + } + } + + return v + +} + +// WhereUint8 uses the specified decider function to select items +// from the []uint8. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereUint8(decider func(int, uint8) bool) *Value { + + var selected []uint8 + + v.EachUint8(func(index int, val uint8) bool { + shouldSelect := decider(index, val) + if shouldSelect == false { + selected = append(selected, val) + } + return true + }) + + return &Value{data: selected} + +} + +// GroupUint8 uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]uint8. +func (v *Value) GroupUint8(grouper func(int, uint8) string) *Value { + + groups := make(map[string][]uint8) + + v.EachUint8(func(index int, val uint8) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]uint8, 0) + } + groups[group] = append(groups[group], val) + return true + }) + + return &Value{data: groups} + +} + +// ReplaceUint8 uses the specified function to replace each uint8s +// by iterating each item. The data in the returned result will be a +// []uint8 containing the replaced items. +func (v *Value) ReplaceUint8(replacer func(int, uint8) uint8) *Value { + + arr := v.MustUint8Slice() + replaced := make([]uint8, len(arr)) + + v.EachUint8(func(index int, val uint8) bool { + replaced[index] = replacer(index, val) + return true + }) + + return &Value{data: replaced} + +} + +// CollectUint8 uses the specified collector function to collect a value +// for each of the uint8s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectUint8(collector func(int, uint8) interface{}) *Value { + + arr := v.MustUint8Slice() + collected := make([]interface{}, len(arr)) + + v.EachUint8(func(index int, val uint8) bool { + collected[index] = collector(index, val) + return true + }) + + return &Value{data: collected} +} + +/* + Uint16 (uint16 and []uint16) + -------------------------------------------------- +*/ + +// Uint16 gets the value as a uint16, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Uint16(optionalDefault ...uint16) uint16 { + if s, ok := v.data.(uint16); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustUint16 gets the value as a uint16. +// +// Panics if the object is not a uint16. +func (v *Value) MustUint16() uint16 { + return v.data.(uint16) +} + +// Uint16Slice gets the value as a []uint16, returns the optionalDefault +// value or nil if the value is not a []uint16. +func (v *Value) Uint16Slice(optionalDefault ...[]uint16) []uint16 { + if s, ok := v.data.([]uint16); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustUint16Slice gets the value as a []uint16. +// +// Panics if the object is not a []uint16. +func (v *Value) MustUint16Slice() []uint16 { + return v.data.([]uint16) +} + +// IsUint16 gets whether the object contained is a uint16 or not. +func (v *Value) IsUint16() bool { + _, ok := v.data.(uint16) + return ok +} + +// IsUint16Slice gets whether the object contained is a []uint16 or not. +func (v *Value) IsUint16Slice() bool { + _, ok := v.data.([]uint16) + return ok +} + +// EachUint16 calls the specified callback for each object +// in the []uint16. +// +// Panics if the object is the wrong type. +func (v *Value) EachUint16(callback func(int, uint16) bool) *Value { + + for index, val := range v.MustUint16Slice() { + carryon := callback(index, val) + if carryon == false { + break + } + } + + return v + +} + +// WhereUint16 uses the specified decider function to select items +// from the []uint16. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereUint16(decider func(int, uint16) bool) *Value { + + var selected []uint16 + + v.EachUint16(func(index int, val uint16) bool { + shouldSelect := decider(index, val) + if shouldSelect == false { + selected = append(selected, val) + } + return true + }) + + return &Value{data: selected} + +} + +// GroupUint16 uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]uint16. +func (v *Value) GroupUint16(grouper func(int, uint16) string) *Value { + + groups := make(map[string][]uint16) + + v.EachUint16(func(index int, val uint16) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]uint16, 0) + } + groups[group] = append(groups[group], val) + return true + }) + + return &Value{data: groups} + +} + +// ReplaceUint16 uses the specified function to replace each uint16s +// by iterating each item. The data in the returned result will be a +// []uint16 containing the replaced items. +func (v *Value) ReplaceUint16(replacer func(int, uint16) uint16) *Value { + + arr := v.MustUint16Slice() + replaced := make([]uint16, len(arr)) + + v.EachUint16(func(index int, val uint16) bool { + replaced[index] = replacer(index, val) + return true + }) + + return &Value{data: replaced} + +} + +// CollectUint16 uses the specified collector function to collect a value +// for each of the uint16s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectUint16(collector func(int, uint16) interface{}) *Value { + + arr := v.MustUint16Slice() + collected := make([]interface{}, len(arr)) + + v.EachUint16(func(index int, val uint16) bool { + collected[index] = collector(index, val) + return true + }) + + return &Value{data: collected} +} + +/* + Uint32 (uint32 and []uint32) + -------------------------------------------------- +*/ + +// Uint32 gets the value as a uint32, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Uint32(optionalDefault ...uint32) uint32 { + if s, ok := v.data.(uint32); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustUint32 gets the value as a uint32. +// +// Panics if the object is not a uint32. +func (v *Value) MustUint32() uint32 { + return v.data.(uint32) +} + +// Uint32Slice gets the value as a []uint32, returns the optionalDefault +// value or nil if the value is not a []uint32. +func (v *Value) Uint32Slice(optionalDefault ...[]uint32) []uint32 { + if s, ok := v.data.([]uint32); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustUint32Slice gets the value as a []uint32. +// +// Panics if the object is not a []uint32. +func (v *Value) MustUint32Slice() []uint32 { + return v.data.([]uint32) +} + +// IsUint32 gets whether the object contained is a uint32 or not. +func (v *Value) IsUint32() bool { + _, ok := v.data.(uint32) + return ok +} + +// IsUint32Slice gets whether the object contained is a []uint32 or not. +func (v *Value) IsUint32Slice() bool { + _, ok := v.data.([]uint32) + return ok +} + +// EachUint32 calls the specified callback for each object +// in the []uint32. +// +// Panics if the object is the wrong type. +func (v *Value) EachUint32(callback func(int, uint32) bool) *Value { + + for index, val := range v.MustUint32Slice() { + carryon := callback(index, val) + if carryon == false { + break + } + } + + return v + +} + +// WhereUint32 uses the specified decider function to select items +// from the []uint32. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereUint32(decider func(int, uint32) bool) *Value { + + var selected []uint32 + + v.EachUint32(func(index int, val uint32) bool { + shouldSelect := decider(index, val) + if shouldSelect == false { + selected = append(selected, val) + } + return true + }) + + return &Value{data: selected} + +} + +// GroupUint32 uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]uint32. +func (v *Value) GroupUint32(grouper func(int, uint32) string) *Value { + + groups := make(map[string][]uint32) + + v.EachUint32(func(index int, val uint32) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]uint32, 0) + } + groups[group] = append(groups[group], val) + return true + }) + + return &Value{data: groups} + +} + +// ReplaceUint32 uses the specified function to replace each uint32s +// by iterating each item. The data in the returned result will be a +// []uint32 containing the replaced items. +func (v *Value) ReplaceUint32(replacer func(int, uint32) uint32) *Value { + + arr := v.MustUint32Slice() + replaced := make([]uint32, len(arr)) + + v.EachUint32(func(index int, val uint32) bool { + replaced[index] = replacer(index, val) + return true + }) + + return &Value{data: replaced} + +} + +// CollectUint32 uses the specified collector function to collect a value +// for each of the uint32s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectUint32(collector func(int, uint32) interface{}) *Value { + + arr := v.MustUint32Slice() + collected := make([]interface{}, len(arr)) + + v.EachUint32(func(index int, val uint32) bool { + collected[index] = collector(index, val) + return true + }) + + return &Value{data: collected} +} + +/* + Uint64 (uint64 and []uint64) + -------------------------------------------------- +*/ + +// Uint64 gets the value as a uint64, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Uint64(optionalDefault ...uint64) uint64 { + if s, ok := v.data.(uint64); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustUint64 gets the value as a uint64. +// +// Panics if the object is not a uint64. +func (v *Value) MustUint64() uint64 { + return v.data.(uint64) +} + +// Uint64Slice gets the value as a []uint64, returns the optionalDefault +// value or nil if the value is not a []uint64. +func (v *Value) Uint64Slice(optionalDefault ...[]uint64) []uint64 { + if s, ok := v.data.([]uint64); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustUint64Slice gets the value as a []uint64. +// +// Panics if the object is not a []uint64. +func (v *Value) MustUint64Slice() []uint64 { + return v.data.([]uint64) +} + +// IsUint64 gets whether the object contained is a uint64 or not. +func (v *Value) IsUint64() bool { + _, ok := v.data.(uint64) + return ok +} + +// IsUint64Slice gets whether the object contained is a []uint64 or not. +func (v *Value) IsUint64Slice() bool { + _, ok := v.data.([]uint64) + return ok +} + +// EachUint64 calls the specified callback for each object +// in the []uint64. +// +// Panics if the object is the wrong type. +func (v *Value) EachUint64(callback func(int, uint64) bool) *Value { + + for index, val := range v.MustUint64Slice() { + carryon := callback(index, val) + if carryon == false { + break + } + } + + return v + +} + +// WhereUint64 uses the specified decider function to select items +// from the []uint64. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereUint64(decider func(int, uint64) bool) *Value { + + var selected []uint64 + + v.EachUint64(func(index int, val uint64) bool { + shouldSelect := decider(index, val) + if shouldSelect == false { + selected = append(selected, val) + } + return true + }) + + return &Value{data: selected} + +} + +// GroupUint64 uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]uint64. +func (v *Value) GroupUint64(grouper func(int, uint64) string) *Value { + + groups := make(map[string][]uint64) + + v.EachUint64(func(index int, val uint64) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]uint64, 0) + } + groups[group] = append(groups[group], val) + return true + }) + + return &Value{data: groups} + +} + +// ReplaceUint64 uses the specified function to replace each uint64s +// by iterating each item. The data in the returned result will be a +// []uint64 containing the replaced items. +func (v *Value) ReplaceUint64(replacer func(int, uint64) uint64) *Value { + + arr := v.MustUint64Slice() + replaced := make([]uint64, len(arr)) + + v.EachUint64(func(index int, val uint64) bool { + replaced[index] = replacer(index, val) + return true + }) + + return &Value{data: replaced} + +} + +// CollectUint64 uses the specified collector function to collect a value +// for each of the uint64s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectUint64(collector func(int, uint64) interface{}) *Value { + + arr := v.MustUint64Slice() + collected := make([]interface{}, len(arr)) + + v.EachUint64(func(index int, val uint64) bool { + collected[index] = collector(index, val) + return true + }) + + return &Value{data: collected} +} + +/* + Uintptr (uintptr and []uintptr) + -------------------------------------------------- +*/ + +// Uintptr gets the value as a uintptr, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Uintptr(optionalDefault ...uintptr) uintptr { + if s, ok := v.data.(uintptr); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustUintptr gets the value as a uintptr. +// +// Panics if the object is not a uintptr. +func (v *Value) MustUintptr() uintptr { + return v.data.(uintptr) +} + +// UintptrSlice gets the value as a []uintptr, returns the optionalDefault +// value or nil if the value is not a []uintptr. +func (v *Value) UintptrSlice(optionalDefault ...[]uintptr) []uintptr { + if s, ok := v.data.([]uintptr); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustUintptrSlice gets the value as a []uintptr. +// +// Panics if the object is not a []uintptr. +func (v *Value) MustUintptrSlice() []uintptr { + return v.data.([]uintptr) +} + +// IsUintptr gets whether the object contained is a uintptr or not. +func (v *Value) IsUintptr() bool { + _, ok := v.data.(uintptr) + return ok +} + +// IsUintptrSlice gets whether the object contained is a []uintptr or not. +func (v *Value) IsUintptrSlice() bool { + _, ok := v.data.([]uintptr) + return ok +} + +// EachUintptr calls the specified callback for each object +// in the []uintptr. +// +// Panics if the object is the wrong type. +func (v *Value) EachUintptr(callback func(int, uintptr) bool) *Value { + + for index, val := range v.MustUintptrSlice() { + carryon := callback(index, val) + if carryon == false { + break + } + } + + return v + +} + +// WhereUintptr uses the specified decider function to select items +// from the []uintptr. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereUintptr(decider func(int, uintptr) bool) *Value { + + var selected []uintptr + + v.EachUintptr(func(index int, val uintptr) bool { + shouldSelect := decider(index, val) + if shouldSelect == false { + selected = append(selected, val) + } + return true + }) + + return &Value{data: selected} + +} + +// GroupUintptr uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]uintptr. +func (v *Value) GroupUintptr(grouper func(int, uintptr) string) *Value { + + groups := make(map[string][]uintptr) + + v.EachUintptr(func(index int, val uintptr) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]uintptr, 0) + } + groups[group] = append(groups[group], val) + return true + }) + + return &Value{data: groups} + +} + +// ReplaceUintptr uses the specified function to replace each uintptrs +// by iterating each item. The data in the returned result will be a +// []uintptr containing the replaced items. +func (v *Value) ReplaceUintptr(replacer func(int, uintptr) uintptr) *Value { + + arr := v.MustUintptrSlice() + replaced := make([]uintptr, len(arr)) + + v.EachUintptr(func(index int, val uintptr) bool { + replaced[index] = replacer(index, val) + return true + }) + + return &Value{data: replaced} + +} + +// CollectUintptr uses the specified collector function to collect a value +// for each of the uintptrs in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectUintptr(collector func(int, uintptr) interface{}) *Value { + + arr := v.MustUintptrSlice() + collected := make([]interface{}, len(arr)) + + v.EachUintptr(func(index int, val uintptr) bool { + collected[index] = collector(index, val) + return true + }) + + return &Value{data: collected} +} + +/* + Float32 (float32 and []float32) + -------------------------------------------------- +*/ + +// Float32 gets the value as a float32, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Float32(optionalDefault ...float32) float32 { + if s, ok := v.data.(float32); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustFloat32 gets the value as a float32. +// +// Panics if the object is not a float32. +func (v *Value) MustFloat32() float32 { + return v.data.(float32) +} + +// Float32Slice gets the value as a []float32, returns the optionalDefault +// value or nil if the value is not a []float32. +func (v *Value) Float32Slice(optionalDefault ...[]float32) []float32 { + if s, ok := v.data.([]float32); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustFloat32Slice gets the value as a []float32. +// +// Panics if the object is not a []float32. +func (v *Value) MustFloat32Slice() []float32 { + return v.data.([]float32) +} + +// IsFloat32 gets whether the object contained is a float32 or not. +func (v *Value) IsFloat32() bool { + _, ok := v.data.(float32) + return ok +} + +// IsFloat32Slice gets whether the object contained is a []float32 or not. +func (v *Value) IsFloat32Slice() bool { + _, ok := v.data.([]float32) + return ok +} + +// EachFloat32 calls the specified callback for each object +// in the []float32. +// +// Panics if the object is the wrong type. +func (v *Value) EachFloat32(callback func(int, float32) bool) *Value { + + for index, val := range v.MustFloat32Slice() { + carryon := callback(index, val) + if carryon == false { + break + } + } + + return v + +} + +// WhereFloat32 uses the specified decider function to select items +// from the []float32. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereFloat32(decider func(int, float32) bool) *Value { + + var selected []float32 + + v.EachFloat32(func(index int, val float32) bool { + shouldSelect := decider(index, val) + if shouldSelect == false { + selected = append(selected, val) + } + return true + }) + + return &Value{data: selected} + +} + +// GroupFloat32 uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]float32. +func (v *Value) GroupFloat32(grouper func(int, float32) string) *Value { + + groups := make(map[string][]float32) + + v.EachFloat32(func(index int, val float32) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]float32, 0) + } + groups[group] = append(groups[group], val) + return true + }) + + return &Value{data: groups} + +} + +// ReplaceFloat32 uses the specified function to replace each float32s +// by iterating each item. The data in the returned result will be a +// []float32 containing the replaced items. +func (v *Value) ReplaceFloat32(replacer func(int, float32) float32) *Value { + + arr := v.MustFloat32Slice() + replaced := make([]float32, len(arr)) + + v.EachFloat32(func(index int, val float32) bool { + replaced[index] = replacer(index, val) + return true + }) + + return &Value{data: replaced} + +} + +// CollectFloat32 uses the specified collector function to collect a value +// for each of the float32s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectFloat32(collector func(int, float32) interface{}) *Value { + + arr := v.MustFloat32Slice() + collected := make([]interface{}, len(arr)) + + v.EachFloat32(func(index int, val float32) bool { + collected[index] = collector(index, val) + return true + }) + + return &Value{data: collected} +} + +/* + Float64 (float64 and []float64) + -------------------------------------------------- +*/ + +// Float64 gets the value as a float64, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Float64(optionalDefault ...float64) float64 { + if s, ok := v.data.(float64); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustFloat64 gets the value as a float64. +// +// Panics if the object is not a float64. +func (v *Value) MustFloat64() float64 { + return v.data.(float64) +} + +// Float64Slice gets the value as a []float64, returns the optionalDefault +// value or nil if the value is not a []float64. +func (v *Value) Float64Slice(optionalDefault ...[]float64) []float64 { + if s, ok := v.data.([]float64); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustFloat64Slice gets the value as a []float64. +// +// Panics if the object is not a []float64. +func (v *Value) MustFloat64Slice() []float64 { + return v.data.([]float64) +} + +// IsFloat64 gets whether the object contained is a float64 or not. +func (v *Value) IsFloat64() bool { + _, ok := v.data.(float64) + return ok +} + +// IsFloat64Slice gets whether the object contained is a []float64 or not. +func (v *Value) IsFloat64Slice() bool { + _, ok := v.data.([]float64) + return ok +} + +// EachFloat64 calls the specified callback for each object +// in the []float64. +// +// Panics if the object is the wrong type. +func (v *Value) EachFloat64(callback func(int, float64) bool) *Value { + + for index, val := range v.MustFloat64Slice() { + carryon := callback(index, val) + if carryon == false { + break + } + } + + return v + +} + +// WhereFloat64 uses the specified decider function to select items +// from the []float64. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereFloat64(decider func(int, float64) bool) *Value { + + var selected []float64 + + v.EachFloat64(func(index int, val float64) bool { + shouldSelect := decider(index, val) + if shouldSelect == false { + selected = append(selected, val) + } + return true + }) + + return &Value{data: selected} + +} + +// GroupFloat64 uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]float64. +func (v *Value) GroupFloat64(grouper func(int, float64) string) *Value { + + groups := make(map[string][]float64) + + v.EachFloat64(func(index int, val float64) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]float64, 0) + } + groups[group] = append(groups[group], val) + return true + }) + + return &Value{data: groups} + +} + +// ReplaceFloat64 uses the specified function to replace each float64s +// by iterating each item. The data in the returned result will be a +// []float64 containing the replaced items. +func (v *Value) ReplaceFloat64(replacer func(int, float64) float64) *Value { + + arr := v.MustFloat64Slice() + replaced := make([]float64, len(arr)) + + v.EachFloat64(func(index int, val float64) bool { + replaced[index] = replacer(index, val) + return true + }) + + return &Value{data: replaced} + +} + +// CollectFloat64 uses the specified collector function to collect a value +// for each of the float64s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectFloat64(collector func(int, float64) interface{}) *Value { + + arr := v.MustFloat64Slice() + collected := make([]interface{}, len(arr)) + + v.EachFloat64(func(index int, val float64) bool { + collected[index] = collector(index, val) + return true + }) + + return &Value{data: collected} +} + +/* + Complex64 (complex64 and []complex64) + -------------------------------------------------- +*/ + +// Complex64 gets the value as a complex64, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Complex64(optionalDefault ...complex64) complex64 { + if s, ok := v.data.(complex64); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustComplex64 gets the value as a complex64. +// +// Panics if the object is not a complex64. +func (v *Value) MustComplex64() complex64 { + return v.data.(complex64) +} + +// Complex64Slice gets the value as a []complex64, returns the optionalDefault +// value or nil if the value is not a []complex64. +func (v *Value) Complex64Slice(optionalDefault ...[]complex64) []complex64 { + if s, ok := v.data.([]complex64); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustComplex64Slice gets the value as a []complex64. +// +// Panics if the object is not a []complex64. +func (v *Value) MustComplex64Slice() []complex64 { + return v.data.([]complex64) +} + +// IsComplex64 gets whether the object contained is a complex64 or not. +func (v *Value) IsComplex64() bool { + _, ok := v.data.(complex64) + return ok +} + +// IsComplex64Slice gets whether the object contained is a []complex64 or not. +func (v *Value) IsComplex64Slice() bool { + _, ok := v.data.([]complex64) + return ok +} + +// EachComplex64 calls the specified callback for each object +// in the []complex64. +// +// Panics if the object is the wrong type. +func (v *Value) EachComplex64(callback func(int, complex64) bool) *Value { + + for index, val := range v.MustComplex64Slice() { + carryon := callback(index, val) + if carryon == false { + break + } + } + + return v + +} + +// WhereComplex64 uses the specified decider function to select items +// from the []complex64. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereComplex64(decider func(int, complex64) bool) *Value { + + var selected []complex64 + + v.EachComplex64(func(index int, val complex64) bool { + shouldSelect := decider(index, val) + if shouldSelect == false { + selected = append(selected, val) + } + return true + }) + + return &Value{data: selected} + +} + +// GroupComplex64 uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]complex64. +func (v *Value) GroupComplex64(grouper func(int, complex64) string) *Value { + + groups := make(map[string][]complex64) + + v.EachComplex64(func(index int, val complex64) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]complex64, 0) + } + groups[group] = append(groups[group], val) + return true + }) + + return &Value{data: groups} + +} + +// ReplaceComplex64 uses the specified function to replace each complex64s +// by iterating each item. The data in the returned result will be a +// []complex64 containing the replaced items. +func (v *Value) ReplaceComplex64(replacer func(int, complex64) complex64) *Value { + + arr := v.MustComplex64Slice() + replaced := make([]complex64, len(arr)) + + v.EachComplex64(func(index int, val complex64) bool { + replaced[index] = replacer(index, val) + return true + }) + + return &Value{data: replaced} + +} + +// CollectComplex64 uses the specified collector function to collect a value +// for each of the complex64s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectComplex64(collector func(int, complex64) interface{}) *Value { + + arr := v.MustComplex64Slice() + collected := make([]interface{}, len(arr)) + + v.EachComplex64(func(index int, val complex64) bool { + collected[index] = collector(index, val) + return true + }) + + return &Value{data: collected} +} + +/* + Complex128 (complex128 and []complex128) + -------------------------------------------------- +*/ + +// Complex128 gets the value as a complex128, returns the optionalDefault +// value or a system default object if the value is the wrong type. +func (v *Value) Complex128(optionalDefault ...complex128) complex128 { + if s, ok := v.data.(complex128); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return 0 +} + +// MustComplex128 gets the value as a complex128. +// +// Panics if the object is not a complex128. +func (v *Value) MustComplex128() complex128 { + return v.data.(complex128) +} + +// Complex128Slice gets the value as a []complex128, returns the optionalDefault +// value or nil if the value is not a []complex128. +func (v *Value) Complex128Slice(optionalDefault ...[]complex128) []complex128 { + if s, ok := v.data.([]complex128); ok { + return s + } + if len(optionalDefault) == 1 { + return optionalDefault[0] + } + return nil +} + +// MustComplex128Slice gets the value as a []complex128. +// +// Panics if the object is not a []complex128. +func (v *Value) MustComplex128Slice() []complex128 { + return v.data.([]complex128) +} + +// IsComplex128 gets whether the object contained is a complex128 or not. +func (v *Value) IsComplex128() bool { + _, ok := v.data.(complex128) + return ok +} + +// IsComplex128Slice gets whether the object contained is a []complex128 or not. +func (v *Value) IsComplex128Slice() bool { + _, ok := v.data.([]complex128) + return ok +} + +// EachComplex128 calls the specified callback for each object +// in the []complex128. +// +// Panics if the object is the wrong type. +func (v *Value) EachComplex128(callback func(int, complex128) bool) *Value { + + for index, val := range v.MustComplex128Slice() { + carryon := callback(index, val) + if carryon == false { + break + } + } + + return v + +} + +// WhereComplex128 uses the specified decider function to select items +// from the []complex128. The object contained in the result will contain +// only the selected items. +func (v *Value) WhereComplex128(decider func(int, complex128) bool) *Value { + + var selected []complex128 + + v.EachComplex128(func(index int, val complex128) bool { + shouldSelect := decider(index, val) + if shouldSelect == false { + selected = append(selected, val) + } + return true + }) + + return &Value{data: selected} + +} + +// GroupComplex128 uses the specified grouper function to group the items +// keyed by the return of the grouper. The object contained in the +// result will contain a map[string][]complex128. +func (v *Value) GroupComplex128(grouper func(int, complex128) string) *Value { + + groups := make(map[string][]complex128) + + v.EachComplex128(func(index int, val complex128) bool { + group := grouper(index, val) + if _, ok := groups[group]; !ok { + groups[group] = make([]complex128, 0) + } + groups[group] = append(groups[group], val) + return true + }) + + return &Value{data: groups} + +} + +// ReplaceComplex128 uses the specified function to replace each complex128s +// by iterating each item. The data in the returned result will be a +// []complex128 containing the replaced items. +func (v *Value) ReplaceComplex128(replacer func(int, complex128) complex128) *Value { + + arr := v.MustComplex128Slice() + replaced := make([]complex128, len(arr)) + + v.EachComplex128(func(index int, val complex128) bool { + replaced[index] = replacer(index, val) + return true + }) + + return &Value{data: replaced} + +} + +// CollectComplex128 uses the specified collector function to collect a value +// for each of the complex128s in the slice. The data returned will be a +// []interface{}. +func (v *Value) CollectComplex128(collector func(int, complex128) interface{}) *Value { + + arr := v.MustComplex128Slice() + collected := make([]interface{}, len(arr)) + + v.EachComplex128(func(index int, val complex128) bool { + collected[index] = collector(index, val) + return true + }) + + return &Value{data: collected} +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/type_specific_codegen_test.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/type_specific_codegen_test.go new file mode 100644 index 000000000..f7a4fceea --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/type_specific_codegen_test.go @@ -0,0 +1,2867 @@ +package objx + +import ( + "fmt" + "github.com/stretchr/testify/assert" + "testing" +) + +// ************************************************************ +// TESTS +// ************************************************************ + +func TestInter(t *testing.T) { + + val := interface{}("something") + m := map[string]interface{}{"value": val, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Inter()) + assert.Equal(t, val, New(m).Get("value").MustInter()) + assert.Equal(t, interface{}(nil), New(m).Get("nothing").Inter()) + assert.Equal(t, val, New(m).Get("nothing").Inter("something")) + + assert.Panics(t, func() { + New(m).Get("age").MustInter() + }) + +} + +func TestInterSlice(t *testing.T) { + + val := interface{}("something") + m := map[string]interface{}{"value": []interface{}{val}, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").InterSlice()[0]) + assert.Equal(t, val, New(m).Get("value").MustInterSlice()[0]) + assert.Equal(t, []interface{}(nil), New(m).Get("nothing").InterSlice()) + assert.Equal(t, val, New(m).Get("nothing").InterSlice([]interface{}{interface{}("something")})[0]) + + assert.Panics(t, func() { + New(m).Get("nothing").MustInterSlice() + }) + +} + +func TestIsInter(t *testing.T) { + + var v *Value + + v = &Value{data: interface{}("something")} + assert.True(t, v.IsInter()) + + v = &Value{data: []interface{}{interface{}("something")}} + assert.True(t, v.IsInterSlice()) + +} + +func TestEachInter(t *testing.T) { + + v := &Value{data: []interface{}{interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something")}} + count := 0 + replacedVals := make([]interface{}, 0) + assert.Equal(t, v, v.EachInter(func(i int, val interface{}) bool { + + count++ + replacedVals = append(replacedVals, val) + + // abort early + if i == 2 { + return false + } + + return true + + })) + + assert.Equal(t, count, 3) + assert.Equal(t, replacedVals[0], v.MustInterSlice()[0]) + assert.Equal(t, replacedVals[1], v.MustInterSlice()[1]) + assert.Equal(t, replacedVals[2], v.MustInterSlice()[2]) + +} + +func TestWhereInter(t *testing.T) { + + v := &Value{data: []interface{}{interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something")}} + + selected := v.WhereInter(func(i int, val interface{}) bool { + return i%2 == 0 + }).MustInterSlice() + + assert.Equal(t, 3, len(selected)) + +} + +func TestGroupInter(t *testing.T) { + + v := &Value{data: []interface{}{interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something")}} + + grouped := v.GroupInter(func(i int, val interface{}) string { + return fmt.Sprintf("%v", i%2 == 0) + }).data.(map[string][]interface{}) + + assert.Equal(t, 2, len(grouped)) + assert.Equal(t, 3, len(grouped["true"])) + assert.Equal(t, 3, len(grouped["false"])) + +} + +func TestReplaceInter(t *testing.T) { + + v := &Value{data: []interface{}{interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something")}} + + rawArr := v.MustInterSlice() + + replaced := v.ReplaceInter(func(index int, val interface{}) interface{} { + if index < len(rawArr)-1 { + return rawArr[index+1] + } + return rawArr[0] + }) + + replacedArr := replaced.MustInterSlice() + if assert.Equal(t, 6, len(replacedArr)) { + assert.Equal(t, replacedArr[0], rawArr[1]) + assert.Equal(t, replacedArr[1], rawArr[2]) + assert.Equal(t, replacedArr[2], rawArr[3]) + assert.Equal(t, replacedArr[3], rawArr[4]) + assert.Equal(t, replacedArr[4], rawArr[5]) + assert.Equal(t, replacedArr[5], rawArr[0]) + } + +} + +func TestCollectInter(t *testing.T) { + + v := &Value{data: []interface{}{interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something"), interface{}("something")}} + + collected := v.CollectInter(func(index int, val interface{}) interface{} { + return index + }) + + collectedArr := collected.MustInterSlice() + if assert.Equal(t, 6, len(collectedArr)) { + assert.Equal(t, collectedArr[0], 0) + assert.Equal(t, collectedArr[1], 1) + assert.Equal(t, collectedArr[2], 2) + assert.Equal(t, collectedArr[3], 3) + assert.Equal(t, collectedArr[4], 4) + assert.Equal(t, collectedArr[5], 5) + } + +} + +// ************************************************************ +// TESTS +// ************************************************************ + +func TestMSI(t *testing.T) { + + val := map[string]interface{}(map[string]interface{}{"name": "Tyler"}) + m := map[string]interface{}{"value": val, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").MSI()) + assert.Equal(t, val, New(m).Get("value").MustMSI()) + assert.Equal(t, map[string]interface{}(nil), New(m).Get("nothing").MSI()) + assert.Equal(t, val, New(m).Get("nothing").MSI(map[string]interface{}{"name": "Tyler"})) + + assert.Panics(t, func() { + New(m).Get("age").MustMSI() + }) + +} + +func TestMSISlice(t *testing.T) { + + val := map[string]interface{}(map[string]interface{}{"name": "Tyler"}) + m := map[string]interface{}{"value": []map[string]interface{}{val}, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").MSISlice()[0]) + assert.Equal(t, val, New(m).Get("value").MustMSISlice()[0]) + assert.Equal(t, []map[string]interface{}(nil), New(m).Get("nothing").MSISlice()) + assert.Equal(t, val, New(m).Get("nothing").MSISlice([]map[string]interface{}{map[string]interface{}(map[string]interface{}{"name": "Tyler"})})[0]) + + assert.Panics(t, func() { + New(m).Get("nothing").MustMSISlice() + }) + +} + +func TestIsMSI(t *testing.T) { + + var v *Value + + v = &Value{data: map[string]interface{}(map[string]interface{}{"name": "Tyler"})} + assert.True(t, v.IsMSI()) + + v = &Value{data: []map[string]interface{}{map[string]interface{}(map[string]interface{}{"name": "Tyler"})}} + assert.True(t, v.IsMSISlice()) + +} + +func TestEachMSI(t *testing.T) { + + v := &Value{data: []map[string]interface{}{map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"})}} + count := 0 + replacedVals := make([]map[string]interface{}, 0) + assert.Equal(t, v, v.EachMSI(func(i int, val map[string]interface{}) bool { + + count++ + replacedVals = append(replacedVals, val) + + // abort early + if i == 2 { + return false + } + + return true + + })) + + assert.Equal(t, count, 3) + assert.Equal(t, replacedVals[0], v.MustMSISlice()[0]) + assert.Equal(t, replacedVals[1], v.MustMSISlice()[1]) + assert.Equal(t, replacedVals[2], v.MustMSISlice()[2]) + +} + +func TestWhereMSI(t *testing.T) { + + v := &Value{data: []map[string]interface{}{map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"})}} + + selected := v.WhereMSI(func(i int, val map[string]interface{}) bool { + return i%2 == 0 + }).MustMSISlice() + + assert.Equal(t, 3, len(selected)) + +} + +func TestGroupMSI(t *testing.T) { + + v := &Value{data: []map[string]interface{}{map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"})}} + + grouped := v.GroupMSI(func(i int, val map[string]interface{}) string { + return fmt.Sprintf("%v", i%2 == 0) + }).data.(map[string][]map[string]interface{}) + + assert.Equal(t, 2, len(grouped)) + assert.Equal(t, 3, len(grouped["true"])) + assert.Equal(t, 3, len(grouped["false"])) + +} + +func TestReplaceMSI(t *testing.T) { + + v := &Value{data: []map[string]interface{}{map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"})}} + + rawArr := v.MustMSISlice() + + replaced := v.ReplaceMSI(func(index int, val map[string]interface{}) map[string]interface{} { + if index < len(rawArr)-1 { + return rawArr[index+1] + } + return rawArr[0] + }) + + replacedArr := replaced.MustMSISlice() + if assert.Equal(t, 6, len(replacedArr)) { + assert.Equal(t, replacedArr[0], rawArr[1]) + assert.Equal(t, replacedArr[1], rawArr[2]) + assert.Equal(t, replacedArr[2], rawArr[3]) + assert.Equal(t, replacedArr[3], rawArr[4]) + assert.Equal(t, replacedArr[4], rawArr[5]) + assert.Equal(t, replacedArr[5], rawArr[0]) + } + +} + +func TestCollectMSI(t *testing.T) { + + v := &Value{data: []map[string]interface{}{map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"}), map[string]interface{}(map[string]interface{}{"name": "Tyler"})}} + + collected := v.CollectMSI(func(index int, val map[string]interface{}) interface{} { + return index + }) + + collectedArr := collected.MustInterSlice() + if assert.Equal(t, 6, len(collectedArr)) { + assert.Equal(t, collectedArr[0], 0) + assert.Equal(t, collectedArr[1], 1) + assert.Equal(t, collectedArr[2], 2) + assert.Equal(t, collectedArr[3], 3) + assert.Equal(t, collectedArr[4], 4) + assert.Equal(t, collectedArr[5], 5) + } + +} + +// ************************************************************ +// TESTS +// ************************************************************ + +func TestObjxMap(t *testing.T) { + + val := (Map)(New(1)) + m := map[string]interface{}{"value": val, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").ObjxMap()) + assert.Equal(t, val, New(m).Get("value").MustObjxMap()) + assert.Equal(t, (Map)(New(nil)), New(m).Get("nothing").ObjxMap()) + assert.Equal(t, val, New(m).Get("nothing").ObjxMap(New(1))) + + assert.Panics(t, func() { + New(m).Get("age").MustObjxMap() + }) + +} + +func TestObjxMapSlice(t *testing.T) { + + val := (Map)(New(1)) + m := map[string]interface{}{"value": [](Map){val}, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").ObjxMapSlice()[0]) + assert.Equal(t, val, New(m).Get("value").MustObjxMapSlice()[0]) + assert.Equal(t, [](Map)(nil), New(m).Get("nothing").ObjxMapSlice()) + assert.Equal(t, val, New(m).Get("nothing").ObjxMapSlice([](Map){(Map)(New(1))})[0]) + + assert.Panics(t, func() { + New(m).Get("nothing").MustObjxMapSlice() + }) + +} + +func TestIsObjxMap(t *testing.T) { + + var v *Value + + v = &Value{data: (Map)(New(1))} + assert.True(t, v.IsObjxMap()) + + v = &Value{data: [](Map){(Map)(New(1))}} + assert.True(t, v.IsObjxMapSlice()) + +} + +func TestEachObjxMap(t *testing.T) { + + v := &Value{data: [](Map){(Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1))}} + count := 0 + replacedVals := make([](Map), 0) + assert.Equal(t, v, v.EachObjxMap(func(i int, val Map) bool { + + count++ + replacedVals = append(replacedVals, val) + + // abort early + if i == 2 { + return false + } + + return true + + })) + + assert.Equal(t, count, 3) + assert.Equal(t, replacedVals[0], v.MustObjxMapSlice()[0]) + assert.Equal(t, replacedVals[1], v.MustObjxMapSlice()[1]) + assert.Equal(t, replacedVals[2], v.MustObjxMapSlice()[2]) + +} + +func TestWhereObjxMap(t *testing.T) { + + v := &Value{data: [](Map){(Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1))}} + + selected := v.WhereObjxMap(func(i int, val Map) bool { + return i%2 == 0 + }).MustObjxMapSlice() + + assert.Equal(t, 3, len(selected)) + +} + +func TestGroupObjxMap(t *testing.T) { + + v := &Value{data: [](Map){(Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1))}} + + grouped := v.GroupObjxMap(func(i int, val Map) string { + return fmt.Sprintf("%v", i%2 == 0) + }).data.(map[string][](Map)) + + assert.Equal(t, 2, len(grouped)) + assert.Equal(t, 3, len(grouped["true"])) + assert.Equal(t, 3, len(grouped["false"])) + +} + +func TestReplaceObjxMap(t *testing.T) { + + v := &Value{data: [](Map){(Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1))}} + + rawArr := v.MustObjxMapSlice() + + replaced := v.ReplaceObjxMap(func(index int, val Map) Map { + if index < len(rawArr)-1 { + return rawArr[index+1] + } + return rawArr[0] + }) + + replacedArr := replaced.MustObjxMapSlice() + if assert.Equal(t, 6, len(replacedArr)) { + assert.Equal(t, replacedArr[0], rawArr[1]) + assert.Equal(t, replacedArr[1], rawArr[2]) + assert.Equal(t, replacedArr[2], rawArr[3]) + assert.Equal(t, replacedArr[3], rawArr[4]) + assert.Equal(t, replacedArr[4], rawArr[5]) + assert.Equal(t, replacedArr[5], rawArr[0]) + } + +} + +func TestCollectObjxMap(t *testing.T) { + + v := &Value{data: [](Map){(Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1)), (Map)(New(1))}} + + collected := v.CollectObjxMap(func(index int, val Map) interface{} { + return index + }) + + collectedArr := collected.MustInterSlice() + if assert.Equal(t, 6, len(collectedArr)) { + assert.Equal(t, collectedArr[0], 0) + assert.Equal(t, collectedArr[1], 1) + assert.Equal(t, collectedArr[2], 2) + assert.Equal(t, collectedArr[3], 3) + assert.Equal(t, collectedArr[4], 4) + assert.Equal(t, collectedArr[5], 5) + } + +} + +// ************************************************************ +// TESTS +// ************************************************************ + +func TestBool(t *testing.T) { + + val := bool(true) + m := map[string]interface{}{"value": val, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Bool()) + assert.Equal(t, val, New(m).Get("value").MustBool()) + assert.Equal(t, bool(false), New(m).Get("nothing").Bool()) + assert.Equal(t, val, New(m).Get("nothing").Bool(true)) + + assert.Panics(t, func() { + New(m).Get("age").MustBool() + }) + +} + +func TestBoolSlice(t *testing.T) { + + val := bool(true) + m := map[string]interface{}{"value": []bool{val}, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").BoolSlice()[0]) + assert.Equal(t, val, New(m).Get("value").MustBoolSlice()[0]) + assert.Equal(t, []bool(nil), New(m).Get("nothing").BoolSlice()) + assert.Equal(t, val, New(m).Get("nothing").BoolSlice([]bool{bool(true)})[0]) + + assert.Panics(t, func() { + New(m).Get("nothing").MustBoolSlice() + }) + +} + +func TestIsBool(t *testing.T) { + + var v *Value + + v = &Value{data: bool(true)} + assert.True(t, v.IsBool()) + + v = &Value{data: []bool{bool(true)}} + assert.True(t, v.IsBoolSlice()) + +} + +func TestEachBool(t *testing.T) { + + v := &Value{data: []bool{bool(true), bool(true), bool(true), bool(true), bool(true)}} + count := 0 + replacedVals := make([]bool, 0) + assert.Equal(t, v, v.EachBool(func(i int, val bool) bool { + + count++ + replacedVals = append(replacedVals, val) + + // abort early + if i == 2 { + return false + } + + return true + + })) + + assert.Equal(t, count, 3) + assert.Equal(t, replacedVals[0], v.MustBoolSlice()[0]) + assert.Equal(t, replacedVals[1], v.MustBoolSlice()[1]) + assert.Equal(t, replacedVals[2], v.MustBoolSlice()[2]) + +} + +func TestWhereBool(t *testing.T) { + + v := &Value{data: []bool{bool(true), bool(true), bool(true), bool(true), bool(true), bool(true)}} + + selected := v.WhereBool(func(i int, val bool) bool { + return i%2 == 0 + }).MustBoolSlice() + + assert.Equal(t, 3, len(selected)) + +} + +func TestGroupBool(t *testing.T) { + + v := &Value{data: []bool{bool(true), bool(true), bool(true), bool(true), bool(true), bool(true)}} + + grouped := v.GroupBool(func(i int, val bool) string { + return fmt.Sprintf("%v", i%2 == 0) + }).data.(map[string][]bool) + + assert.Equal(t, 2, len(grouped)) + assert.Equal(t, 3, len(grouped["true"])) + assert.Equal(t, 3, len(grouped["false"])) + +} + +func TestReplaceBool(t *testing.T) { + + v := &Value{data: []bool{bool(true), bool(true), bool(true), bool(true), bool(true), bool(true)}} + + rawArr := v.MustBoolSlice() + + replaced := v.ReplaceBool(func(index int, val bool) bool { + if index < len(rawArr)-1 { + return rawArr[index+1] + } + return rawArr[0] + }) + + replacedArr := replaced.MustBoolSlice() + if assert.Equal(t, 6, len(replacedArr)) { + assert.Equal(t, replacedArr[0], rawArr[1]) + assert.Equal(t, replacedArr[1], rawArr[2]) + assert.Equal(t, replacedArr[2], rawArr[3]) + assert.Equal(t, replacedArr[3], rawArr[4]) + assert.Equal(t, replacedArr[4], rawArr[5]) + assert.Equal(t, replacedArr[5], rawArr[0]) + } + +} + +func TestCollectBool(t *testing.T) { + + v := &Value{data: []bool{bool(true), bool(true), bool(true), bool(true), bool(true), bool(true)}} + + collected := v.CollectBool(func(index int, val bool) interface{} { + return index + }) + + collectedArr := collected.MustInterSlice() + if assert.Equal(t, 6, len(collectedArr)) { + assert.Equal(t, collectedArr[0], 0) + assert.Equal(t, collectedArr[1], 1) + assert.Equal(t, collectedArr[2], 2) + assert.Equal(t, collectedArr[3], 3) + assert.Equal(t, collectedArr[4], 4) + assert.Equal(t, collectedArr[5], 5) + } + +} + +// ************************************************************ +// TESTS +// ************************************************************ + +func TestStr(t *testing.T) { + + val := string("hello") + m := map[string]interface{}{"value": val, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Str()) + assert.Equal(t, val, New(m).Get("value").MustStr()) + assert.Equal(t, string(""), New(m).Get("nothing").Str()) + assert.Equal(t, val, New(m).Get("nothing").Str("hello")) + + assert.Panics(t, func() { + New(m).Get("age").MustStr() + }) + +} + +func TestStrSlice(t *testing.T) { + + val := string("hello") + m := map[string]interface{}{"value": []string{val}, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").StrSlice()[0]) + assert.Equal(t, val, New(m).Get("value").MustStrSlice()[0]) + assert.Equal(t, []string(nil), New(m).Get("nothing").StrSlice()) + assert.Equal(t, val, New(m).Get("nothing").StrSlice([]string{string("hello")})[0]) + + assert.Panics(t, func() { + New(m).Get("nothing").MustStrSlice() + }) + +} + +func TestIsStr(t *testing.T) { + + var v *Value + + v = &Value{data: string("hello")} + assert.True(t, v.IsStr()) + + v = &Value{data: []string{string("hello")}} + assert.True(t, v.IsStrSlice()) + +} + +func TestEachStr(t *testing.T) { + + v := &Value{data: []string{string("hello"), string("hello"), string("hello"), string("hello"), string("hello")}} + count := 0 + replacedVals := make([]string, 0) + assert.Equal(t, v, v.EachStr(func(i int, val string) bool { + + count++ + replacedVals = append(replacedVals, val) + + // abort early + if i == 2 { + return false + } + + return true + + })) + + assert.Equal(t, count, 3) + assert.Equal(t, replacedVals[0], v.MustStrSlice()[0]) + assert.Equal(t, replacedVals[1], v.MustStrSlice()[1]) + assert.Equal(t, replacedVals[2], v.MustStrSlice()[2]) + +} + +func TestWhereStr(t *testing.T) { + + v := &Value{data: []string{string("hello"), string("hello"), string("hello"), string("hello"), string("hello"), string("hello")}} + + selected := v.WhereStr(func(i int, val string) bool { + return i%2 == 0 + }).MustStrSlice() + + assert.Equal(t, 3, len(selected)) + +} + +func TestGroupStr(t *testing.T) { + + v := &Value{data: []string{string("hello"), string("hello"), string("hello"), string("hello"), string("hello"), string("hello")}} + + grouped := v.GroupStr(func(i int, val string) string { + return fmt.Sprintf("%v", i%2 == 0) + }).data.(map[string][]string) + + assert.Equal(t, 2, len(grouped)) + assert.Equal(t, 3, len(grouped["true"])) + assert.Equal(t, 3, len(grouped["false"])) + +} + +func TestReplaceStr(t *testing.T) { + + v := &Value{data: []string{string("hello"), string("hello"), string("hello"), string("hello"), string("hello"), string("hello")}} + + rawArr := v.MustStrSlice() + + replaced := v.ReplaceStr(func(index int, val string) string { + if index < len(rawArr)-1 { + return rawArr[index+1] + } + return rawArr[0] + }) + + replacedArr := replaced.MustStrSlice() + if assert.Equal(t, 6, len(replacedArr)) { + assert.Equal(t, replacedArr[0], rawArr[1]) + assert.Equal(t, replacedArr[1], rawArr[2]) + assert.Equal(t, replacedArr[2], rawArr[3]) + assert.Equal(t, replacedArr[3], rawArr[4]) + assert.Equal(t, replacedArr[4], rawArr[5]) + assert.Equal(t, replacedArr[5], rawArr[0]) + } + +} + +func TestCollectStr(t *testing.T) { + + v := &Value{data: []string{string("hello"), string("hello"), string("hello"), string("hello"), string("hello"), string("hello")}} + + collected := v.CollectStr(func(index int, val string) interface{} { + return index + }) + + collectedArr := collected.MustInterSlice() + if assert.Equal(t, 6, len(collectedArr)) { + assert.Equal(t, collectedArr[0], 0) + assert.Equal(t, collectedArr[1], 1) + assert.Equal(t, collectedArr[2], 2) + assert.Equal(t, collectedArr[3], 3) + assert.Equal(t, collectedArr[4], 4) + assert.Equal(t, collectedArr[5], 5) + } + +} + +// ************************************************************ +// TESTS +// ************************************************************ + +func TestInt(t *testing.T) { + + val := int(1) + m := map[string]interface{}{"value": val, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Int()) + assert.Equal(t, val, New(m).Get("value").MustInt()) + assert.Equal(t, int(0), New(m).Get("nothing").Int()) + assert.Equal(t, val, New(m).Get("nothing").Int(1)) + + assert.Panics(t, func() { + New(m).Get("age").MustInt() + }) + +} + +func TestIntSlice(t *testing.T) { + + val := int(1) + m := map[string]interface{}{"value": []int{val}, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").IntSlice()[0]) + assert.Equal(t, val, New(m).Get("value").MustIntSlice()[0]) + assert.Equal(t, []int(nil), New(m).Get("nothing").IntSlice()) + assert.Equal(t, val, New(m).Get("nothing").IntSlice([]int{int(1)})[0]) + + assert.Panics(t, func() { + New(m).Get("nothing").MustIntSlice() + }) + +} + +func TestIsInt(t *testing.T) { + + var v *Value + + v = &Value{data: int(1)} + assert.True(t, v.IsInt()) + + v = &Value{data: []int{int(1)}} + assert.True(t, v.IsIntSlice()) + +} + +func TestEachInt(t *testing.T) { + + v := &Value{data: []int{int(1), int(1), int(1), int(1), int(1)}} + count := 0 + replacedVals := make([]int, 0) + assert.Equal(t, v, v.EachInt(func(i int, val int) bool { + + count++ + replacedVals = append(replacedVals, val) + + // abort early + if i == 2 { + return false + } + + return true + + })) + + assert.Equal(t, count, 3) + assert.Equal(t, replacedVals[0], v.MustIntSlice()[0]) + assert.Equal(t, replacedVals[1], v.MustIntSlice()[1]) + assert.Equal(t, replacedVals[2], v.MustIntSlice()[2]) + +} + +func TestWhereInt(t *testing.T) { + + v := &Value{data: []int{int(1), int(1), int(1), int(1), int(1), int(1)}} + + selected := v.WhereInt(func(i int, val int) bool { + return i%2 == 0 + }).MustIntSlice() + + assert.Equal(t, 3, len(selected)) + +} + +func TestGroupInt(t *testing.T) { + + v := &Value{data: []int{int(1), int(1), int(1), int(1), int(1), int(1)}} + + grouped := v.GroupInt(func(i int, val int) string { + return fmt.Sprintf("%v", i%2 == 0) + }).data.(map[string][]int) + + assert.Equal(t, 2, len(grouped)) + assert.Equal(t, 3, len(grouped["true"])) + assert.Equal(t, 3, len(grouped["false"])) + +} + +func TestReplaceInt(t *testing.T) { + + v := &Value{data: []int{int(1), int(1), int(1), int(1), int(1), int(1)}} + + rawArr := v.MustIntSlice() + + replaced := v.ReplaceInt(func(index int, val int) int { + if index < len(rawArr)-1 { + return rawArr[index+1] + } + return rawArr[0] + }) + + replacedArr := replaced.MustIntSlice() + if assert.Equal(t, 6, len(replacedArr)) { + assert.Equal(t, replacedArr[0], rawArr[1]) + assert.Equal(t, replacedArr[1], rawArr[2]) + assert.Equal(t, replacedArr[2], rawArr[3]) + assert.Equal(t, replacedArr[3], rawArr[4]) + assert.Equal(t, replacedArr[4], rawArr[5]) + assert.Equal(t, replacedArr[5], rawArr[0]) + } + +} + +func TestCollectInt(t *testing.T) { + + v := &Value{data: []int{int(1), int(1), int(1), int(1), int(1), int(1)}} + + collected := v.CollectInt(func(index int, val int) interface{} { + return index + }) + + collectedArr := collected.MustInterSlice() + if assert.Equal(t, 6, len(collectedArr)) { + assert.Equal(t, collectedArr[0], 0) + assert.Equal(t, collectedArr[1], 1) + assert.Equal(t, collectedArr[2], 2) + assert.Equal(t, collectedArr[3], 3) + assert.Equal(t, collectedArr[4], 4) + assert.Equal(t, collectedArr[5], 5) + } + +} + +// ************************************************************ +// TESTS +// ************************************************************ + +func TestInt8(t *testing.T) { + + val := int8(1) + m := map[string]interface{}{"value": val, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Int8()) + assert.Equal(t, val, New(m).Get("value").MustInt8()) + assert.Equal(t, int8(0), New(m).Get("nothing").Int8()) + assert.Equal(t, val, New(m).Get("nothing").Int8(1)) + + assert.Panics(t, func() { + New(m).Get("age").MustInt8() + }) + +} + +func TestInt8Slice(t *testing.T) { + + val := int8(1) + m := map[string]interface{}{"value": []int8{val}, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Int8Slice()[0]) + assert.Equal(t, val, New(m).Get("value").MustInt8Slice()[0]) + assert.Equal(t, []int8(nil), New(m).Get("nothing").Int8Slice()) + assert.Equal(t, val, New(m).Get("nothing").Int8Slice([]int8{int8(1)})[0]) + + assert.Panics(t, func() { + New(m).Get("nothing").MustInt8Slice() + }) + +} + +func TestIsInt8(t *testing.T) { + + var v *Value + + v = &Value{data: int8(1)} + assert.True(t, v.IsInt8()) + + v = &Value{data: []int8{int8(1)}} + assert.True(t, v.IsInt8Slice()) + +} + +func TestEachInt8(t *testing.T) { + + v := &Value{data: []int8{int8(1), int8(1), int8(1), int8(1), int8(1)}} + count := 0 + replacedVals := make([]int8, 0) + assert.Equal(t, v, v.EachInt8(func(i int, val int8) bool { + + count++ + replacedVals = append(replacedVals, val) + + // abort early + if i == 2 { + return false + } + + return true + + })) + + assert.Equal(t, count, 3) + assert.Equal(t, replacedVals[0], v.MustInt8Slice()[0]) + assert.Equal(t, replacedVals[1], v.MustInt8Slice()[1]) + assert.Equal(t, replacedVals[2], v.MustInt8Slice()[2]) + +} + +func TestWhereInt8(t *testing.T) { + + v := &Value{data: []int8{int8(1), int8(1), int8(1), int8(1), int8(1), int8(1)}} + + selected := v.WhereInt8(func(i int, val int8) bool { + return i%2 == 0 + }).MustInt8Slice() + + assert.Equal(t, 3, len(selected)) + +} + +func TestGroupInt8(t *testing.T) { + + v := &Value{data: []int8{int8(1), int8(1), int8(1), int8(1), int8(1), int8(1)}} + + grouped := v.GroupInt8(func(i int, val int8) string { + return fmt.Sprintf("%v", i%2 == 0) + }).data.(map[string][]int8) + + assert.Equal(t, 2, len(grouped)) + assert.Equal(t, 3, len(grouped["true"])) + assert.Equal(t, 3, len(grouped["false"])) + +} + +func TestReplaceInt8(t *testing.T) { + + v := &Value{data: []int8{int8(1), int8(1), int8(1), int8(1), int8(1), int8(1)}} + + rawArr := v.MustInt8Slice() + + replaced := v.ReplaceInt8(func(index int, val int8) int8 { + if index < len(rawArr)-1 { + return rawArr[index+1] + } + return rawArr[0] + }) + + replacedArr := replaced.MustInt8Slice() + if assert.Equal(t, 6, len(replacedArr)) { + assert.Equal(t, replacedArr[0], rawArr[1]) + assert.Equal(t, replacedArr[1], rawArr[2]) + assert.Equal(t, replacedArr[2], rawArr[3]) + assert.Equal(t, replacedArr[3], rawArr[4]) + assert.Equal(t, replacedArr[4], rawArr[5]) + assert.Equal(t, replacedArr[5], rawArr[0]) + } + +} + +func TestCollectInt8(t *testing.T) { + + v := &Value{data: []int8{int8(1), int8(1), int8(1), int8(1), int8(1), int8(1)}} + + collected := v.CollectInt8(func(index int, val int8) interface{} { + return index + }) + + collectedArr := collected.MustInterSlice() + if assert.Equal(t, 6, len(collectedArr)) { + assert.Equal(t, collectedArr[0], 0) + assert.Equal(t, collectedArr[1], 1) + assert.Equal(t, collectedArr[2], 2) + assert.Equal(t, collectedArr[3], 3) + assert.Equal(t, collectedArr[4], 4) + assert.Equal(t, collectedArr[5], 5) + } + +} + +// ************************************************************ +// TESTS +// ************************************************************ + +func TestInt16(t *testing.T) { + + val := int16(1) + m := map[string]interface{}{"value": val, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Int16()) + assert.Equal(t, val, New(m).Get("value").MustInt16()) + assert.Equal(t, int16(0), New(m).Get("nothing").Int16()) + assert.Equal(t, val, New(m).Get("nothing").Int16(1)) + + assert.Panics(t, func() { + New(m).Get("age").MustInt16() + }) + +} + +func TestInt16Slice(t *testing.T) { + + val := int16(1) + m := map[string]interface{}{"value": []int16{val}, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Int16Slice()[0]) + assert.Equal(t, val, New(m).Get("value").MustInt16Slice()[0]) + assert.Equal(t, []int16(nil), New(m).Get("nothing").Int16Slice()) + assert.Equal(t, val, New(m).Get("nothing").Int16Slice([]int16{int16(1)})[0]) + + assert.Panics(t, func() { + New(m).Get("nothing").MustInt16Slice() + }) + +} + +func TestIsInt16(t *testing.T) { + + var v *Value + + v = &Value{data: int16(1)} + assert.True(t, v.IsInt16()) + + v = &Value{data: []int16{int16(1)}} + assert.True(t, v.IsInt16Slice()) + +} + +func TestEachInt16(t *testing.T) { + + v := &Value{data: []int16{int16(1), int16(1), int16(1), int16(1), int16(1)}} + count := 0 + replacedVals := make([]int16, 0) + assert.Equal(t, v, v.EachInt16(func(i int, val int16) bool { + + count++ + replacedVals = append(replacedVals, val) + + // abort early + if i == 2 { + return false + } + + return true + + })) + + assert.Equal(t, count, 3) + assert.Equal(t, replacedVals[0], v.MustInt16Slice()[0]) + assert.Equal(t, replacedVals[1], v.MustInt16Slice()[1]) + assert.Equal(t, replacedVals[2], v.MustInt16Slice()[2]) + +} + +func TestWhereInt16(t *testing.T) { + + v := &Value{data: []int16{int16(1), int16(1), int16(1), int16(1), int16(1), int16(1)}} + + selected := v.WhereInt16(func(i int, val int16) bool { + return i%2 == 0 + }).MustInt16Slice() + + assert.Equal(t, 3, len(selected)) + +} + +func TestGroupInt16(t *testing.T) { + + v := &Value{data: []int16{int16(1), int16(1), int16(1), int16(1), int16(1), int16(1)}} + + grouped := v.GroupInt16(func(i int, val int16) string { + return fmt.Sprintf("%v", i%2 == 0) + }).data.(map[string][]int16) + + assert.Equal(t, 2, len(grouped)) + assert.Equal(t, 3, len(grouped["true"])) + assert.Equal(t, 3, len(grouped["false"])) + +} + +func TestReplaceInt16(t *testing.T) { + + v := &Value{data: []int16{int16(1), int16(1), int16(1), int16(1), int16(1), int16(1)}} + + rawArr := v.MustInt16Slice() + + replaced := v.ReplaceInt16(func(index int, val int16) int16 { + if index < len(rawArr)-1 { + return rawArr[index+1] + } + return rawArr[0] + }) + + replacedArr := replaced.MustInt16Slice() + if assert.Equal(t, 6, len(replacedArr)) { + assert.Equal(t, replacedArr[0], rawArr[1]) + assert.Equal(t, replacedArr[1], rawArr[2]) + assert.Equal(t, replacedArr[2], rawArr[3]) + assert.Equal(t, replacedArr[3], rawArr[4]) + assert.Equal(t, replacedArr[4], rawArr[5]) + assert.Equal(t, replacedArr[5], rawArr[0]) + } + +} + +func TestCollectInt16(t *testing.T) { + + v := &Value{data: []int16{int16(1), int16(1), int16(1), int16(1), int16(1), int16(1)}} + + collected := v.CollectInt16(func(index int, val int16) interface{} { + return index + }) + + collectedArr := collected.MustInterSlice() + if assert.Equal(t, 6, len(collectedArr)) { + assert.Equal(t, collectedArr[0], 0) + assert.Equal(t, collectedArr[1], 1) + assert.Equal(t, collectedArr[2], 2) + assert.Equal(t, collectedArr[3], 3) + assert.Equal(t, collectedArr[4], 4) + assert.Equal(t, collectedArr[5], 5) + } + +} + +// ************************************************************ +// TESTS +// ************************************************************ + +func TestInt32(t *testing.T) { + + val := int32(1) + m := map[string]interface{}{"value": val, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Int32()) + assert.Equal(t, val, New(m).Get("value").MustInt32()) + assert.Equal(t, int32(0), New(m).Get("nothing").Int32()) + assert.Equal(t, val, New(m).Get("nothing").Int32(1)) + + assert.Panics(t, func() { + New(m).Get("age").MustInt32() + }) + +} + +func TestInt32Slice(t *testing.T) { + + val := int32(1) + m := map[string]interface{}{"value": []int32{val}, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Int32Slice()[0]) + assert.Equal(t, val, New(m).Get("value").MustInt32Slice()[0]) + assert.Equal(t, []int32(nil), New(m).Get("nothing").Int32Slice()) + assert.Equal(t, val, New(m).Get("nothing").Int32Slice([]int32{int32(1)})[0]) + + assert.Panics(t, func() { + New(m).Get("nothing").MustInt32Slice() + }) + +} + +func TestIsInt32(t *testing.T) { + + var v *Value + + v = &Value{data: int32(1)} + assert.True(t, v.IsInt32()) + + v = &Value{data: []int32{int32(1)}} + assert.True(t, v.IsInt32Slice()) + +} + +func TestEachInt32(t *testing.T) { + + v := &Value{data: []int32{int32(1), int32(1), int32(1), int32(1), int32(1)}} + count := 0 + replacedVals := make([]int32, 0) + assert.Equal(t, v, v.EachInt32(func(i int, val int32) bool { + + count++ + replacedVals = append(replacedVals, val) + + // abort early + if i == 2 { + return false + } + + return true + + })) + + assert.Equal(t, count, 3) + assert.Equal(t, replacedVals[0], v.MustInt32Slice()[0]) + assert.Equal(t, replacedVals[1], v.MustInt32Slice()[1]) + assert.Equal(t, replacedVals[2], v.MustInt32Slice()[2]) + +} + +func TestWhereInt32(t *testing.T) { + + v := &Value{data: []int32{int32(1), int32(1), int32(1), int32(1), int32(1), int32(1)}} + + selected := v.WhereInt32(func(i int, val int32) bool { + return i%2 == 0 + }).MustInt32Slice() + + assert.Equal(t, 3, len(selected)) + +} + +func TestGroupInt32(t *testing.T) { + + v := &Value{data: []int32{int32(1), int32(1), int32(1), int32(1), int32(1), int32(1)}} + + grouped := v.GroupInt32(func(i int, val int32) string { + return fmt.Sprintf("%v", i%2 == 0) + }).data.(map[string][]int32) + + assert.Equal(t, 2, len(grouped)) + assert.Equal(t, 3, len(grouped["true"])) + assert.Equal(t, 3, len(grouped["false"])) + +} + +func TestReplaceInt32(t *testing.T) { + + v := &Value{data: []int32{int32(1), int32(1), int32(1), int32(1), int32(1), int32(1)}} + + rawArr := v.MustInt32Slice() + + replaced := v.ReplaceInt32(func(index int, val int32) int32 { + if index < len(rawArr)-1 { + return rawArr[index+1] + } + return rawArr[0] + }) + + replacedArr := replaced.MustInt32Slice() + if assert.Equal(t, 6, len(replacedArr)) { + assert.Equal(t, replacedArr[0], rawArr[1]) + assert.Equal(t, replacedArr[1], rawArr[2]) + assert.Equal(t, replacedArr[2], rawArr[3]) + assert.Equal(t, replacedArr[3], rawArr[4]) + assert.Equal(t, replacedArr[4], rawArr[5]) + assert.Equal(t, replacedArr[5], rawArr[0]) + } + +} + +func TestCollectInt32(t *testing.T) { + + v := &Value{data: []int32{int32(1), int32(1), int32(1), int32(1), int32(1), int32(1)}} + + collected := v.CollectInt32(func(index int, val int32) interface{} { + return index + }) + + collectedArr := collected.MustInterSlice() + if assert.Equal(t, 6, len(collectedArr)) { + assert.Equal(t, collectedArr[0], 0) + assert.Equal(t, collectedArr[1], 1) + assert.Equal(t, collectedArr[2], 2) + assert.Equal(t, collectedArr[3], 3) + assert.Equal(t, collectedArr[4], 4) + assert.Equal(t, collectedArr[5], 5) + } + +} + +// ************************************************************ +// TESTS +// ************************************************************ + +func TestInt64(t *testing.T) { + + val := int64(1) + m := map[string]interface{}{"value": val, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Int64()) + assert.Equal(t, val, New(m).Get("value").MustInt64()) + assert.Equal(t, int64(0), New(m).Get("nothing").Int64()) + assert.Equal(t, val, New(m).Get("nothing").Int64(1)) + + assert.Panics(t, func() { + New(m).Get("age").MustInt64() + }) + +} + +func TestInt64Slice(t *testing.T) { + + val := int64(1) + m := map[string]interface{}{"value": []int64{val}, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Int64Slice()[0]) + assert.Equal(t, val, New(m).Get("value").MustInt64Slice()[0]) + assert.Equal(t, []int64(nil), New(m).Get("nothing").Int64Slice()) + assert.Equal(t, val, New(m).Get("nothing").Int64Slice([]int64{int64(1)})[0]) + + assert.Panics(t, func() { + New(m).Get("nothing").MustInt64Slice() + }) + +} + +func TestIsInt64(t *testing.T) { + + var v *Value + + v = &Value{data: int64(1)} + assert.True(t, v.IsInt64()) + + v = &Value{data: []int64{int64(1)}} + assert.True(t, v.IsInt64Slice()) + +} + +func TestEachInt64(t *testing.T) { + + v := &Value{data: []int64{int64(1), int64(1), int64(1), int64(1), int64(1)}} + count := 0 + replacedVals := make([]int64, 0) + assert.Equal(t, v, v.EachInt64(func(i int, val int64) bool { + + count++ + replacedVals = append(replacedVals, val) + + // abort early + if i == 2 { + return false + } + + return true + + })) + + assert.Equal(t, count, 3) + assert.Equal(t, replacedVals[0], v.MustInt64Slice()[0]) + assert.Equal(t, replacedVals[1], v.MustInt64Slice()[1]) + assert.Equal(t, replacedVals[2], v.MustInt64Slice()[2]) + +} + +func TestWhereInt64(t *testing.T) { + + v := &Value{data: []int64{int64(1), int64(1), int64(1), int64(1), int64(1), int64(1)}} + + selected := v.WhereInt64(func(i int, val int64) bool { + return i%2 == 0 + }).MustInt64Slice() + + assert.Equal(t, 3, len(selected)) + +} + +func TestGroupInt64(t *testing.T) { + + v := &Value{data: []int64{int64(1), int64(1), int64(1), int64(1), int64(1), int64(1)}} + + grouped := v.GroupInt64(func(i int, val int64) string { + return fmt.Sprintf("%v", i%2 == 0) + }).data.(map[string][]int64) + + assert.Equal(t, 2, len(grouped)) + assert.Equal(t, 3, len(grouped["true"])) + assert.Equal(t, 3, len(grouped["false"])) + +} + +func TestReplaceInt64(t *testing.T) { + + v := &Value{data: []int64{int64(1), int64(1), int64(1), int64(1), int64(1), int64(1)}} + + rawArr := v.MustInt64Slice() + + replaced := v.ReplaceInt64(func(index int, val int64) int64 { + if index < len(rawArr)-1 { + return rawArr[index+1] + } + return rawArr[0] + }) + + replacedArr := replaced.MustInt64Slice() + if assert.Equal(t, 6, len(replacedArr)) { + assert.Equal(t, replacedArr[0], rawArr[1]) + assert.Equal(t, replacedArr[1], rawArr[2]) + assert.Equal(t, replacedArr[2], rawArr[3]) + assert.Equal(t, replacedArr[3], rawArr[4]) + assert.Equal(t, replacedArr[4], rawArr[5]) + assert.Equal(t, replacedArr[5], rawArr[0]) + } + +} + +func TestCollectInt64(t *testing.T) { + + v := &Value{data: []int64{int64(1), int64(1), int64(1), int64(1), int64(1), int64(1)}} + + collected := v.CollectInt64(func(index int, val int64) interface{} { + return index + }) + + collectedArr := collected.MustInterSlice() + if assert.Equal(t, 6, len(collectedArr)) { + assert.Equal(t, collectedArr[0], 0) + assert.Equal(t, collectedArr[1], 1) + assert.Equal(t, collectedArr[2], 2) + assert.Equal(t, collectedArr[3], 3) + assert.Equal(t, collectedArr[4], 4) + assert.Equal(t, collectedArr[5], 5) + } + +} + +// ************************************************************ +// TESTS +// ************************************************************ + +func TestUint(t *testing.T) { + + val := uint(1) + m := map[string]interface{}{"value": val, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Uint()) + assert.Equal(t, val, New(m).Get("value").MustUint()) + assert.Equal(t, uint(0), New(m).Get("nothing").Uint()) + assert.Equal(t, val, New(m).Get("nothing").Uint(1)) + + assert.Panics(t, func() { + New(m).Get("age").MustUint() + }) + +} + +func TestUintSlice(t *testing.T) { + + val := uint(1) + m := map[string]interface{}{"value": []uint{val}, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").UintSlice()[0]) + assert.Equal(t, val, New(m).Get("value").MustUintSlice()[0]) + assert.Equal(t, []uint(nil), New(m).Get("nothing").UintSlice()) + assert.Equal(t, val, New(m).Get("nothing").UintSlice([]uint{uint(1)})[0]) + + assert.Panics(t, func() { + New(m).Get("nothing").MustUintSlice() + }) + +} + +func TestIsUint(t *testing.T) { + + var v *Value + + v = &Value{data: uint(1)} + assert.True(t, v.IsUint()) + + v = &Value{data: []uint{uint(1)}} + assert.True(t, v.IsUintSlice()) + +} + +func TestEachUint(t *testing.T) { + + v := &Value{data: []uint{uint(1), uint(1), uint(1), uint(1), uint(1)}} + count := 0 + replacedVals := make([]uint, 0) + assert.Equal(t, v, v.EachUint(func(i int, val uint) bool { + + count++ + replacedVals = append(replacedVals, val) + + // abort early + if i == 2 { + return false + } + + return true + + })) + + assert.Equal(t, count, 3) + assert.Equal(t, replacedVals[0], v.MustUintSlice()[0]) + assert.Equal(t, replacedVals[1], v.MustUintSlice()[1]) + assert.Equal(t, replacedVals[2], v.MustUintSlice()[2]) + +} + +func TestWhereUint(t *testing.T) { + + v := &Value{data: []uint{uint(1), uint(1), uint(1), uint(1), uint(1), uint(1)}} + + selected := v.WhereUint(func(i int, val uint) bool { + return i%2 == 0 + }).MustUintSlice() + + assert.Equal(t, 3, len(selected)) + +} + +func TestGroupUint(t *testing.T) { + + v := &Value{data: []uint{uint(1), uint(1), uint(1), uint(1), uint(1), uint(1)}} + + grouped := v.GroupUint(func(i int, val uint) string { + return fmt.Sprintf("%v", i%2 == 0) + }).data.(map[string][]uint) + + assert.Equal(t, 2, len(grouped)) + assert.Equal(t, 3, len(grouped["true"])) + assert.Equal(t, 3, len(grouped["false"])) + +} + +func TestReplaceUint(t *testing.T) { + + v := &Value{data: []uint{uint(1), uint(1), uint(1), uint(1), uint(1), uint(1)}} + + rawArr := v.MustUintSlice() + + replaced := v.ReplaceUint(func(index int, val uint) uint { + if index < len(rawArr)-1 { + return rawArr[index+1] + } + return rawArr[0] + }) + + replacedArr := replaced.MustUintSlice() + if assert.Equal(t, 6, len(replacedArr)) { + assert.Equal(t, replacedArr[0], rawArr[1]) + assert.Equal(t, replacedArr[1], rawArr[2]) + assert.Equal(t, replacedArr[2], rawArr[3]) + assert.Equal(t, replacedArr[3], rawArr[4]) + assert.Equal(t, replacedArr[4], rawArr[5]) + assert.Equal(t, replacedArr[5], rawArr[0]) + } + +} + +func TestCollectUint(t *testing.T) { + + v := &Value{data: []uint{uint(1), uint(1), uint(1), uint(1), uint(1), uint(1)}} + + collected := v.CollectUint(func(index int, val uint) interface{} { + return index + }) + + collectedArr := collected.MustInterSlice() + if assert.Equal(t, 6, len(collectedArr)) { + assert.Equal(t, collectedArr[0], 0) + assert.Equal(t, collectedArr[1], 1) + assert.Equal(t, collectedArr[2], 2) + assert.Equal(t, collectedArr[3], 3) + assert.Equal(t, collectedArr[4], 4) + assert.Equal(t, collectedArr[5], 5) + } + +} + +// ************************************************************ +// TESTS +// ************************************************************ + +func TestUint8(t *testing.T) { + + val := uint8(1) + m := map[string]interface{}{"value": val, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Uint8()) + assert.Equal(t, val, New(m).Get("value").MustUint8()) + assert.Equal(t, uint8(0), New(m).Get("nothing").Uint8()) + assert.Equal(t, val, New(m).Get("nothing").Uint8(1)) + + assert.Panics(t, func() { + New(m).Get("age").MustUint8() + }) + +} + +func TestUint8Slice(t *testing.T) { + + val := uint8(1) + m := map[string]interface{}{"value": []uint8{val}, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Uint8Slice()[0]) + assert.Equal(t, val, New(m).Get("value").MustUint8Slice()[0]) + assert.Equal(t, []uint8(nil), New(m).Get("nothing").Uint8Slice()) + assert.Equal(t, val, New(m).Get("nothing").Uint8Slice([]uint8{uint8(1)})[0]) + + assert.Panics(t, func() { + New(m).Get("nothing").MustUint8Slice() + }) + +} + +func TestIsUint8(t *testing.T) { + + var v *Value + + v = &Value{data: uint8(1)} + assert.True(t, v.IsUint8()) + + v = &Value{data: []uint8{uint8(1)}} + assert.True(t, v.IsUint8Slice()) + +} + +func TestEachUint8(t *testing.T) { + + v := &Value{data: []uint8{uint8(1), uint8(1), uint8(1), uint8(1), uint8(1)}} + count := 0 + replacedVals := make([]uint8, 0) + assert.Equal(t, v, v.EachUint8(func(i int, val uint8) bool { + + count++ + replacedVals = append(replacedVals, val) + + // abort early + if i == 2 { + return false + } + + return true + + })) + + assert.Equal(t, count, 3) + assert.Equal(t, replacedVals[0], v.MustUint8Slice()[0]) + assert.Equal(t, replacedVals[1], v.MustUint8Slice()[1]) + assert.Equal(t, replacedVals[2], v.MustUint8Slice()[2]) + +} + +func TestWhereUint8(t *testing.T) { + + v := &Value{data: []uint8{uint8(1), uint8(1), uint8(1), uint8(1), uint8(1), uint8(1)}} + + selected := v.WhereUint8(func(i int, val uint8) bool { + return i%2 == 0 + }).MustUint8Slice() + + assert.Equal(t, 3, len(selected)) + +} + +func TestGroupUint8(t *testing.T) { + + v := &Value{data: []uint8{uint8(1), uint8(1), uint8(1), uint8(1), uint8(1), uint8(1)}} + + grouped := v.GroupUint8(func(i int, val uint8) string { + return fmt.Sprintf("%v", i%2 == 0) + }).data.(map[string][]uint8) + + assert.Equal(t, 2, len(grouped)) + assert.Equal(t, 3, len(grouped["true"])) + assert.Equal(t, 3, len(grouped["false"])) + +} + +func TestReplaceUint8(t *testing.T) { + + v := &Value{data: []uint8{uint8(1), uint8(1), uint8(1), uint8(1), uint8(1), uint8(1)}} + + rawArr := v.MustUint8Slice() + + replaced := v.ReplaceUint8(func(index int, val uint8) uint8 { + if index < len(rawArr)-1 { + return rawArr[index+1] + } + return rawArr[0] + }) + + replacedArr := replaced.MustUint8Slice() + if assert.Equal(t, 6, len(replacedArr)) { + assert.Equal(t, replacedArr[0], rawArr[1]) + assert.Equal(t, replacedArr[1], rawArr[2]) + assert.Equal(t, replacedArr[2], rawArr[3]) + assert.Equal(t, replacedArr[3], rawArr[4]) + assert.Equal(t, replacedArr[4], rawArr[5]) + assert.Equal(t, replacedArr[5], rawArr[0]) + } + +} + +func TestCollectUint8(t *testing.T) { + + v := &Value{data: []uint8{uint8(1), uint8(1), uint8(1), uint8(1), uint8(1), uint8(1)}} + + collected := v.CollectUint8(func(index int, val uint8) interface{} { + return index + }) + + collectedArr := collected.MustInterSlice() + if assert.Equal(t, 6, len(collectedArr)) { + assert.Equal(t, collectedArr[0], 0) + assert.Equal(t, collectedArr[1], 1) + assert.Equal(t, collectedArr[2], 2) + assert.Equal(t, collectedArr[3], 3) + assert.Equal(t, collectedArr[4], 4) + assert.Equal(t, collectedArr[5], 5) + } + +} + +// ************************************************************ +// TESTS +// ************************************************************ + +func TestUint16(t *testing.T) { + + val := uint16(1) + m := map[string]interface{}{"value": val, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Uint16()) + assert.Equal(t, val, New(m).Get("value").MustUint16()) + assert.Equal(t, uint16(0), New(m).Get("nothing").Uint16()) + assert.Equal(t, val, New(m).Get("nothing").Uint16(1)) + + assert.Panics(t, func() { + New(m).Get("age").MustUint16() + }) + +} + +func TestUint16Slice(t *testing.T) { + + val := uint16(1) + m := map[string]interface{}{"value": []uint16{val}, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Uint16Slice()[0]) + assert.Equal(t, val, New(m).Get("value").MustUint16Slice()[0]) + assert.Equal(t, []uint16(nil), New(m).Get("nothing").Uint16Slice()) + assert.Equal(t, val, New(m).Get("nothing").Uint16Slice([]uint16{uint16(1)})[0]) + + assert.Panics(t, func() { + New(m).Get("nothing").MustUint16Slice() + }) + +} + +func TestIsUint16(t *testing.T) { + + var v *Value + + v = &Value{data: uint16(1)} + assert.True(t, v.IsUint16()) + + v = &Value{data: []uint16{uint16(1)}} + assert.True(t, v.IsUint16Slice()) + +} + +func TestEachUint16(t *testing.T) { + + v := &Value{data: []uint16{uint16(1), uint16(1), uint16(1), uint16(1), uint16(1)}} + count := 0 + replacedVals := make([]uint16, 0) + assert.Equal(t, v, v.EachUint16(func(i int, val uint16) bool { + + count++ + replacedVals = append(replacedVals, val) + + // abort early + if i == 2 { + return false + } + + return true + + })) + + assert.Equal(t, count, 3) + assert.Equal(t, replacedVals[0], v.MustUint16Slice()[0]) + assert.Equal(t, replacedVals[1], v.MustUint16Slice()[1]) + assert.Equal(t, replacedVals[2], v.MustUint16Slice()[2]) + +} + +func TestWhereUint16(t *testing.T) { + + v := &Value{data: []uint16{uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1)}} + + selected := v.WhereUint16(func(i int, val uint16) bool { + return i%2 == 0 + }).MustUint16Slice() + + assert.Equal(t, 3, len(selected)) + +} + +func TestGroupUint16(t *testing.T) { + + v := &Value{data: []uint16{uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1)}} + + grouped := v.GroupUint16(func(i int, val uint16) string { + return fmt.Sprintf("%v", i%2 == 0) + }).data.(map[string][]uint16) + + assert.Equal(t, 2, len(grouped)) + assert.Equal(t, 3, len(grouped["true"])) + assert.Equal(t, 3, len(grouped["false"])) + +} + +func TestReplaceUint16(t *testing.T) { + + v := &Value{data: []uint16{uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1)}} + + rawArr := v.MustUint16Slice() + + replaced := v.ReplaceUint16(func(index int, val uint16) uint16 { + if index < len(rawArr)-1 { + return rawArr[index+1] + } + return rawArr[0] + }) + + replacedArr := replaced.MustUint16Slice() + if assert.Equal(t, 6, len(replacedArr)) { + assert.Equal(t, replacedArr[0], rawArr[1]) + assert.Equal(t, replacedArr[1], rawArr[2]) + assert.Equal(t, replacedArr[2], rawArr[3]) + assert.Equal(t, replacedArr[3], rawArr[4]) + assert.Equal(t, replacedArr[4], rawArr[5]) + assert.Equal(t, replacedArr[5], rawArr[0]) + } + +} + +func TestCollectUint16(t *testing.T) { + + v := &Value{data: []uint16{uint16(1), uint16(1), uint16(1), uint16(1), uint16(1), uint16(1)}} + + collected := v.CollectUint16(func(index int, val uint16) interface{} { + return index + }) + + collectedArr := collected.MustInterSlice() + if assert.Equal(t, 6, len(collectedArr)) { + assert.Equal(t, collectedArr[0], 0) + assert.Equal(t, collectedArr[1], 1) + assert.Equal(t, collectedArr[2], 2) + assert.Equal(t, collectedArr[3], 3) + assert.Equal(t, collectedArr[4], 4) + assert.Equal(t, collectedArr[5], 5) + } + +} + +// ************************************************************ +// TESTS +// ************************************************************ + +func TestUint32(t *testing.T) { + + val := uint32(1) + m := map[string]interface{}{"value": val, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Uint32()) + assert.Equal(t, val, New(m).Get("value").MustUint32()) + assert.Equal(t, uint32(0), New(m).Get("nothing").Uint32()) + assert.Equal(t, val, New(m).Get("nothing").Uint32(1)) + + assert.Panics(t, func() { + New(m).Get("age").MustUint32() + }) + +} + +func TestUint32Slice(t *testing.T) { + + val := uint32(1) + m := map[string]interface{}{"value": []uint32{val}, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Uint32Slice()[0]) + assert.Equal(t, val, New(m).Get("value").MustUint32Slice()[0]) + assert.Equal(t, []uint32(nil), New(m).Get("nothing").Uint32Slice()) + assert.Equal(t, val, New(m).Get("nothing").Uint32Slice([]uint32{uint32(1)})[0]) + + assert.Panics(t, func() { + New(m).Get("nothing").MustUint32Slice() + }) + +} + +func TestIsUint32(t *testing.T) { + + var v *Value + + v = &Value{data: uint32(1)} + assert.True(t, v.IsUint32()) + + v = &Value{data: []uint32{uint32(1)}} + assert.True(t, v.IsUint32Slice()) + +} + +func TestEachUint32(t *testing.T) { + + v := &Value{data: []uint32{uint32(1), uint32(1), uint32(1), uint32(1), uint32(1)}} + count := 0 + replacedVals := make([]uint32, 0) + assert.Equal(t, v, v.EachUint32(func(i int, val uint32) bool { + + count++ + replacedVals = append(replacedVals, val) + + // abort early + if i == 2 { + return false + } + + return true + + })) + + assert.Equal(t, count, 3) + assert.Equal(t, replacedVals[0], v.MustUint32Slice()[0]) + assert.Equal(t, replacedVals[1], v.MustUint32Slice()[1]) + assert.Equal(t, replacedVals[2], v.MustUint32Slice()[2]) + +} + +func TestWhereUint32(t *testing.T) { + + v := &Value{data: []uint32{uint32(1), uint32(1), uint32(1), uint32(1), uint32(1), uint32(1)}} + + selected := v.WhereUint32(func(i int, val uint32) bool { + return i%2 == 0 + }).MustUint32Slice() + + assert.Equal(t, 3, len(selected)) + +} + +func TestGroupUint32(t *testing.T) { + + v := &Value{data: []uint32{uint32(1), uint32(1), uint32(1), uint32(1), uint32(1), uint32(1)}} + + grouped := v.GroupUint32(func(i int, val uint32) string { + return fmt.Sprintf("%v", i%2 == 0) + }).data.(map[string][]uint32) + + assert.Equal(t, 2, len(grouped)) + assert.Equal(t, 3, len(grouped["true"])) + assert.Equal(t, 3, len(grouped["false"])) + +} + +func TestReplaceUint32(t *testing.T) { + + v := &Value{data: []uint32{uint32(1), uint32(1), uint32(1), uint32(1), uint32(1), uint32(1)}} + + rawArr := v.MustUint32Slice() + + replaced := v.ReplaceUint32(func(index int, val uint32) uint32 { + if index < len(rawArr)-1 { + return rawArr[index+1] + } + return rawArr[0] + }) + + replacedArr := replaced.MustUint32Slice() + if assert.Equal(t, 6, len(replacedArr)) { + assert.Equal(t, replacedArr[0], rawArr[1]) + assert.Equal(t, replacedArr[1], rawArr[2]) + assert.Equal(t, replacedArr[2], rawArr[3]) + assert.Equal(t, replacedArr[3], rawArr[4]) + assert.Equal(t, replacedArr[4], rawArr[5]) + assert.Equal(t, replacedArr[5], rawArr[0]) + } + +} + +func TestCollectUint32(t *testing.T) { + + v := &Value{data: []uint32{uint32(1), uint32(1), uint32(1), uint32(1), uint32(1), uint32(1)}} + + collected := v.CollectUint32(func(index int, val uint32) interface{} { + return index + }) + + collectedArr := collected.MustInterSlice() + if assert.Equal(t, 6, len(collectedArr)) { + assert.Equal(t, collectedArr[0], 0) + assert.Equal(t, collectedArr[1], 1) + assert.Equal(t, collectedArr[2], 2) + assert.Equal(t, collectedArr[3], 3) + assert.Equal(t, collectedArr[4], 4) + assert.Equal(t, collectedArr[5], 5) + } + +} + +// ************************************************************ +// TESTS +// ************************************************************ + +func TestUint64(t *testing.T) { + + val := uint64(1) + m := map[string]interface{}{"value": val, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Uint64()) + assert.Equal(t, val, New(m).Get("value").MustUint64()) + assert.Equal(t, uint64(0), New(m).Get("nothing").Uint64()) + assert.Equal(t, val, New(m).Get("nothing").Uint64(1)) + + assert.Panics(t, func() { + New(m).Get("age").MustUint64() + }) + +} + +func TestUint64Slice(t *testing.T) { + + val := uint64(1) + m := map[string]interface{}{"value": []uint64{val}, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Uint64Slice()[0]) + assert.Equal(t, val, New(m).Get("value").MustUint64Slice()[0]) + assert.Equal(t, []uint64(nil), New(m).Get("nothing").Uint64Slice()) + assert.Equal(t, val, New(m).Get("nothing").Uint64Slice([]uint64{uint64(1)})[0]) + + assert.Panics(t, func() { + New(m).Get("nothing").MustUint64Slice() + }) + +} + +func TestIsUint64(t *testing.T) { + + var v *Value + + v = &Value{data: uint64(1)} + assert.True(t, v.IsUint64()) + + v = &Value{data: []uint64{uint64(1)}} + assert.True(t, v.IsUint64Slice()) + +} + +func TestEachUint64(t *testing.T) { + + v := &Value{data: []uint64{uint64(1), uint64(1), uint64(1), uint64(1), uint64(1)}} + count := 0 + replacedVals := make([]uint64, 0) + assert.Equal(t, v, v.EachUint64(func(i int, val uint64) bool { + + count++ + replacedVals = append(replacedVals, val) + + // abort early + if i == 2 { + return false + } + + return true + + })) + + assert.Equal(t, count, 3) + assert.Equal(t, replacedVals[0], v.MustUint64Slice()[0]) + assert.Equal(t, replacedVals[1], v.MustUint64Slice()[1]) + assert.Equal(t, replacedVals[2], v.MustUint64Slice()[2]) + +} + +func TestWhereUint64(t *testing.T) { + + v := &Value{data: []uint64{uint64(1), uint64(1), uint64(1), uint64(1), uint64(1), uint64(1)}} + + selected := v.WhereUint64(func(i int, val uint64) bool { + return i%2 == 0 + }).MustUint64Slice() + + assert.Equal(t, 3, len(selected)) + +} + +func TestGroupUint64(t *testing.T) { + + v := &Value{data: []uint64{uint64(1), uint64(1), uint64(1), uint64(1), uint64(1), uint64(1)}} + + grouped := v.GroupUint64(func(i int, val uint64) string { + return fmt.Sprintf("%v", i%2 == 0) + }).data.(map[string][]uint64) + + assert.Equal(t, 2, len(grouped)) + assert.Equal(t, 3, len(grouped["true"])) + assert.Equal(t, 3, len(grouped["false"])) + +} + +func TestReplaceUint64(t *testing.T) { + + v := &Value{data: []uint64{uint64(1), uint64(1), uint64(1), uint64(1), uint64(1), uint64(1)}} + + rawArr := v.MustUint64Slice() + + replaced := v.ReplaceUint64(func(index int, val uint64) uint64 { + if index < len(rawArr)-1 { + return rawArr[index+1] + } + return rawArr[0] + }) + + replacedArr := replaced.MustUint64Slice() + if assert.Equal(t, 6, len(replacedArr)) { + assert.Equal(t, replacedArr[0], rawArr[1]) + assert.Equal(t, replacedArr[1], rawArr[2]) + assert.Equal(t, replacedArr[2], rawArr[3]) + assert.Equal(t, replacedArr[3], rawArr[4]) + assert.Equal(t, replacedArr[4], rawArr[5]) + assert.Equal(t, replacedArr[5], rawArr[0]) + } + +} + +func TestCollectUint64(t *testing.T) { + + v := &Value{data: []uint64{uint64(1), uint64(1), uint64(1), uint64(1), uint64(1), uint64(1)}} + + collected := v.CollectUint64(func(index int, val uint64) interface{} { + return index + }) + + collectedArr := collected.MustInterSlice() + if assert.Equal(t, 6, len(collectedArr)) { + assert.Equal(t, collectedArr[0], 0) + assert.Equal(t, collectedArr[1], 1) + assert.Equal(t, collectedArr[2], 2) + assert.Equal(t, collectedArr[3], 3) + assert.Equal(t, collectedArr[4], 4) + assert.Equal(t, collectedArr[5], 5) + } + +} + +// ************************************************************ +// TESTS +// ************************************************************ + +func TestUintptr(t *testing.T) { + + val := uintptr(1) + m := map[string]interface{}{"value": val, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Uintptr()) + assert.Equal(t, val, New(m).Get("value").MustUintptr()) + assert.Equal(t, uintptr(0), New(m).Get("nothing").Uintptr()) + assert.Equal(t, val, New(m).Get("nothing").Uintptr(1)) + + assert.Panics(t, func() { + New(m).Get("age").MustUintptr() + }) + +} + +func TestUintptrSlice(t *testing.T) { + + val := uintptr(1) + m := map[string]interface{}{"value": []uintptr{val}, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").UintptrSlice()[0]) + assert.Equal(t, val, New(m).Get("value").MustUintptrSlice()[0]) + assert.Equal(t, []uintptr(nil), New(m).Get("nothing").UintptrSlice()) + assert.Equal(t, val, New(m).Get("nothing").UintptrSlice([]uintptr{uintptr(1)})[0]) + + assert.Panics(t, func() { + New(m).Get("nothing").MustUintptrSlice() + }) + +} + +func TestIsUintptr(t *testing.T) { + + var v *Value + + v = &Value{data: uintptr(1)} + assert.True(t, v.IsUintptr()) + + v = &Value{data: []uintptr{uintptr(1)}} + assert.True(t, v.IsUintptrSlice()) + +} + +func TestEachUintptr(t *testing.T) { + + v := &Value{data: []uintptr{uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1)}} + count := 0 + replacedVals := make([]uintptr, 0) + assert.Equal(t, v, v.EachUintptr(func(i int, val uintptr) bool { + + count++ + replacedVals = append(replacedVals, val) + + // abort early + if i == 2 { + return false + } + + return true + + })) + + assert.Equal(t, count, 3) + assert.Equal(t, replacedVals[0], v.MustUintptrSlice()[0]) + assert.Equal(t, replacedVals[1], v.MustUintptrSlice()[1]) + assert.Equal(t, replacedVals[2], v.MustUintptrSlice()[2]) + +} + +func TestWhereUintptr(t *testing.T) { + + v := &Value{data: []uintptr{uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1)}} + + selected := v.WhereUintptr(func(i int, val uintptr) bool { + return i%2 == 0 + }).MustUintptrSlice() + + assert.Equal(t, 3, len(selected)) + +} + +func TestGroupUintptr(t *testing.T) { + + v := &Value{data: []uintptr{uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1)}} + + grouped := v.GroupUintptr(func(i int, val uintptr) string { + return fmt.Sprintf("%v", i%2 == 0) + }).data.(map[string][]uintptr) + + assert.Equal(t, 2, len(grouped)) + assert.Equal(t, 3, len(grouped["true"])) + assert.Equal(t, 3, len(grouped["false"])) + +} + +func TestReplaceUintptr(t *testing.T) { + + v := &Value{data: []uintptr{uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1)}} + + rawArr := v.MustUintptrSlice() + + replaced := v.ReplaceUintptr(func(index int, val uintptr) uintptr { + if index < len(rawArr)-1 { + return rawArr[index+1] + } + return rawArr[0] + }) + + replacedArr := replaced.MustUintptrSlice() + if assert.Equal(t, 6, len(replacedArr)) { + assert.Equal(t, replacedArr[0], rawArr[1]) + assert.Equal(t, replacedArr[1], rawArr[2]) + assert.Equal(t, replacedArr[2], rawArr[3]) + assert.Equal(t, replacedArr[3], rawArr[4]) + assert.Equal(t, replacedArr[4], rawArr[5]) + assert.Equal(t, replacedArr[5], rawArr[0]) + } + +} + +func TestCollectUintptr(t *testing.T) { + + v := &Value{data: []uintptr{uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1), uintptr(1)}} + + collected := v.CollectUintptr(func(index int, val uintptr) interface{} { + return index + }) + + collectedArr := collected.MustInterSlice() + if assert.Equal(t, 6, len(collectedArr)) { + assert.Equal(t, collectedArr[0], 0) + assert.Equal(t, collectedArr[1], 1) + assert.Equal(t, collectedArr[2], 2) + assert.Equal(t, collectedArr[3], 3) + assert.Equal(t, collectedArr[4], 4) + assert.Equal(t, collectedArr[5], 5) + } + +} + +// ************************************************************ +// TESTS +// ************************************************************ + +func TestFloat32(t *testing.T) { + + val := float32(1) + m := map[string]interface{}{"value": val, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Float32()) + assert.Equal(t, val, New(m).Get("value").MustFloat32()) + assert.Equal(t, float32(0), New(m).Get("nothing").Float32()) + assert.Equal(t, val, New(m).Get("nothing").Float32(1)) + + assert.Panics(t, func() { + New(m).Get("age").MustFloat32() + }) + +} + +func TestFloat32Slice(t *testing.T) { + + val := float32(1) + m := map[string]interface{}{"value": []float32{val}, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Float32Slice()[0]) + assert.Equal(t, val, New(m).Get("value").MustFloat32Slice()[0]) + assert.Equal(t, []float32(nil), New(m).Get("nothing").Float32Slice()) + assert.Equal(t, val, New(m).Get("nothing").Float32Slice([]float32{float32(1)})[0]) + + assert.Panics(t, func() { + New(m).Get("nothing").MustFloat32Slice() + }) + +} + +func TestIsFloat32(t *testing.T) { + + var v *Value + + v = &Value{data: float32(1)} + assert.True(t, v.IsFloat32()) + + v = &Value{data: []float32{float32(1)}} + assert.True(t, v.IsFloat32Slice()) + +} + +func TestEachFloat32(t *testing.T) { + + v := &Value{data: []float32{float32(1), float32(1), float32(1), float32(1), float32(1)}} + count := 0 + replacedVals := make([]float32, 0) + assert.Equal(t, v, v.EachFloat32(func(i int, val float32) bool { + + count++ + replacedVals = append(replacedVals, val) + + // abort early + if i == 2 { + return false + } + + return true + + })) + + assert.Equal(t, count, 3) + assert.Equal(t, replacedVals[0], v.MustFloat32Slice()[0]) + assert.Equal(t, replacedVals[1], v.MustFloat32Slice()[1]) + assert.Equal(t, replacedVals[2], v.MustFloat32Slice()[2]) + +} + +func TestWhereFloat32(t *testing.T) { + + v := &Value{data: []float32{float32(1), float32(1), float32(1), float32(1), float32(1), float32(1)}} + + selected := v.WhereFloat32(func(i int, val float32) bool { + return i%2 == 0 + }).MustFloat32Slice() + + assert.Equal(t, 3, len(selected)) + +} + +func TestGroupFloat32(t *testing.T) { + + v := &Value{data: []float32{float32(1), float32(1), float32(1), float32(1), float32(1), float32(1)}} + + grouped := v.GroupFloat32(func(i int, val float32) string { + return fmt.Sprintf("%v", i%2 == 0) + }).data.(map[string][]float32) + + assert.Equal(t, 2, len(grouped)) + assert.Equal(t, 3, len(grouped["true"])) + assert.Equal(t, 3, len(grouped["false"])) + +} + +func TestReplaceFloat32(t *testing.T) { + + v := &Value{data: []float32{float32(1), float32(1), float32(1), float32(1), float32(1), float32(1)}} + + rawArr := v.MustFloat32Slice() + + replaced := v.ReplaceFloat32(func(index int, val float32) float32 { + if index < len(rawArr)-1 { + return rawArr[index+1] + } + return rawArr[0] + }) + + replacedArr := replaced.MustFloat32Slice() + if assert.Equal(t, 6, len(replacedArr)) { + assert.Equal(t, replacedArr[0], rawArr[1]) + assert.Equal(t, replacedArr[1], rawArr[2]) + assert.Equal(t, replacedArr[2], rawArr[3]) + assert.Equal(t, replacedArr[3], rawArr[4]) + assert.Equal(t, replacedArr[4], rawArr[5]) + assert.Equal(t, replacedArr[5], rawArr[0]) + } + +} + +func TestCollectFloat32(t *testing.T) { + + v := &Value{data: []float32{float32(1), float32(1), float32(1), float32(1), float32(1), float32(1)}} + + collected := v.CollectFloat32(func(index int, val float32) interface{} { + return index + }) + + collectedArr := collected.MustInterSlice() + if assert.Equal(t, 6, len(collectedArr)) { + assert.Equal(t, collectedArr[0], 0) + assert.Equal(t, collectedArr[1], 1) + assert.Equal(t, collectedArr[2], 2) + assert.Equal(t, collectedArr[3], 3) + assert.Equal(t, collectedArr[4], 4) + assert.Equal(t, collectedArr[5], 5) + } + +} + +// ************************************************************ +// TESTS +// ************************************************************ + +func TestFloat64(t *testing.T) { + + val := float64(1) + m := map[string]interface{}{"value": val, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Float64()) + assert.Equal(t, val, New(m).Get("value").MustFloat64()) + assert.Equal(t, float64(0), New(m).Get("nothing").Float64()) + assert.Equal(t, val, New(m).Get("nothing").Float64(1)) + + assert.Panics(t, func() { + New(m).Get("age").MustFloat64() + }) + +} + +func TestFloat64Slice(t *testing.T) { + + val := float64(1) + m := map[string]interface{}{"value": []float64{val}, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Float64Slice()[0]) + assert.Equal(t, val, New(m).Get("value").MustFloat64Slice()[0]) + assert.Equal(t, []float64(nil), New(m).Get("nothing").Float64Slice()) + assert.Equal(t, val, New(m).Get("nothing").Float64Slice([]float64{float64(1)})[0]) + + assert.Panics(t, func() { + New(m).Get("nothing").MustFloat64Slice() + }) + +} + +func TestIsFloat64(t *testing.T) { + + var v *Value + + v = &Value{data: float64(1)} + assert.True(t, v.IsFloat64()) + + v = &Value{data: []float64{float64(1)}} + assert.True(t, v.IsFloat64Slice()) + +} + +func TestEachFloat64(t *testing.T) { + + v := &Value{data: []float64{float64(1), float64(1), float64(1), float64(1), float64(1)}} + count := 0 + replacedVals := make([]float64, 0) + assert.Equal(t, v, v.EachFloat64(func(i int, val float64) bool { + + count++ + replacedVals = append(replacedVals, val) + + // abort early + if i == 2 { + return false + } + + return true + + })) + + assert.Equal(t, count, 3) + assert.Equal(t, replacedVals[0], v.MustFloat64Slice()[0]) + assert.Equal(t, replacedVals[1], v.MustFloat64Slice()[1]) + assert.Equal(t, replacedVals[2], v.MustFloat64Slice()[2]) + +} + +func TestWhereFloat64(t *testing.T) { + + v := &Value{data: []float64{float64(1), float64(1), float64(1), float64(1), float64(1), float64(1)}} + + selected := v.WhereFloat64(func(i int, val float64) bool { + return i%2 == 0 + }).MustFloat64Slice() + + assert.Equal(t, 3, len(selected)) + +} + +func TestGroupFloat64(t *testing.T) { + + v := &Value{data: []float64{float64(1), float64(1), float64(1), float64(1), float64(1), float64(1)}} + + grouped := v.GroupFloat64(func(i int, val float64) string { + return fmt.Sprintf("%v", i%2 == 0) + }).data.(map[string][]float64) + + assert.Equal(t, 2, len(grouped)) + assert.Equal(t, 3, len(grouped["true"])) + assert.Equal(t, 3, len(grouped["false"])) + +} + +func TestReplaceFloat64(t *testing.T) { + + v := &Value{data: []float64{float64(1), float64(1), float64(1), float64(1), float64(1), float64(1)}} + + rawArr := v.MustFloat64Slice() + + replaced := v.ReplaceFloat64(func(index int, val float64) float64 { + if index < len(rawArr)-1 { + return rawArr[index+1] + } + return rawArr[0] + }) + + replacedArr := replaced.MustFloat64Slice() + if assert.Equal(t, 6, len(replacedArr)) { + assert.Equal(t, replacedArr[0], rawArr[1]) + assert.Equal(t, replacedArr[1], rawArr[2]) + assert.Equal(t, replacedArr[2], rawArr[3]) + assert.Equal(t, replacedArr[3], rawArr[4]) + assert.Equal(t, replacedArr[4], rawArr[5]) + assert.Equal(t, replacedArr[5], rawArr[0]) + } + +} + +func TestCollectFloat64(t *testing.T) { + + v := &Value{data: []float64{float64(1), float64(1), float64(1), float64(1), float64(1), float64(1)}} + + collected := v.CollectFloat64(func(index int, val float64) interface{} { + return index + }) + + collectedArr := collected.MustInterSlice() + if assert.Equal(t, 6, len(collectedArr)) { + assert.Equal(t, collectedArr[0], 0) + assert.Equal(t, collectedArr[1], 1) + assert.Equal(t, collectedArr[2], 2) + assert.Equal(t, collectedArr[3], 3) + assert.Equal(t, collectedArr[4], 4) + assert.Equal(t, collectedArr[5], 5) + } + +} + +// ************************************************************ +// TESTS +// ************************************************************ + +func TestComplex64(t *testing.T) { + + val := complex64(1) + m := map[string]interface{}{"value": val, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Complex64()) + assert.Equal(t, val, New(m).Get("value").MustComplex64()) + assert.Equal(t, complex64(0), New(m).Get("nothing").Complex64()) + assert.Equal(t, val, New(m).Get("nothing").Complex64(1)) + + assert.Panics(t, func() { + New(m).Get("age").MustComplex64() + }) + +} + +func TestComplex64Slice(t *testing.T) { + + val := complex64(1) + m := map[string]interface{}{"value": []complex64{val}, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Complex64Slice()[0]) + assert.Equal(t, val, New(m).Get("value").MustComplex64Slice()[0]) + assert.Equal(t, []complex64(nil), New(m).Get("nothing").Complex64Slice()) + assert.Equal(t, val, New(m).Get("nothing").Complex64Slice([]complex64{complex64(1)})[0]) + + assert.Panics(t, func() { + New(m).Get("nothing").MustComplex64Slice() + }) + +} + +func TestIsComplex64(t *testing.T) { + + var v *Value + + v = &Value{data: complex64(1)} + assert.True(t, v.IsComplex64()) + + v = &Value{data: []complex64{complex64(1)}} + assert.True(t, v.IsComplex64Slice()) + +} + +func TestEachComplex64(t *testing.T) { + + v := &Value{data: []complex64{complex64(1), complex64(1), complex64(1), complex64(1), complex64(1)}} + count := 0 + replacedVals := make([]complex64, 0) + assert.Equal(t, v, v.EachComplex64(func(i int, val complex64) bool { + + count++ + replacedVals = append(replacedVals, val) + + // abort early + if i == 2 { + return false + } + + return true + + })) + + assert.Equal(t, count, 3) + assert.Equal(t, replacedVals[0], v.MustComplex64Slice()[0]) + assert.Equal(t, replacedVals[1], v.MustComplex64Slice()[1]) + assert.Equal(t, replacedVals[2], v.MustComplex64Slice()[2]) + +} + +func TestWhereComplex64(t *testing.T) { + + v := &Value{data: []complex64{complex64(1), complex64(1), complex64(1), complex64(1), complex64(1), complex64(1)}} + + selected := v.WhereComplex64(func(i int, val complex64) bool { + return i%2 == 0 + }).MustComplex64Slice() + + assert.Equal(t, 3, len(selected)) + +} + +func TestGroupComplex64(t *testing.T) { + + v := &Value{data: []complex64{complex64(1), complex64(1), complex64(1), complex64(1), complex64(1), complex64(1)}} + + grouped := v.GroupComplex64(func(i int, val complex64) string { + return fmt.Sprintf("%v", i%2 == 0) + }).data.(map[string][]complex64) + + assert.Equal(t, 2, len(grouped)) + assert.Equal(t, 3, len(grouped["true"])) + assert.Equal(t, 3, len(grouped["false"])) + +} + +func TestReplaceComplex64(t *testing.T) { + + v := &Value{data: []complex64{complex64(1), complex64(1), complex64(1), complex64(1), complex64(1), complex64(1)}} + + rawArr := v.MustComplex64Slice() + + replaced := v.ReplaceComplex64(func(index int, val complex64) complex64 { + if index < len(rawArr)-1 { + return rawArr[index+1] + } + return rawArr[0] + }) + + replacedArr := replaced.MustComplex64Slice() + if assert.Equal(t, 6, len(replacedArr)) { + assert.Equal(t, replacedArr[0], rawArr[1]) + assert.Equal(t, replacedArr[1], rawArr[2]) + assert.Equal(t, replacedArr[2], rawArr[3]) + assert.Equal(t, replacedArr[3], rawArr[4]) + assert.Equal(t, replacedArr[4], rawArr[5]) + assert.Equal(t, replacedArr[5], rawArr[0]) + } + +} + +func TestCollectComplex64(t *testing.T) { + + v := &Value{data: []complex64{complex64(1), complex64(1), complex64(1), complex64(1), complex64(1), complex64(1)}} + + collected := v.CollectComplex64(func(index int, val complex64) interface{} { + return index + }) + + collectedArr := collected.MustInterSlice() + if assert.Equal(t, 6, len(collectedArr)) { + assert.Equal(t, collectedArr[0], 0) + assert.Equal(t, collectedArr[1], 1) + assert.Equal(t, collectedArr[2], 2) + assert.Equal(t, collectedArr[3], 3) + assert.Equal(t, collectedArr[4], 4) + assert.Equal(t, collectedArr[5], 5) + } + +} + +// ************************************************************ +// TESTS +// ************************************************************ + +func TestComplex128(t *testing.T) { + + val := complex128(1) + m := map[string]interface{}{"value": val, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Complex128()) + assert.Equal(t, val, New(m).Get("value").MustComplex128()) + assert.Equal(t, complex128(0), New(m).Get("nothing").Complex128()) + assert.Equal(t, val, New(m).Get("nothing").Complex128(1)) + + assert.Panics(t, func() { + New(m).Get("age").MustComplex128() + }) + +} + +func TestComplex128Slice(t *testing.T) { + + val := complex128(1) + m := map[string]interface{}{"value": []complex128{val}, "nothing": nil} + assert.Equal(t, val, New(m).Get("value").Complex128Slice()[0]) + assert.Equal(t, val, New(m).Get("value").MustComplex128Slice()[0]) + assert.Equal(t, []complex128(nil), New(m).Get("nothing").Complex128Slice()) + assert.Equal(t, val, New(m).Get("nothing").Complex128Slice([]complex128{complex128(1)})[0]) + + assert.Panics(t, func() { + New(m).Get("nothing").MustComplex128Slice() + }) + +} + +func TestIsComplex128(t *testing.T) { + + var v *Value + + v = &Value{data: complex128(1)} + assert.True(t, v.IsComplex128()) + + v = &Value{data: []complex128{complex128(1)}} + assert.True(t, v.IsComplex128Slice()) + +} + +func TestEachComplex128(t *testing.T) { + + v := &Value{data: []complex128{complex128(1), complex128(1), complex128(1), complex128(1), complex128(1)}} + count := 0 + replacedVals := make([]complex128, 0) + assert.Equal(t, v, v.EachComplex128(func(i int, val complex128) bool { + + count++ + replacedVals = append(replacedVals, val) + + // abort early + if i == 2 { + return false + } + + return true + + })) + + assert.Equal(t, count, 3) + assert.Equal(t, replacedVals[0], v.MustComplex128Slice()[0]) + assert.Equal(t, replacedVals[1], v.MustComplex128Slice()[1]) + assert.Equal(t, replacedVals[2], v.MustComplex128Slice()[2]) + +} + +func TestWhereComplex128(t *testing.T) { + + v := &Value{data: []complex128{complex128(1), complex128(1), complex128(1), complex128(1), complex128(1), complex128(1)}} + + selected := v.WhereComplex128(func(i int, val complex128) bool { + return i%2 == 0 + }).MustComplex128Slice() + + assert.Equal(t, 3, len(selected)) + +} + +func TestGroupComplex128(t *testing.T) { + + v := &Value{data: []complex128{complex128(1), complex128(1), complex128(1), complex128(1), complex128(1), complex128(1)}} + + grouped := v.GroupComplex128(func(i int, val complex128) string { + return fmt.Sprintf("%v", i%2 == 0) + }).data.(map[string][]complex128) + + assert.Equal(t, 2, len(grouped)) + assert.Equal(t, 3, len(grouped["true"])) + assert.Equal(t, 3, len(grouped["false"])) + +} + +func TestReplaceComplex128(t *testing.T) { + + v := &Value{data: []complex128{complex128(1), complex128(1), complex128(1), complex128(1), complex128(1), complex128(1)}} + + rawArr := v.MustComplex128Slice() + + replaced := v.ReplaceComplex128(func(index int, val complex128) complex128 { + if index < len(rawArr)-1 { + return rawArr[index+1] + } + return rawArr[0] + }) + + replacedArr := replaced.MustComplex128Slice() + if assert.Equal(t, 6, len(replacedArr)) { + assert.Equal(t, replacedArr[0], rawArr[1]) + assert.Equal(t, replacedArr[1], rawArr[2]) + assert.Equal(t, replacedArr[2], rawArr[3]) + assert.Equal(t, replacedArr[3], rawArr[4]) + assert.Equal(t, replacedArr[4], rawArr[5]) + assert.Equal(t, replacedArr[5], rawArr[0]) + } + +} + +func TestCollectComplex128(t *testing.T) { + + v := &Value{data: []complex128{complex128(1), complex128(1), complex128(1), complex128(1), complex128(1), complex128(1)}} + + collected := v.CollectComplex128(func(index int, val complex128) interface{} { + return index + }) + + collectedArr := collected.MustInterSlice() + if assert.Equal(t, 6, len(collectedArr)) { + assert.Equal(t, collectedArr[0], 0) + assert.Equal(t, collectedArr[1], 1) + assert.Equal(t, collectedArr[2], 2) + assert.Equal(t, collectedArr[3], 3) + assert.Equal(t, collectedArr[4], 4) + assert.Equal(t, collectedArr[5], 5) + } + +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/value.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/value.go new file mode 100644 index 000000000..7aaef06b1 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/value.go @@ -0,0 +1,13 @@ +package objx + +// Value provides methods for extracting interface{} data in various +// types. +type Value struct { + // data contains the raw data being managed by this Value + data interface{} +} + +// Data returns the raw data contained by this Value +func (v *Value) Data() interface{} { + return v.data +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/value_test.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/value_test.go new file mode 100644 index 000000000..0bc65d92c --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/objx/value_test.go @@ -0,0 +1 @@ +package objx diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions.go new file mode 100644 index 000000000..58e178165 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions.go @@ -0,0 +1,805 @@ +package assert + +import ( + "bufio" + "bytes" + "fmt" + "reflect" + "regexp" + "runtime" + "strings" + "time" +) + +// TestingT is an interface wrapper around *testing.T +type TestingT interface { + Errorf(format string, args ...interface{}) +} + +// Comparison a custom function that returns true on success and false on failure +type Comparison func() (success bool) + +/* + Helper functions +*/ + +// ObjectsAreEqual determines if two objects are considered equal. +// +// This function does no assertion of any kind. +func ObjectsAreEqual(expected, actual interface{}) bool { + + if expected == nil || actual == nil { + return expected == actual + } + + if reflect.DeepEqual(expected, actual) { + return true + } + + // Last ditch effort + if fmt.Sprintf("%#v", expected) == fmt.Sprintf("%#v", actual) { + return true + } + + return false + +} + +func ObjectsAreEqualValues(expected, actual interface{}) bool { + if ObjectsAreEqual(expected, actual) { + return true + } + + actualType := reflect.TypeOf(actual) + expectedValue := reflect.ValueOf(expected) + if expectedValue.Type().ConvertibleTo(actualType) { + // Attempt comparison after type conversion + if reflect.DeepEqual(actual, expectedValue.Convert(actualType).Interface()) { + return true + } + } + + return false +} + +/* CallerInfo is necessary because the assert functions use the testing object +internally, causing it to print the file:line of the assert method, rather than where +the problem actually occured in calling code.*/ + +// CallerInfo returns a string containing the file and line number of the assert call +// that failed. +func CallerInfo() string { + + file := "" + line := 0 + ok := false + + for i := 0; ; i++ { + _, file, line, ok = runtime.Caller(i) + if !ok { + return "" + } + parts := strings.Split(file, "/") + dir := parts[len(parts)-2] + file = parts[len(parts)-1] + if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" { + break + } + } + + return fmt.Sprintf("%s:%d", file, line) +} + +// getWhitespaceString returns a string that is long enough to overwrite the default +// output from the go testing framework. +func getWhitespaceString() string { + + _, file, line, ok := runtime.Caller(1) + if !ok { + return "" + } + parts := strings.Split(file, "/") + file = parts[len(parts)-1] + + return strings.Repeat(" ", len(fmt.Sprintf("%s:%d: ", file, line))) + +} + +func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { + if len(msgAndArgs) == 0 || msgAndArgs == nil { + return "" + } + if len(msgAndArgs) == 1 { + return msgAndArgs[0].(string) + } + if len(msgAndArgs) > 1 { + return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...) + } + return "" +} + +// Indents all lines of the message by appending a number of tabs to each line, in an output format compatible with Go's +// test printing (see inner comment for specifics) +func indentMessageLines(message string, tabs int) string { + outBuf := new(bytes.Buffer) + + for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ { + if i != 0 { + outBuf.WriteRune('\n') + } + for ii := 0; ii < tabs; ii++ { + outBuf.WriteRune('\t') + // Bizarrely, all lines except the first need one fewer tabs prepended, so deliberately advance the counter + // by 1 prematurely. + if ii == 0 && i > 0 { + ii++ + } + } + outBuf.WriteString(scanner.Text()) + } + + return outBuf.String() +} + +// Fail reports a failure through +func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { + + message := messageFromMsgAndArgs(msgAndArgs...) + + if len(message) > 0 { + t.Errorf("\r%s\r\tLocation:\t%s\n"+ + "\r\tError:%s\n"+ + "\r\tMessages:\t%s\n\r", + getWhitespaceString(), + CallerInfo(), + indentMessageLines(failureMessage, 2), + message) + } else { + t.Errorf("\r%s\r\tLocation:\t%s\n"+ + "\r\tError:%s\n\r", + getWhitespaceString(), + CallerInfo(), + indentMessageLines(failureMessage, 2)) + } + + return false +} + +// Implements asserts that an object is implemented by the specified interface. +// +// assert.Implements(t, (*MyInterface)(nil), new(MyObject), "MyObject") +func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { + + interfaceType := reflect.TypeOf(interfaceObject).Elem() + + if !reflect.TypeOf(object).Implements(interfaceType) { + return Fail(t, fmt.Sprintf("Object must implement %v", interfaceType), msgAndArgs...) + } + + return true + +} + +// IsType asserts that the specified objects are of the same type. +func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { + + if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) { + return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...) + } + + return true +} + +// Equal asserts that two objects are equal. +// +// assert.Equal(t, 123, 123, "123 and 123 should be equal") +// +// Returns whether the assertion was successful (true) or not (false). +func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + + if !ObjectsAreEqual(expected, actual) { + return Fail(t, fmt.Sprintf("Not equal: %#v (expected)\n"+ + " != %#v (actual)", expected, actual), msgAndArgs...) + } + + return true + +} + +// EqualValues asserts that two objects are equal or convertable to the same types +// and equal. +// +// assert.EqualValues(t, uint32(123), int32(123), "123 and 123 should be equal") +// +// Returns whether the assertion was successful (true) or not (false). +func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + + if !ObjectsAreEqualValues(expected, actual) { + return Fail(t, fmt.Sprintf("Not equal: %#v (expected)\n"+ + " != %#v (actual)", expected, actual), msgAndArgs...) + } + + return true + +} + +// Exactly asserts that two objects are equal is value and type. +// +// assert.Exactly(t, int32(123), int64(123), "123 and 123 should NOT be equal") +// +// Returns whether the assertion was successful (true) or not (false). +func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + + aType := reflect.TypeOf(expected) + bType := reflect.TypeOf(actual) + + if aType != bType { + return Fail(t, "Types expected to match exactly", "%v != %v", aType, bType) + } + + return Equal(t, expected, actual, msgAndArgs...) + +} + +// NotNil asserts that the specified object is not nil. +// +// assert.NotNil(t, err, "err should be something") +// +// Returns whether the assertion was successful (true) or not (false). +func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + + success := true + + if object == nil { + success = false + } else { + value := reflect.ValueOf(object) + kind := value.Kind() + if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() { + success = false + } + } + + if !success { + Fail(t, "Expected not to be nil.", msgAndArgs...) + } + + return success +} + +// isNil checks if a specified object is nil or not, without Failing. +func isNil(object interface{}) bool { + if object == nil { + return true + } + + value := reflect.ValueOf(object) + kind := value.Kind() + if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() { + return true + } + + return false +} + +// Nil asserts that the specified object is nil. +// +// assert.Nil(t, err, "err should be nothing") +// +// Returns whether the assertion was successful (true) or not (false). +func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + if isNil(object) { + return true + } + return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...) +} + +var zeros = []interface{}{ + int(0), + int8(0), + int16(0), + int32(0), + int64(0), + uint(0), + uint8(0), + uint16(0), + uint32(0), + uint64(0), + float32(0), + float64(0), +} + +// isEmpty gets whether the specified object is considered empty or not. +func isEmpty(object interface{}) bool { + + if object == nil { + return true + } else if object == "" { + return true + } else if object == false { + return true + } + + for _, v := range zeros { + if object == v { + return true + } + } + + objValue := reflect.ValueOf(object) + + switch objValue.Kind() { + case reflect.Map: + fallthrough + case reflect.Slice, reflect.Chan: + { + return (objValue.Len() == 0) + } + case reflect.Ptr: + { + switch object.(type) { + case *time.Time: + return object.(*time.Time).IsZero() + default: + return false + } + } + } + return false +} + +// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// assert.Empty(t, obj) +// +// Returns whether the assertion was successful (true) or not (false). +func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + + pass := isEmpty(object) + if !pass { + Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...) + } + + return pass + +} + +// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// if assert.NotEmpty(t, obj) { +// assert.Equal(t, "two", obj[1]) +// } +// +// Returns whether the assertion was successful (true) or not (false). +func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + + pass := !isEmpty(object) + if !pass { + Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...) + } + + return pass + +} + +// getLen try to get length of object. +// return (false, 0) if impossible. +func getLen(x interface{}) (ok bool, length int) { + v := reflect.ValueOf(x) + defer func() { + if e := recover(); e != nil { + ok = false + } + }() + return true, v.Len() +} + +// Len asserts that the specified object has specific length. +// Len also fails if the object has a type that len() not accept. +// +// assert.Len(t, mySlice, 3, "The size of slice is not 3") +// +// Returns whether the assertion was successful (true) or not (false). +func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool { + ok, l := getLen(object) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...) + } + + if l != length { + return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but has %d", object, length, l), msgAndArgs...) + } + return true +} + +// True asserts that the specified value is true. +// +// assert.True(t, myBool, "myBool should be true") +// +// Returns whether the assertion was successful (true) or not (false). +func True(t TestingT, value bool, msgAndArgs ...interface{}) bool { + + if value != true { + return Fail(t, "Should be true", msgAndArgs...) + } + + return true + +} + +// False asserts that the specified value is true. +// +// assert.False(t, myBool, "myBool should be false") +// +// Returns whether the assertion was successful (true) or not (false). +func False(t TestingT, value bool, msgAndArgs ...interface{}) bool { + + if value != false { + return Fail(t, "Should be false", msgAndArgs...) + } + + return true + +} + +// NotEqual asserts that the specified values are NOT equal. +// +// assert.NotEqual(t, obj1, obj2, "two objects shouldn't be equal") +// +// Returns whether the assertion was successful (true) or not (false). +func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + + if ObjectsAreEqual(expected, actual) { + return Fail(t, "Should not be equal", msgAndArgs...) + } + + return true + +} + +// containsElement try loop over the list check if the list includes the element. +// return (false, false) if impossible. +// return (true, false) if element was not found. +// return (true, true) if element was found. +func includeElement(list interface{}, element interface{}) (ok, found bool) { + + listValue := reflect.ValueOf(list) + elementValue := reflect.ValueOf(element) + defer func() { + if e := recover(); e != nil { + ok = false + found = false + } + }() + + if reflect.TypeOf(list).Kind() == reflect.String { + return true, strings.Contains(listValue.String(), elementValue.String()) + } + + for i := 0; i < listValue.Len(); i++ { + if ObjectsAreEqual(listValue.Index(i).Interface(), element) { + return true, true + } + } + return true, false + +} + +// Contains asserts that the specified string or list(array, slice...) contains the +// specified substring or element. +// +// assert.Contains(t, "Hello World", "World", "But 'Hello World' does contain 'World'") +// assert.Contains(t, ["Hello", "World"], "World", "But ["Hello", "World"] does contain 'World'") +// +// Returns whether the assertion was successful (true) or not (false). +func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { + + ok, found := includeElement(s, contains) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...) + } + if !found { + return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", s, contains), msgAndArgs...) + } + + return true + +} + +// NotContains asserts that the specified string or list(array, slice...) does NOT contain the +// specified substring or element. +// +// assert.NotContains(t, "Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'") +// assert.NotContains(t, ["Hello", "World"], "Earth", "But ['Hello', 'World'] does NOT contain 'Earth'") +// +// Returns whether the assertion was successful (true) or not (false). +func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { + + ok, found := includeElement(s, contains) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...) + } + if found { + return Fail(t, fmt.Sprintf("\"%s\" should not contain \"%s\"", s, contains), msgAndArgs...) + } + + return true + +} + +// Condition uses a Comparison to assert a complex condition. +func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool { + result := comp() + if !result { + Fail(t, "Condition failed!", msgAndArgs...) + } + return result +} + +// PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics +// methods, and represents a simple func that takes no arguments, and returns nothing. +type PanicTestFunc func() + +// didPanic returns true if the function passed to it panics. Otherwise, it returns false. +func didPanic(f PanicTestFunc) (bool, interface{}) { + + didPanic := false + var message interface{} + func() { + + defer func() { + if message = recover(); message != nil { + didPanic = true + } + }() + + // call the target function + f() + + }() + + return didPanic, message + +} + +// Panics asserts that the code inside the specified PanicTestFunc panics. +// +// assert.Panics(t, func(){ +// GoCrazy() +// }, "Calling GoCrazy() should panic") +// +// Returns whether the assertion was successful (true) or not (false). +func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { + + if funcDidPanic, panicValue := didPanic(f); !funcDidPanic { + return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...) + } + + return true +} + +// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// assert.NotPanics(t, func(){ +// RemainCalm() +// }, "Calling RemainCalm() should NOT panic") +// +// Returns whether the assertion was successful (true) or not (false). +func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { + + if funcDidPanic, panicValue := didPanic(f); funcDidPanic { + return Fail(t, fmt.Sprintf("func %#v should not panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...) + } + + return true +} + +// WithinDuration asserts that the two times are within duration delta of each other. +// +// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s") +// +// Returns whether the assertion was successful (true) or not (false). +func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { + + dt := expected.Sub(actual) + if dt < -delta || dt > delta { + return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) + } + + return true +} + +func toFloat(x interface{}) (float64, bool) { + var xf float64 + xok := true + + switch xn := x.(type) { + case uint8: + xf = float64(xn) + case uint16: + xf = float64(xn) + case uint32: + xf = float64(xn) + case uint64: + xf = float64(xn) + case int: + xf = float64(xn) + case int8: + xf = float64(xn) + case int16: + xf = float64(xn) + case int32: + xf = float64(xn) + case int64: + xf = float64(xn) + case float32: + xf = float64(xn) + case float64: + xf = float64(xn) + default: + xok = false + } + + return xf, xok +} + +// InDelta asserts that the two numerals are within delta of each other. +// +// assert.InDelta(t, math.Pi, (22 / 7.0), 0.01) +// +// Returns whether the assertion was successful (true) or not (false). +func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + + af, aok := toFloat(expected) + bf, bok := toFloat(actual) + + if !aok || !bok { + return Fail(t, fmt.Sprintf("Parameters must be numerical"), msgAndArgs...) + } + + dt := af - bf + if dt < -delta || dt > delta { + return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) + } + + return true +} + +// min(|expected|, |actual|) * epsilon +func calcEpsilonDelta(expected, actual interface{}, epsilon float64) float64 { + af, aok := toFloat(expected) + bf, bok := toFloat(actual) + + if !aok || !bok { + // invalid input + return 0 + } + + if af < 0 { + af = -af + } + if bf < 0 { + bf = -bf + } + var delta float64 + if af < bf { + delta = af * epsilon + } else { + delta = bf * epsilon + } + return delta +} + +// InEpsilon asserts that expected and actual have a relative error less than epsilon +// +// Returns whether the assertion was successful (true) or not (false). +func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + delta := calcEpsilonDelta(expected, actual, epsilon) + + return InDelta(t, expected, actual, delta, msgAndArgs...) +} + +/* + Errors +*/ + +// NoError asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if assert.NoError(t, err) { +// assert.Equal(t, actualObj, expectedObj) +// } +// +// Returns whether the assertion was successful (true) or not (false). +func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool { + if isNil(err) { + return true + } + + return Fail(t, fmt.Sprintf("No error is expected but got %v", err), msgAndArgs...) +} + +// Error asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if assert.Error(t, err, "An error was expected") { +// assert.Equal(t, err, expectedError) +// } +// +// Returns whether the assertion was successful (true) or not (false). +func Error(t TestingT, err error, msgAndArgs ...interface{}) bool { + + message := messageFromMsgAndArgs(msgAndArgs...) + return NotNil(t, err, "An error is expected but got nil. %s", message) + +} + +// EqualError asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// if assert.Error(t, err, "An error was expected") { +// assert.Equal(t, err, expectedError) +// } +// +// Returns whether the assertion was successful (true) or not (false). +func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool { + + message := messageFromMsgAndArgs(msgAndArgs...) + if !NotNil(t, theError, "An error is expected but got nil. %s", message) { + return false + } + s := "An error with value \"%s\" is expected but got \"%s\". %s" + return Equal(t, theError.Error(), errString, + s, errString, theError.Error(), message) +} + +// matchRegexp return true if a specified regexp matches a string. +func matchRegexp(rx interface{}, str interface{}) bool { + + var r *regexp.Regexp + if rr, ok := rx.(*regexp.Regexp); ok { + r = rr + } else { + r = regexp.MustCompile(fmt.Sprint(rx)) + } + + return (r.FindStringIndex(fmt.Sprint(str)) != nil) + +} + +// Regexp asserts that a specified regexp matches a string. +// +// assert.Regexp(t, regexp.MustCompile("start"), "it's starting") +// assert.Regexp(t, "start...$", "it's not starting") +// +// Returns whether the assertion was successful (true) or not (false). +func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + + match := matchRegexp(rx, str) + + if !match { + Fail(t, fmt.Sprintf("Expect \"%v\" to match \"%v\"", str, rx), msgAndArgs...) + } + + return match +} + +// NotRegexp asserts that a specified regexp does not match a string. +// +// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") +// assert.NotRegexp(t, "^start", "it's not starting") +// +// Returns whether the assertion was successful (true) or not (false). +func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + match := matchRegexp(rx, str) + + if match { + Fail(t, fmt.Sprintf("Expect \"%v\" to NOT match \"%v\"", str, rx), msgAndArgs...) + } + + return !match + +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions_test.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions_test.go new file mode 100644 index 000000000..2cb58dbd7 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions_test.go @@ -0,0 +1,768 @@ +package assert + +import ( + "errors" + "regexp" + "testing" + "time" +) + +// AssertionTesterInterface defines an interface to be used for testing assertion methods +type AssertionTesterInterface interface { + TestMethod() +} + +// AssertionTesterConformingObject is an object that conforms to the AssertionTesterInterface interface +type AssertionTesterConformingObject struct { +} + +func (a *AssertionTesterConformingObject) TestMethod() { +} + +// AssertionTesterNonConformingObject is an object that does not conform to the AssertionTesterInterface interface +type AssertionTesterNonConformingObject struct { +} + +func TestObjectsAreEqual(t *testing.T) { + + if !ObjectsAreEqual("Hello World", "Hello World") { + t.Error("objectsAreEqual should return true") + } + if !ObjectsAreEqual(123, 123) { + t.Error("objectsAreEqual should return true") + } + if !ObjectsAreEqual(123.5, 123.5) { + t.Error("objectsAreEqual should return true") + } + if !ObjectsAreEqual([]byte("Hello World"), []byte("Hello World")) { + t.Error("objectsAreEqual should return true") + } + if !ObjectsAreEqual(nil, nil) { + t.Error("objectsAreEqual should return true") + } + if ObjectsAreEqual(map[int]int{5: 10}, map[int]int{10: 20}) { + t.Error("objectsAreEqual should return false") + } + if ObjectsAreEqual('x', "x") { + t.Error("objectsAreEqual should return false") + } + if ObjectsAreEqual("x", 'x') { + t.Error("objectsAreEqual should return false") + } + if ObjectsAreEqual(0, 0.1) { + t.Error("objectsAreEqual should return false") + } + if ObjectsAreEqual(0.1, 0) { + t.Error("objectsAreEqual should return false") + } + if ObjectsAreEqual(uint32(10), int32(10)) { + t.Error("objectsAreEqual should return false") + } + if !ObjectsAreEqualValues(uint32(10), int32(10)) { + t.Error("ObjectsAreEqualValues should return true") + } + +} + +func TestImplements(t *testing.T) { + + mockT := new(testing.T) + + if !Implements(mockT, (*AssertionTesterInterface)(nil), new(AssertionTesterConformingObject)) { + t.Error("Implements method should return true: AssertionTesterConformingObject implements AssertionTesterInterface") + } + if Implements(mockT, (*AssertionTesterInterface)(nil), new(AssertionTesterNonConformingObject)) { + t.Error("Implements method should return false: AssertionTesterNonConformingObject does not implements AssertionTesterInterface") + } + +} + +func TestIsType(t *testing.T) { + + mockT := new(testing.T) + + if !IsType(mockT, new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) { + t.Error("IsType should return true: AssertionTesterConformingObject is the same type as AssertionTesterConformingObject") + } + if IsType(mockT, new(AssertionTesterConformingObject), new(AssertionTesterNonConformingObject)) { + t.Error("IsType should return false: AssertionTesterConformingObject is not the same type as AssertionTesterNonConformingObject") + } + +} + +func TestEqual(t *testing.T) { + + mockT := new(testing.T) + + if !Equal(mockT, "Hello World", "Hello World") { + t.Error("Equal should return true") + } + if !Equal(mockT, 123, 123) { + t.Error("Equal should return true") + } + if !Equal(mockT, 123.5, 123.5) { + t.Error("Equal should return true") + } + if !Equal(mockT, []byte("Hello World"), []byte("Hello World")) { + t.Error("Equal should return true") + } + if !Equal(mockT, nil, nil) { + t.Error("Equal should return true") + } + if !Equal(mockT, int32(123), int32(123)) { + t.Error("Equal should return true") + } + if !Equal(mockT, uint64(123), uint64(123)) { + t.Error("Equal should return true") + } + funcA := func() int { return 42 } + if !Equal(mockT, funcA, funcA) { + t.Error("Equal should return true") + } + +} + +func TestNotNil(t *testing.T) { + + mockT := new(testing.T) + + if !NotNil(mockT, new(AssertionTesterConformingObject)) { + t.Error("NotNil should return true: object is not nil") + } + if NotNil(mockT, nil) { + t.Error("NotNil should return false: object is nil") + } + +} + +func TestNil(t *testing.T) { + + mockT := new(testing.T) + + if !Nil(mockT, nil) { + t.Error("Nil should return true: object is nil") + } + if Nil(mockT, new(AssertionTesterConformingObject)) { + t.Error("Nil should return false: object is not nil") + } + +} + +func TestTrue(t *testing.T) { + + mockT := new(testing.T) + + if !True(mockT, true) { + t.Error("True should return true") + } + if True(mockT, false) { + t.Error("True should return false") + } + +} + +func TestFalse(t *testing.T) { + + mockT := new(testing.T) + + if !False(mockT, false) { + t.Error("False should return true") + } + if False(mockT, true) { + t.Error("False should return false") + } + +} + +func TestExactly(t *testing.T) { + + mockT := new(testing.T) + + a := float32(1) + b := float64(1) + c := float32(1) + d := float32(2) + + if Exactly(mockT, a, b) { + t.Error("Exactly should return false") + } + if Exactly(mockT, a, d) { + t.Error("Exactly should return false") + } + if !Exactly(mockT, a, c) { + t.Error("Exactly should return true") + } + + if Exactly(mockT, nil, a) { + t.Error("Exactly should return false") + } + if Exactly(mockT, a, nil) { + t.Error("Exactly should return false") + } + +} + +func TestNotEqual(t *testing.T) { + + mockT := new(testing.T) + + if !NotEqual(mockT, "Hello World", "Hello World!") { + t.Error("NotEqual should return true") + } + if !NotEqual(mockT, 123, 1234) { + t.Error("NotEqual should return true") + } + if !NotEqual(mockT, 123.5, 123.55) { + t.Error("NotEqual should return true") + } + if !NotEqual(mockT, []byte("Hello World"), []byte("Hello World!")) { + t.Error("NotEqual should return true") + } + if !NotEqual(mockT, nil, new(AssertionTesterConformingObject)) { + t.Error("NotEqual should return true") + } + funcA := func() int { return 23 } + funcB := func() int { return 42 } + if !NotEqual(mockT, funcA, funcB) { + t.Error("NotEqual should return true") + } + + if NotEqual(mockT, "Hello World", "Hello World") { + t.Error("NotEqual should return false") + } + if NotEqual(mockT, 123, 123) { + t.Error("NotEqual should return false") + } + if NotEqual(mockT, 123.5, 123.5) { + t.Error("NotEqual should return false") + } + if NotEqual(mockT, []byte("Hello World"), []byte("Hello World")) { + t.Error("NotEqual should return false") + } + if NotEqual(mockT, new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) { + t.Error("NotEqual should return false") + } +} + +type A struct { + Name, Value string +} + +func TestContains(t *testing.T) { + + mockT := new(testing.T) + list := []string{"Foo", "Bar"} + complexList := []*A{ + {"b", "c"}, + {"d", "e"}, + {"g", "h"}, + {"j", "k"}, + } + + if !Contains(mockT, "Hello World", "Hello") { + t.Error("Contains should return true: \"Hello World\" contains \"Hello\"") + } + if Contains(mockT, "Hello World", "Salut") { + t.Error("Contains should return false: \"Hello World\" does not contain \"Salut\"") + } + + if !Contains(mockT, list, "Bar") { + t.Error("Contains should return true: \"[\"Foo\", \"Bar\"]\" contains \"Bar\"") + } + if Contains(mockT, list, "Salut") { + t.Error("Contains should return false: \"[\"Foo\", \"Bar\"]\" does not contain \"Salut\"") + } + if !Contains(mockT, complexList, &A{"g", "h"}) { + t.Error("Contains should return true: complexList contains {\"g\", \"h\"}") + } + if Contains(mockT, complexList, &A{"g", "e"}) { + t.Error("Contains should return false: complexList contains {\"g\", \"e\"}") + } +} + +func TestNotContains(t *testing.T) { + + mockT := new(testing.T) + list := []string{"Foo", "Bar"} + + if !NotContains(mockT, "Hello World", "Hello!") { + t.Error("NotContains should return true: \"Hello World\" does not contain \"Hello!\"") + } + if NotContains(mockT, "Hello World", "Hello") { + t.Error("NotContains should return false: \"Hello World\" contains \"Hello\"") + } + + if !NotContains(mockT, list, "Foo!") { + t.Error("NotContains should return true: \"[\"Foo\", \"Bar\"]\" does not contain \"Foo!\"") + } + if NotContains(mockT, list, "Foo") { + t.Error("NotContains should return false: \"[\"Foo\", \"Bar\"]\" contains \"Foo\"") + } + +} + +func Test_includeElement(t *testing.T) { + + list1 := []string{"Foo", "Bar"} + list2 := []int{1, 2} + + ok, found := includeElement("Hello World", "World") + True(t, ok) + True(t, found) + + ok, found = includeElement(list1, "Foo") + True(t, ok) + True(t, found) + + ok, found = includeElement(list1, "Bar") + True(t, ok) + True(t, found) + + ok, found = includeElement(list2, 1) + True(t, ok) + True(t, found) + + ok, found = includeElement(list2, 2) + True(t, ok) + True(t, found) + + ok, found = includeElement(list1, "Foo!") + True(t, ok) + False(t, found) + + ok, found = includeElement(list2, 3) + True(t, ok) + False(t, found) + + ok, found = includeElement(list2, "1") + True(t, ok) + False(t, found) + + ok, found = includeElement(1433, "1") + False(t, ok) + False(t, found) + +} + +func TestCondition(t *testing.T) { + mockT := new(testing.T) + + if !Condition(mockT, func() bool { return true }, "Truth") { + t.Error("Condition should return true") + } + + if Condition(mockT, func() bool { return false }, "Lie") { + t.Error("Condition should return false") + } + +} + +func TestDidPanic(t *testing.T) { + + if funcDidPanic, _ := didPanic(func() { + panic("Panic!") + }); !funcDidPanic { + t.Error("didPanic should return true") + } + + if funcDidPanic, _ := didPanic(func() { + }); funcDidPanic { + t.Error("didPanic should return false") + } + +} + +func TestPanics(t *testing.T) { + + mockT := new(testing.T) + + if !Panics(mockT, func() { + panic("Panic!") + }) { + t.Error("Panics should return true") + } + + if Panics(mockT, func() { + }) { + t.Error("Panics should return false") + } + +} + +func TestNotPanics(t *testing.T) { + + mockT := new(testing.T) + + if !NotPanics(mockT, func() { + }) { + t.Error("NotPanics should return true") + } + + if NotPanics(mockT, func() { + panic("Panic!") + }) { + t.Error("NotPanics should return false") + } + +} + +func TestEqual_Funcs(t *testing.T) { + + type f func() int + f1 := func() int { return 1 } + f2 := func() int { return 2 } + + f1Copy := f1 + + Equal(t, f1Copy, f1, "Funcs are the same and should be considered equal") + NotEqual(t, f1, f2, "f1 and f2 are different") + +} + +func TestNoError(t *testing.T) { + + mockT := new(testing.T) + + // start with a nil error + var err error + + True(t, NoError(mockT, err), "NoError should return True for nil arg") + + // now set an error + err = errors.New("some error") + + False(t, NoError(mockT, err), "NoError with error should return False") + +} + +func TestError(t *testing.T) { + + mockT := new(testing.T) + + // start with a nil error + var err error + + False(t, Error(mockT, err), "Error should return False for nil arg") + + // now set an error + err = errors.New("some error") + + True(t, Error(mockT, err), "Error with error should return True") + +} + +func TestEqualError(t *testing.T) { + mockT := new(testing.T) + + // start with a nil error + var err error + False(t, EqualError(mockT, err, ""), + "EqualError should return false for nil arg") + + // now set an error + err = errors.New("some error") + False(t, EqualError(mockT, err, "Not some error"), + "EqualError should return false for different error string") + True(t, EqualError(mockT, err, "some error"), + "EqualError should return true") +} + +func Test_isEmpty(t *testing.T) { + + chWithValue := make(chan struct{}, 1) + chWithValue <- struct{}{} + + True(t, isEmpty("")) + True(t, isEmpty(nil)) + True(t, isEmpty([]string{})) + True(t, isEmpty(0)) + True(t, isEmpty(int32(0))) + True(t, isEmpty(int64(0))) + True(t, isEmpty(false)) + True(t, isEmpty(map[string]string{})) + True(t, isEmpty(new(time.Time))) + True(t, isEmpty(make(chan struct{}))) + False(t, isEmpty("something")) + False(t, isEmpty(errors.New("something"))) + False(t, isEmpty([]string{"something"})) + False(t, isEmpty(1)) + False(t, isEmpty(true)) + False(t, isEmpty(map[string]string{"Hello": "World"})) + False(t, isEmpty(chWithValue)) + +} + +func TestEmpty(t *testing.T) { + + mockT := new(testing.T) + chWithValue := make(chan struct{}, 1) + chWithValue <- struct{}{} + + True(t, Empty(mockT, ""), "Empty string is empty") + True(t, Empty(mockT, nil), "Nil is empty") + True(t, Empty(mockT, []string{}), "Empty string array is empty") + True(t, Empty(mockT, 0), "Zero int value is empty") + True(t, Empty(mockT, false), "False value is empty") + True(t, Empty(mockT, make(chan struct{})), "Channel without values is empty") + + False(t, Empty(mockT, "something"), "Non Empty string is not empty") + False(t, Empty(mockT, errors.New("something")), "Non nil object is not empty") + False(t, Empty(mockT, []string{"something"}), "Non empty string array is not empty") + False(t, Empty(mockT, 1), "Non-zero int value is not empty") + False(t, Empty(mockT, true), "True value is not empty") + False(t, Empty(mockT, chWithValue), "Channel with values is not empty") +} + +func TestNotEmpty(t *testing.T) { + + mockT := new(testing.T) + chWithValue := make(chan struct{}, 1) + chWithValue <- struct{}{} + + False(t, NotEmpty(mockT, ""), "Empty string is empty") + False(t, NotEmpty(mockT, nil), "Nil is empty") + False(t, NotEmpty(mockT, []string{}), "Empty string array is empty") + False(t, NotEmpty(mockT, 0), "Zero int value is empty") + False(t, NotEmpty(mockT, false), "False value is empty") + False(t, NotEmpty(mockT, make(chan struct{})), "Channel without values is empty") + + True(t, NotEmpty(mockT, "something"), "Non Empty string is not empty") + True(t, NotEmpty(mockT, errors.New("something")), "Non nil object is not empty") + True(t, NotEmpty(mockT, []string{"something"}), "Non empty string array is not empty") + True(t, NotEmpty(mockT, 1), "Non-zero int value is not empty") + True(t, NotEmpty(mockT, true), "True value is not empty") + True(t, NotEmpty(mockT, chWithValue), "Channel with values is not empty") +} + +func Test_getLen(t *testing.T) { + falseCases := []interface{}{ + nil, + 0, + true, + false, + 'A', + struct{}{}, + } + for _, v := range falseCases { + ok, l := getLen(v) + False(t, ok, "Expected getLen fail to get length of %#v", v) + Equal(t, 0, l, "getLen should return 0 for %#v", v) + } + + ch := make(chan int, 5) + ch <- 1 + ch <- 2 + ch <- 3 + trueCases := []struct { + v interface{} + l int + }{ + {[]int{1, 2, 3}, 3}, + {[...]int{1, 2, 3}, 3}, + {"ABC", 3}, + {map[int]int{1: 2, 2: 4, 3: 6}, 3}, + {ch, 3}, + + {[]int{}, 0}, + {map[int]int{}, 0}, + {make(chan int), 0}, + + {[]int(nil), 0}, + {map[int]int(nil), 0}, + {(chan int)(nil), 0}, + } + + for _, c := range trueCases { + ok, l := getLen(c.v) + True(t, ok, "Expected getLen success to get length of %#v", c.v) + Equal(t, c.l, l) + } +} + +func TestLen(t *testing.T) { + mockT := new(testing.T) + + False(t, Len(mockT, nil, 0), "nil does not have length") + False(t, Len(mockT, 0, 0), "int does not have length") + False(t, Len(mockT, true, 0), "true does not have length") + False(t, Len(mockT, false, 0), "false does not have length") + False(t, Len(mockT, 'A', 0), "Rune does not have length") + False(t, Len(mockT, struct{}{}, 0), "Struct does not have length") + + ch := make(chan int, 5) + ch <- 1 + ch <- 2 + ch <- 3 + + cases := []struct { + v interface{} + l int + }{ + {[]int{1, 2, 3}, 3}, + {[...]int{1, 2, 3}, 3}, + {"ABC", 3}, + {map[int]int{1: 2, 2: 4, 3: 6}, 3}, + {ch, 3}, + + {[]int{}, 0}, + {map[int]int{}, 0}, + {make(chan int), 0}, + + {[]int(nil), 0}, + {map[int]int(nil), 0}, + {(chan int)(nil), 0}, + } + + for _, c := range cases { + True(t, Len(mockT, c.v, c.l), "%#v have %d items", c.v, c.l) + } + + cases = []struct { + v interface{} + l int + }{ + {[]int{1, 2, 3}, 4}, + {[...]int{1, 2, 3}, 2}, + {"ABC", 2}, + {map[int]int{1: 2, 2: 4, 3: 6}, 4}, + {ch, 2}, + + {[]int{}, 1}, + {map[int]int{}, 1}, + {make(chan int), 1}, + + {[]int(nil), 1}, + {map[int]int(nil), 1}, + {(chan int)(nil), 1}, + } + + for _, c := range cases { + False(t, Len(mockT, c.v, c.l), "%#v have %d items", c.v, c.l) + } +} + +func TestWithinDuration(t *testing.T) { + + mockT := new(testing.T) + a := time.Now() + b := a.Add(10 * time.Second) + + True(t, WithinDuration(mockT, a, b, 10*time.Second), "A 10s difference is within a 10s time difference") + True(t, WithinDuration(mockT, b, a, 10*time.Second), "A 10s difference is within a 10s time difference") + + False(t, WithinDuration(mockT, a, b, 9*time.Second), "A 10s difference is not within a 9s time difference") + False(t, WithinDuration(mockT, b, a, 9*time.Second), "A 10s difference is not within a 9s time difference") + + False(t, WithinDuration(mockT, a, b, -9*time.Second), "A 10s difference is not within a 9s time difference") + False(t, WithinDuration(mockT, b, a, -9*time.Second), "A 10s difference is not within a 9s time difference") + + False(t, WithinDuration(mockT, a, b, -11*time.Second), "A 10s difference is not within a 9s time difference") + False(t, WithinDuration(mockT, b, a, -11*time.Second), "A 10s difference is not within a 9s time difference") +} + +func TestInDelta(t *testing.T) { + mockT := new(testing.T) + + True(t, InDelta(mockT, 1.001, 1, 0.01), "|1.001 - 1| <= 0.01") + True(t, InDelta(mockT, 1, 1.001, 0.01), "|1 - 1.001| <= 0.01") + True(t, InDelta(mockT, 1, 2, 1), "|1 - 2| <= 1") + False(t, InDelta(mockT, 1, 2, 0.5), "Expected |1 - 2| <= 0.5 to fail") + False(t, InDelta(mockT, 2, 1, 0.5), "Expected |2 - 1| <= 0.5 to fail") + False(t, InDelta(mockT, "", nil, 1), "Expected non numerals to fail") + + cases := []struct { + a, b interface{} + delta float64 + }{ + {uint8(2), uint8(1), 1}, + {uint16(2), uint16(1), 1}, + {uint32(2), uint32(1), 1}, + {uint64(2), uint64(1), 1}, + + {int(2), int(1), 1}, + {int8(2), int8(1), 1}, + {int16(2), int16(1), 1}, + {int32(2), int32(1), 1}, + {int64(2), int64(1), 1}, + + {float32(2), float32(1), 1}, + {float64(2), float64(1), 1}, + } + + for _, tc := range cases { + True(t, InDelta(mockT, tc.a, tc.b, tc.delta), "Expected |%V - %V| <= %v", tc.a, tc.b, tc.delta) + } +} + +func TestInEpsilon(t *testing.T) { + mockT := new(testing.T) + + cases := []struct { + a, b interface{} + epsilon float64 + }{ + {uint8(2), uint16(2), .001}, + {2.1, 2.2, 0.1}, + {2.2, 2.1, 0.1}, + {-2.1, -2.2, 0.1}, + {-2.2, -2.1, 0.1}, + {uint64(100), uint8(101), 0.01}, + {0.1, -0.1, 2}, + } + + for _, tc := range cases { + True(t, InEpsilon(mockT, tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon)) + } + + cases = []struct { + a, b interface{} + epsilon float64 + }{ + {uint8(2), int16(-2), .001}, + {uint64(100), uint8(102), 0.01}, + {2.1, 2.2, 0.001}, + {2.2, 2.1, 0.001}, + {2.1, -2.2, 1}, + {2.1, "bla-bla", 0}, + {0.1, -0.1, 1.99}, + } + + for _, tc := range cases { + False(t, InEpsilon(mockT, tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon)) + } + +} + +func TestRegexp(t *testing.T) { + mockT := new(testing.T) + + cases := []struct { + rx, str string + }{ + {"^start", "start of the line"}, + {"end$", "in the end"}, + {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12.34"}, + } + + for _, tc := range cases { + True(t, Regexp(mockT, tc.rx, tc.str)) + True(t, Regexp(mockT, regexp.MustCompile(tc.rx), tc.str)) + False(t, NotRegexp(mockT, tc.rx, tc.str)) + False(t, NotRegexp(mockT, regexp.MustCompile(tc.rx), tc.str)) + } + + cases = []struct { + rx, str string + }{ + {"^asdfastart", "Not the start of the line"}, + {"end$", "in the end."}, + {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12a.34"}, + } + + for _, tc := range cases { + False(t, Regexp(mockT, tc.rx, tc.str), "Expected \"%s\" to not match \"%s\"", tc.rx, tc.str) + False(t, Regexp(mockT, regexp.MustCompile(tc.rx), tc.str)) + True(t, NotRegexp(mockT, tc.rx, tc.str)) + True(t, NotRegexp(mockT, regexp.MustCompile(tc.rx), tc.str)) + } +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/assert/doc.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/assert/doc.go new file mode 100644 index 000000000..1c6de283d --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/assert/doc.go @@ -0,0 +1,150 @@ +// A set of comprehensive testing tools for use with the normal Go testing system. +// +// Example Usage +// +// The following is a complete example using assert in a standard test function: +// import ( +// "testing" +// "github.com/stretchr/testify/assert" +// ) +// +// func TestSomething(t *testing.T) { +// +// var a string = "Hello" +// var b string = "Hello" +// +// assert.Equal(t, a, b, "The two words should be the same.") +// +// } +// +// if you assert many times, use the below: +// +// import ( +// "testing" +// "github.com/stretchr/testify/assert" +// ) +// +// func TestSomething(t *testing.T) { +// assert := assert.New(t) +// +// var a string = "Hello" +// var b string = "Hello" +// +// assert.Equal(a, b, "The two words should be the same.") +// } +// +// Assertions +// +// Assertions allow you to easily write test code, and are global funcs in the `assert` package. +// All assertion functions take, as the first argument, the `*testing.T` object provided by the +// testing framework. This allows the assertion funcs to write the failings and other details to +// the correct place. +// +// Every assertion function also takes an optional string message as the final argument, +// allowing custom error messages to be appended to the message the assertion method outputs. +// +// Here is an overview of the assert functions: +// +// assert.Equal(t, expected, actual [, message [, format-args]) +// +// assert.NotEqual(t, notExpected, actual [, message [, format-args]]) +// +// assert.True(t, actualBool [, message [, format-args]]) +// +// assert.False(t, actualBool [, message [, format-args]]) +// +// assert.Nil(t, actualObject [, message [, format-args]]) +// +// assert.NotNil(t, actualObject [, message [, format-args]]) +// +// assert.Empty(t, actualObject [, message [, format-args]]) +// +// assert.NotEmpty(t, actualObject [, message [, format-args]]) +// +// assert.Len(t, actualObject, expectedLength, [, message [, format-args]]) +// +// assert.Error(t, errorObject [, message [, format-args]]) +// +// assert.NoError(t, errorObject [, message [, format-args]]) +// +// assert.EqualError(t, theError, errString [, message [, format-args]]) +// +// assert.Implements(t, (*MyInterface)(nil), new(MyObject) [,message [, format-args]]) +// +// assert.IsType(t, expectedObject, actualObject [, message [, format-args]]) +// +// assert.Contains(t, stringOrSlice, substringOrElement [, message [, format-args]]) +// +// assert.NotContains(t, stringOrSlice, substringOrElement [, message [, format-args]]) +// +// assert.Panics(t, func(){ +// +// // call code that should panic +// +// } [, message [, format-args]]) +// +// assert.NotPanics(t, func(){ +// +// // call code that should not panic +// +// } [, message [, format-args]]) +// +// assert.WithinDuration(t, timeA, timeB, deltaTime, [, message [, format-args]]) +// +// assert.InDelta(t, numA, numB, delta, [, message [, format-args]]) +// +// assert.InEpsilon(t, numA, numB, epsilon, [, message [, format-args]]) +// +// assert package contains Assertions object. it has assertion methods. +// +// Here is an overview of the assert functions: +// assert.Equal(expected, actual [, message [, format-args]) +// +// assert.NotEqual(notExpected, actual [, message [, format-args]]) +// +// assert.True(actualBool [, message [, format-args]]) +// +// assert.False(actualBool [, message [, format-args]]) +// +// assert.Nil(actualObject [, message [, format-args]]) +// +// assert.NotNil(actualObject [, message [, format-args]]) +// +// assert.Empty(actualObject [, message [, format-args]]) +// +// assert.NotEmpty(actualObject [, message [, format-args]]) +// +// assert.Len(actualObject, expectedLength, [, message [, format-args]]) +// +// assert.Error(errorObject [, message [, format-args]]) +// +// assert.NoError(errorObject [, message [, format-args]]) +// +// assert.EqualError(theError, errString [, message [, format-args]]) +// +// assert.Implements((*MyInterface)(nil), new(MyObject) [,message [, format-args]]) +// +// assert.IsType(expectedObject, actualObject [, message [, format-args]]) +// +// assert.Contains(stringOrSlice, substringOrElement [, message [, format-args]]) +// +// assert.NotContains(stringOrSlice, substringOrElement [, message [, format-args]]) +// +// assert.Panics(func(){ +// +// // call code that should panic +// +// } [, message [, format-args]]) +// +// assert.NotPanics(func(){ +// +// // call code that should not panic +// +// } [, message [, format-args]]) +// +// assert.WithinDuration(timeA, timeB, deltaTime, [, message [, format-args]]) +// +// assert.InDelta(numA, numB, delta, [, message [, format-args]]) +// +// assert.InEpsilon(numA, numB, epsilon, [, message [, format-args]]) +package assert diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/assert/errors.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/assert/errors.go new file mode 100644 index 000000000..ac9dc9d1d --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/assert/errors.go @@ -0,0 +1,10 @@ +package assert + +import ( + "errors" +) + +// AnError is an error instance useful for testing. If the code does not care +// about error specifics, and only needs to return the error for example, this +// error should be used to make the test code more readable. +var AnError = errors.New("assert.AnError general error for testing") diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions.go new file mode 100644 index 000000000..67a6925a1 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions.go @@ -0,0 +1,262 @@ +package assert + +import "time" + +type Assertions struct { + t TestingT +} + +func New(t TestingT) *Assertions { + return &Assertions{ + t: t, + } +} + +// Fail reports a failure through +func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool { + return Fail(a.t, failureMessage, msgAndArgs...) +} + +// Implements asserts that an object is implemented by the specified interface. +// +// assert.Implements((*MyInterface)(nil), new(MyObject), "MyObject") +func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { + return Implements(a.t, interfaceObject, object, msgAndArgs...) +} + +// IsType asserts that the specified objects are of the same type. +func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { + return IsType(a.t, expectedType, object, msgAndArgs...) +} + +// Equal asserts that two objects are equal. +// +// assert.Equal(123, 123, "123 and 123 should be equal") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) Equal(expected, actual interface{}, msgAndArgs ...interface{}) bool { + return Equal(a.t, expected, actual, msgAndArgs...) +} + +// EqualValues asserts that two objects are equal or convertable to the same types +// and equal. +// +// assert.EqualValues(uint32(123), int32(123), "123 and 123 should be equal") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) EqualValues(expected, actual interface{}, msgAndArgs ...interface{}) bool { + return EqualValues(a.t, expected, actual, msgAndArgs...) +} + +// Exactly asserts that two objects are equal is value and type. +// +// assert.Exactly(int32(123), int64(123), "123 and 123 should NOT be equal") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) Exactly(expected, actual interface{}, msgAndArgs ...interface{}) bool { + return Exactly(a.t, expected, actual, msgAndArgs...) +} + +// NotNil asserts that the specified object is not nil. +// +// assert.NotNil(err, "err should be something") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool { + return NotNil(a.t, object, msgAndArgs...) +} + +// Nil asserts that the specified object is nil. +// +// assert.Nil(err, "err should be nothing") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool { + return Nil(a.t, object, msgAndArgs...) +} + +// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or a +// slice with len == 0. +// +// assert.Empty(obj) +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool { + return Empty(a.t, object, msgAndArgs...) +} + +// Empty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or a +// slice with len == 0. +// +// if assert.NotEmpty(obj) { +// assert.Equal("two", obj[1]) +// } +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool { + return NotEmpty(a.t, object, msgAndArgs...) +} + +// Len asserts that the specified object has specific length. +// Len also fails if the object has a type that len() not accept. +// +// assert.Len(mySlice, 3, "The size of slice is not 3") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool { + return Len(a.t, object, length, msgAndArgs...) +} + +// True asserts that the specified value is true. +// +// assert.True(myBool, "myBool should be true") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool { + return True(a.t, value, msgAndArgs...) +} + +// False asserts that the specified value is true. +// +// assert.False(myBool, "myBool should be false") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool { + return False(a.t, value, msgAndArgs...) +} + +// NotEqual asserts that the specified values are NOT equal. +// +// assert.NotEqual(obj1, obj2, "two objects shouldn't be equal") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) NotEqual(expected, actual interface{}, msgAndArgs ...interface{}) bool { + return NotEqual(a.t, expected, actual, msgAndArgs...) +} + +// Contains asserts that the specified string contains the specified substring. +// +// assert.Contains("Hello World", "World", "But 'Hello World' does contain 'World'") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) Contains(s, contains interface{}, msgAndArgs ...interface{}) bool { + return Contains(a.t, s, contains, msgAndArgs...) +} + +// NotContains asserts that the specified string does NOT contain the specified substring. +// +// assert.NotContains("Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) NotContains(s, contains interface{}, msgAndArgs ...interface{}) bool { + return NotContains(a.t, s, contains, msgAndArgs...) +} + +// Uses a Comparison to assert a complex condition. +func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool { + return Condition(a.t, comp, msgAndArgs...) +} + +// Panics asserts that the code inside the specified PanicTestFunc panics. +// +// assert.Panics(func(){ +// GoCrazy() +// }, "Calling GoCrazy() should panic") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool { + return Panics(a.t, f, msgAndArgs...) +} + +// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// assert.NotPanics(func(){ +// RemainCalm() +// }, "Calling RemainCalm() should NOT panic") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool { + return NotPanics(a.t, f, msgAndArgs...) +} + +// WithinDuration asserts that the two times are within duration delta of each other. +// +// assert.WithinDuration(time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) WithinDuration(expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { + return WithinDuration(a.t, expected, actual, delta, msgAndArgs...) +} + +// InDelta asserts that the two numerals are within delta of each other. +// +// assert.InDelta(t, math.Pi, (22 / 7.0), 0.01) +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) InDelta(expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + return InDelta(a.t, expected, actual, delta, msgAndArgs...) +} + +// InEpsilon asserts that expected and actual have a relative error less than epsilon +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) InEpsilon(expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...) +} + +// NoError asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if assert.NoError(err) { +// assert.Equal(actualObj, expectedObj) +// } +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) NoError(theError error, msgAndArgs ...interface{}) bool { + return NoError(a.t, theError, msgAndArgs...) +} + +// Error asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if assert.Error(err, "An error was expected") { +// assert.Equal(err, expectedError) +// } +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) Error(theError error, msgAndArgs ...interface{}) bool { + return Error(a.t, theError, msgAndArgs...) +} + +// EqualError asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// if assert.Error(err, "An error was expected") { +// assert.Equal(err, expectedError) +// } +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool { + return EqualError(a.t, theError, errString, msgAndArgs...) +} + +// Regexp asserts that a specified regexp matches a string. +// +// assert.Regexp(t, regexp.MustCompile("start"), "it's starting") +// assert.Regexp(t, "start...$", "it's not starting") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + return Regexp(a.t, rx, str, msgAndArgs...) +} + +// NotRegexp asserts that a specified regexp does not match a string. +// +// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") +// assert.NotRegexp(t, "^start", "it's not starting") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + return NotRegexp(a.t, rx, str, msgAndArgs...) +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions_test.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions_test.go new file mode 100644 index 000000000..0dac6c7ae --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions_test.go @@ -0,0 +1,526 @@ +package assert + +import ( + "errors" + "regexp" + "testing" + "time" +) + +func TestImplementsWrapper(t *testing.T) { + assert := New(new(testing.T)) + + if !assert.Implements((*AssertionTesterInterface)(nil), new(AssertionTesterConformingObject)) { + t.Error("Implements method should return true: AssertionTesterConformingObject implements AssertionTesterInterface") + } + if assert.Implements((*AssertionTesterInterface)(nil), new(AssertionTesterNonConformingObject)) { + t.Error("Implements method should return false: AssertionTesterNonConformingObject does not implements AssertionTesterInterface") + } +} + +func TestIsTypeWrapper(t *testing.T) { + assert := New(new(testing.T)) + + if !assert.IsType(new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) { + t.Error("IsType should return true: AssertionTesterConformingObject is the same type as AssertionTesterConformingObject") + } + if assert.IsType(new(AssertionTesterConformingObject), new(AssertionTesterNonConformingObject)) { + t.Error("IsType should return false: AssertionTesterConformingObject is not the same type as AssertionTesterNonConformingObject") + } + +} + +func TestEqualWrapper(t *testing.T) { + assert := New(new(testing.T)) + + if !assert.Equal("Hello World", "Hello World") { + t.Error("Equal should return true") + } + if !assert.Equal(123, 123) { + t.Error("Equal should return true") + } + if !assert.Equal(123.5, 123.5) { + t.Error("Equal should return true") + } + if !assert.Equal([]byte("Hello World"), []byte("Hello World")) { + t.Error("Equal should return true") + } + if !assert.Equal(nil, nil) { + t.Error("Equal should return true") + } +} + +func TestEqualValuesWrapper(t *testing.T) { + assert := New(new(testing.T)) + + if !assert.EqualValues(uint32(10), int32(10)) { + t.Error("EqualValues should return true") + } +} + +func TestNotNilWrapper(t *testing.T) { + assert := New(new(testing.T)) + + if !assert.NotNil(new(AssertionTesterConformingObject)) { + t.Error("NotNil should return true: object is not nil") + } + if assert.NotNil(nil) { + t.Error("NotNil should return false: object is nil") + } + +} + +func TestNilWrapper(t *testing.T) { + assert := New(new(testing.T)) + + if !assert.Nil(nil) { + t.Error("Nil should return true: object is nil") + } + if assert.Nil(new(AssertionTesterConformingObject)) { + t.Error("Nil should return false: object is not nil") + } + +} + +func TestTrueWrapper(t *testing.T) { + assert := New(new(testing.T)) + + if !assert.True(true) { + t.Error("True should return true") + } + if assert.True(false) { + t.Error("True should return false") + } + +} + +func TestFalseWrapper(t *testing.T) { + assert := New(new(testing.T)) + + if !assert.False(false) { + t.Error("False should return true") + } + if assert.False(true) { + t.Error("False should return false") + } + +} + +func TestExactlyWrapper(t *testing.T) { + assert := New(new(testing.T)) + + a := float32(1) + b := float64(1) + c := float32(1) + d := float32(2) + + if assert.Exactly(a, b) { + t.Error("Exactly should return false") + } + if assert.Exactly(a, d) { + t.Error("Exactly should return false") + } + if !assert.Exactly(a, c) { + t.Error("Exactly should return true") + } + + if assert.Exactly(nil, a) { + t.Error("Exactly should return false") + } + if assert.Exactly(a, nil) { + t.Error("Exactly should return false") + } + +} + +func TestNotEqualWrapper(t *testing.T) { + + assert := New(new(testing.T)) + + if !assert.NotEqual("Hello World", "Hello World!") { + t.Error("NotEqual should return true") + } + if !assert.NotEqual(123, 1234) { + t.Error("NotEqual should return true") + } + if !assert.NotEqual(123.5, 123.55) { + t.Error("NotEqual should return true") + } + if !assert.NotEqual([]byte("Hello World"), []byte("Hello World!")) { + t.Error("NotEqual should return true") + } + if !assert.NotEqual(nil, new(AssertionTesterConformingObject)) { + t.Error("NotEqual should return true") + } +} + +func TestContainsWrapper(t *testing.T) { + + assert := New(new(testing.T)) + list := []string{"Foo", "Bar"} + + if !assert.Contains("Hello World", "Hello") { + t.Error("Contains should return true: \"Hello World\" contains \"Hello\"") + } + if assert.Contains("Hello World", "Salut") { + t.Error("Contains should return false: \"Hello World\" does not contain \"Salut\"") + } + + if !assert.Contains(list, "Foo") { + t.Error("Contains should return true: \"[\"Foo\", \"Bar\"]\" contains \"Foo\"") + } + if assert.Contains(list, "Salut") { + t.Error("Contains should return false: \"[\"Foo\", \"Bar\"]\" does not contain \"Salut\"") + } + +} + +func TestNotContainsWrapper(t *testing.T) { + + assert := New(new(testing.T)) + list := []string{"Foo", "Bar"} + + if !assert.NotContains("Hello World", "Hello!") { + t.Error("NotContains should return true: \"Hello World\" does not contain \"Hello!\"") + } + if assert.NotContains("Hello World", "Hello") { + t.Error("NotContains should return false: \"Hello World\" contains \"Hello\"") + } + + if !assert.NotContains(list, "Foo!") { + t.Error("NotContains should return true: \"[\"Foo\", \"Bar\"]\" does not contain \"Foo!\"") + } + if assert.NotContains(list, "Foo") { + t.Error("NotContains should return false: \"[\"Foo\", \"Bar\"]\" contains \"Foo\"") + } + +} + +func TestConditionWrapper(t *testing.T) { + + assert := New(new(testing.T)) + + if !assert.Condition(func() bool { return true }, "Truth") { + t.Error("Condition should return true") + } + + if assert.Condition(func() bool { return false }, "Lie") { + t.Error("Condition should return false") + } + +} + +func TestDidPanicWrapper(t *testing.T) { + + if funcDidPanic, _ := didPanic(func() { + panic("Panic!") + }); !funcDidPanic { + t.Error("didPanic should return true") + } + + if funcDidPanic, _ := didPanic(func() { + }); funcDidPanic { + t.Error("didPanic should return false") + } + +} + +func TestPanicsWrapper(t *testing.T) { + + assert := New(new(testing.T)) + + if !assert.Panics(func() { + panic("Panic!") + }) { + t.Error("Panics should return true") + } + + if assert.Panics(func() { + }) { + t.Error("Panics should return false") + } + +} + +func TestNotPanicsWrapper(t *testing.T) { + + assert := New(new(testing.T)) + + if !assert.NotPanics(func() { + }) { + t.Error("NotPanics should return true") + } + + if assert.NotPanics(func() { + panic("Panic!") + }) { + t.Error("NotPanics should return false") + } + +} + +func TestEqualWrapper_Funcs(t *testing.T) { + + assert := New(t) + + type f func() int + var f1 f = func() int { return 1 } + var f2 f = func() int { return 2 } + + var f1_copy f = f1 + + assert.Equal(f1_copy, f1, "Funcs are the same and should be considered equal") + assert.NotEqual(f1, f2, "f1 and f2 are different") + +} + +func TestNoErrorWrapper(t *testing.T) { + assert := New(t) + mockAssert := New(new(testing.T)) + + // start with a nil error + var err error = nil + + assert.True(mockAssert.NoError(err), "NoError should return True for nil arg") + + // now set an error + err = errors.New("Some error") + + assert.False(mockAssert.NoError(err), "NoError with error should return False") + +} + +func TestErrorWrapper(t *testing.T) { + assert := New(t) + mockAssert := New(new(testing.T)) + + // start with a nil error + var err error = nil + + assert.False(mockAssert.Error(err), "Error should return False for nil arg") + + // now set an error + err = errors.New("Some error") + + assert.True(mockAssert.Error(err), "Error with error should return True") + +} + +func TestEqualErrorWrapper(t *testing.T) { + assert := New(t) + mockAssert := New(new(testing.T)) + + // start with a nil error + var err error + assert.False(mockAssert.EqualError(err, ""), + "EqualError should return false for nil arg") + + // now set an error + err = errors.New("some error") + assert.False(mockAssert.EqualError(err, "Not some error"), + "EqualError should return false for different error string") + assert.True(mockAssert.EqualError(err, "some error"), + "EqualError should return true") +} + +func TestEmptyWrapper(t *testing.T) { + assert := New(t) + mockAssert := New(new(testing.T)) + + assert.True(mockAssert.Empty(""), "Empty string is empty") + assert.True(mockAssert.Empty(nil), "Nil is empty") + assert.True(mockAssert.Empty([]string{}), "Empty string array is empty") + assert.True(mockAssert.Empty(0), "Zero int value is empty") + assert.True(mockAssert.Empty(false), "False value is empty") + + assert.False(mockAssert.Empty("something"), "Non Empty string is not empty") + assert.False(mockAssert.Empty(errors.New("something")), "Non nil object is not empty") + assert.False(mockAssert.Empty([]string{"something"}), "Non empty string array is not empty") + assert.False(mockAssert.Empty(1), "Non-zero int value is not empty") + assert.False(mockAssert.Empty(true), "True value is not empty") + +} + +func TestNotEmptyWrapper(t *testing.T) { + assert := New(t) + mockAssert := New(new(testing.T)) + + assert.False(mockAssert.NotEmpty(""), "Empty string is empty") + assert.False(mockAssert.NotEmpty(nil), "Nil is empty") + assert.False(mockAssert.NotEmpty([]string{}), "Empty string array is empty") + assert.False(mockAssert.NotEmpty(0), "Zero int value is empty") + assert.False(mockAssert.NotEmpty(false), "False value is empty") + + assert.True(mockAssert.NotEmpty("something"), "Non Empty string is not empty") + assert.True(mockAssert.NotEmpty(errors.New("something")), "Non nil object is not empty") + assert.True(mockAssert.NotEmpty([]string{"something"}), "Non empty string array is not empty") + assert.True(mockAssert.NotEmpty(1), "Non-zero int value is not empty") + assert.True(mockAssert.NotEmpty(true), "True value is not empty") + +} + +func TestLenWrapper(t *testing.T) { + assert := New(t) + mockAssert := New(new(testing.T)) + + assert.False(mockAssert.Len(nil, 0), "nil does not have length") + assert.False(mockAssert.Len(0, 0), "int does not have length") + assert.False(mockAssert.Len(true, 0), "true does not have length") + assert.False(mockAssert.Len(false, 0), "false does not have length") + assert.False(mockAssert.Len('A', 0), "Rune does not have length") + assert.False(mockAssert.Len(struct{}{}, 0), "Struct does not have length") + + ch := make(chan int, 5) + ch <- 1 + ch <- 2 + ch <- 3 + + cases := []struct { + v interface{} + l int + }{ + {[]int{1, 2, 3}, 3}, + {[...]int{1, 2, 3}, 3}, + {"ABC", 3}, + {map[int]int{1: 2, 2: 4, 3: 6}, 3}, + {ch, 3}, + + {[]int{}, 0}, + {map[int]int{}, 0}, + {make(chan int), 0}, + + {[]int(nil), 0}, + {map[int]int(nil), 0}, + {(chan int)(nil), 0}, + } + + for _, c := range cases { + assert.True(mockAssert.Len(c.v, c.l), "%#v have %d items", c.v, c.l) + } +} + +func TestWithinDurationWrapper(t *testing.T) { + assert := New(t) + mockAssert := New(new(testing.T)) + a := time.Now() + b := a.Add(10 * time.Second) + + assert.True(mockAssert.WithinDuration(a, b, 10*time.Second), "A 10s difference is within a 10s time difference") + assert.True(mockAssert.WithinDuration(b, a, 10*time.Second), "A 10s difference is within a 10s time difference") + + assert.False(mockAssert.WithinDuration(a, b, 9*time.Second), "A 10s difference is not within a 9s time difference") + assert.False(mockAssert.WithinDuration(b, a, 9*time.Second), "A 10s difference is not within a 9s time difference") + + assert.False(mockAssert.WithinDuration(a, b, -9*time.Second), "A 10s difference is not within a 9s time difference") + assert.False(mockAssert.WithinDuration(b, a, -9*time.Second), "A 10s difference is not within a 9s time difference") + + assert.False(mockAssert.WithinDuration(a, b, -11*time.Second), "A 10s difference is not within a 9s time difference") + assert.False(mockAssert.WithinDuration(b, a, -11*time.Second), "A 10s difference is not within a 9s time difference") +} + +func TestInDeltaWrapper(t *testing.T) { + assert := New(new(testing.T)) + + True(t, assert.InDelta(1.001, 1, 0.01), "|1.001 - 1| <= 0.01") + True(t, assert.InDelta(1, 1.001, 0.01), "|1 - 1.001| <= 0.01") + True(t, assert.InDelta(1, 2, 1), "|1 - 2| <= 1") + False(t, assert.InDelta(1, 2, 0.5), "Expected |1 - 2| <= 0.5 to fail") + False(t, assert.InDelta(2, 1, 0.5), "Expected |2 - 1| <= 0.5 to fail") + False(t, assert.InDelta("", nil, 1), "Expected non numerals to fail") + + cases := []struct { + a, b interface{} + delta float64 + }{ + {uint8(2), uint8(1), 1}, + {uint16(2), uint16(1), 1}, + {uint32(2), uint32(1), 1}, + {uint64(2), uint64(1), 1}, + + {int(2), int(1), 1}, + {int8(2), int8(1), 1}, + {int16(2), int16(1), 1}, + {int32(2), int32(1), 1}, + {int64(2), int64(1), 1}, + + {float32(2), float32(1), 1}, + {float64(2), float64(1), 1}, + } + + for _, tc := range cases { + True(t, assert.InDelta(tc.a, tc.b, tc.delta), "Expected |%V - %V| <= %v", tc.a, tc.b, tc.delta) + } +} + +func TestInEpsilonWrapper(t *testing.T) { + assert := New(new(testing.T)) + + cases := []struct { + a, b interface{} + epsilon float64 + }{ + {uint8(2), uint16(2), .001}, + {2.1, 2.2, 0.1}, + {2.2, 2.1, 0.1}, + {-2.1, -2.2, 0.1}, + {-2.2, -2.1, 0.1}, + {uint64(100), uint8(101), 0.01}, + {0.1, -0.1, 2}, + } + + for _, tc := range cases { + True(t, assert.InEpsilon(tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon)) + } + + cases = []struct { + a, b interface{} + epsilon float64 + }{ + {uint8(2), int16(-2), .001}, + {uint64(100), uint8(102), 0.01}, + {2.1, 2.2, 0.001}, + {2.2, 2.1, 0.001}, + {2.1, -2.2, 1}, + {2.1, "bla-bla", 0}, + {0.1, -0.1, 1.99}, + } + + for _, tc := range cases { + False(t, assert.InEpsilon(tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon)) + } +} + +func TestRegexpWrapper(t *testing.T) { + + assert := New(new(testing.T)) + + cases := []struct { + rx, str string + }{ + {"^start", "start of the line"}, + {"end$", "in the end"}, + {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12.34"}, + } + + for _, tc := range cases { + True(t, assert.Regexp(tc.rx, tc.str)) + True(t, assert.Regexp(regexp.MustCompile(tc.rx), tc.str)) + False(t, assert.NotRegexp(tc.rx, tc.str)) + False(t, assert.NotRegexp(regexp.MustCompile(tc.rx), tc.str)) + } + + cases = []struct { + rx, str string + }{ + {"^asdfastart", "Not the start of the line"}, + {"end$", "in the end."}, + {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12a.34"}, + } + + for _, tc := range cases { + False(t, assert.Regexp(tc.rx, tc.str), "Expected \"%s\" to not match \"%s\"", tc.rx, tc.str) + False(t, assert.Regexp(regexp.MustCompile(tc.rx), tc.str)) + True(t, assert.NotRegexp(tc.rx, tc.str)) + True(t, assert.NotRegexp(regexp.MustCompile(tc.rx), tc.str)) + } +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions.go new file mode 100644 index 000000000..0419c1b60 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions.go @@ -0,0 +1,157 @@ +package assert + +import ( + "fmt" + "net/http" + "net/http/httptest" + "net/url" + "strings" +) + +// httpCode is a helper that returns HTTP code of the response. It returns -1 +// if building a new request fails. +func httpCode(handler http.HandlerFunc, mode, url string, values url.Values) int { + w := httptest.NewRecorder() + req, err := http.NewRequest(mode, url+"?"+values.Encode(), nil) + if err != nil { + return -1 + } + handler(w, req) + return w.Code +} + +// HTTPSuccess asserts that a specified handler returns a success status code. +// +// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil) +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPSuccess(t TestingT, handler http.HandlerFunc, mode, url string, values url.Values) bool { + code := httpCode(handler, mode, url, values) + if code == -1 { + return false + } + return code >= http.StatusOK && code <= http.StatusPartialContent +} + +// HTTPRedirect asserts that a specified handler returns a redirect status code. +// +// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPRedirect(t TestingT, handler http.HandlerFunc, mode, url string, values url.Values) bool { + code := httpCode(handler, mode, url, values) + if code == -1 { + return false + } + return code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect +} + +// HTTPError asserts that a specified handler returns an error status code. +// +// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPError(t TestingT, handler http.HandlerFunc, mode, url string, values url.Values) bool { + code := httpCode(handler, mode, url, values) + if code == -1 { + return false + } + return code >= http.StatusBadRequest +} + +// HttpBody is a helper that returns HTTP body of the response. It returns +// empty string if building a new request fails. +func HttpBody(handler http.HandlerFunc, mode, url string, values url.Values) string { + w := httptest.NewRecorder() + req, err := http.NewRequest(mode, url+"?"+values.Encode(), nil) + if err != nil { + return "" + } + handler(w, req) + return w.Body.String() +} + +// HTTPBodyContains asserts that a specified handler returns a +// body that contains a string. +// +// assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyContains(t TestingT, handler http.HandlerFunc, mode, url string, values url.Values, str interface{}) bool { + body := HttpBody(handler, mode, url, values) + + contains := strings.Contains(body, fmt.Sprint(str)) + if !contains { + Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) + } + + return contains +} + +// HTTPBodyNotContains asserts that a specified handler returns a +// body that does not contain a string. +// +// assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, mode, url string, values url.Values, str interface{}) bool { + body := HttpBody(handler, mode, url, values) + + contains := strings.Contains(body, fmt.Sprint(str)) + if contains { + Fail(t, "Expected response body for %s to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body) + } + + return !contains +} + +// +// Assertions Wrappers +// + +// HTTPSuccess asserts that a specified handler returns a success status code. +// +// assert.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil) +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, mode, url string, values url.Values) bool { + return HTTPSuccess(a.t, handler, mode, url, values) +} + +// HTTPRedirect asserts that a specified handler returns a redirect status code. +// +// assert.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, mode, url string, values url.Values) bool { + return HTTPRedirect(a.t, handler, mode, url, values) +} + +// HTTPError asserts that a specified handler returns an error status code. +// +// assert.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPError(handler http.HandlerFunc, mode, url string, values url.Values) bool { + return HTTPError(a.t, handler, mode, url, values) +} + +// HTTPBodyContains asserts that a specified handler returns a +// body that contains a string. +// +// assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, mode, url string, values url.Values, str interface{}) bool { + return HTTPBodyContains(a.t, handler, mode, url, values, str) +} + +// HTTPBodyNotContains asserts that a specified handler returns a +// body that does not contain a string. +// +// assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, mode, url string, values url.Values, str interface{}) bool { + return HTTPBodyNotContains(a.t, handler, mode, url, values, str) +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions_test.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions_test.go new file mode 100644 index 000000000..684c2d5d1 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions_test.go @@ -0,0 +1,86 @@ +package assert + +import ( + "fmt" + "net/http" + "net/url" + "testing" +) + +func httpOK(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) +} + +func httpRedirect(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusTemporaryRedirect) +} + +func httpError(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusInternalServerError) +} + +func TestHTTPStatuses(t *testing.T) { + assert := New(t) + mockT := new(testing.T) + + assert.Equal(HTTPSuccess(mockT, httpOK, "GET", "/", nil), true) + assert.Equal(HTTPSuccess(mockT, httpRedirect, "GET", "/", nil), false) + assert.Equal(HTTPSuccess(mockT, httpError, "GET", "/", nil), false) + + assert.Equal(HTTPRedirect(mockT, httpOK, "GET", "/", nil), false) + assert.Equal(HTTPRedirect(mockT, httpRedirect, "GET", "/", nil), true) + assert.Equal(HTTPRedirect(mockT, httpError, "GET", "/", nil), false) + + assert.Equal(HTTPError(mockT, httpOK, "GET", "/", nil), false) + assert.Equal(HTTPError(mockT, httpRedirect, "GET", "/", nil), false) + assert.Equal(HTTPError(mockT, httpError, "GET", "/", nil), true) +} + +func TestHTTPStatusesWrapper(t *testing.T) { + assert := New(t) + mockAssert := New(new(testing.T)) + + assert.Equal(mockAssert.HTTPSuccess(httpOK, "GET", "/", nil), true) + assert.Equal(mockAssert.HTTPSuccess(httpRedirect, "GET", "/", nil), false) + assert.Equal(mockAssert.HTTPSuccess(httpError, "GET", "/", nil), false) + + assert.Equal(mockAssert.HTTPRedirect(httpOK, "GET", "/", nil), false) + assert.Equal(mockAssert.HTTPRedirect(httpRedirect, "GET", "/", nil), true) + assert.Equal(mockAssert.HTTPRedirect(httpError, "GET", "/", nil), false) + + assert.Equal(mockAssert.HTTPError(httpOK, "GET", "/", nil), false) + assert.Equal(mockAssert.HTTPError(httpRedirect, "GET", "/", nil), false) + assert.Equal(mockAssert.HTTPError(httpError, "GET", "/", nil), true) +} + +func httpHelloName(w http.ResponseWriter, r *http.Request) { + name := r.FormValue("name") + w.Write([]byte(fmt.Sprintf("Hello, %s!", name))) +} + +func TestHttpBody(t *testing.T) { + assert := New(t) + mockT := new(testing.T) + + assert.True(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!")) + assert.True(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World")) + assert.False(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world")) + + assert.False(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!")) + assert.False(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World")) + assert.True(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world")) +} + +func TestHttpBodyWrappers(t *testing.T) { + assert := New(t) + mockAssert := New(new(testing.T)) + + assert.True(mockAssert.HTTPBodyContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!")) + assert.True(mockAssert.HTTPBodyContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World")) + assert.False(mockAssert.HTTPBodyContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world")) + + assert.False(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!")) + assert.False(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World")) + assert.True(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world")) + +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/mock/doc.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/mock/doc.go new file mode 100644 index 000000000..dd385074b --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/mock/doc.go @@ -0,0 +1,43 @@ +// Provides a system by which it is possible to mock your objects and verify calls are happening as expected. +// +// Example Usage +// +// The mock package provides an object, Mock, that tracks activity on another object. It is usually +// embedded into a test object as shown below: +// +// type MyTestObject struct { +// // add a Mock object instance +// mock.Mock +// +// // other fields go here as normal +// } +// +// When implementing the methods of an interface, you wire your functions up +// to call the Mock.Called(args...) method, and return the appropriate values. +// +// For example, to mock a method that saves the name and age of a person and returns +// the year of their birth or an error, you might write this: +// +// func (o *MyTestObject) SavePersonDetails(firstname, lastname string, age int) (int, error) { +// args := o.Called(firstname, lastname, age) +// return args.Int(0), args.Error(1) +// } +// +// The Int, Error and Bool methods are examples of strongly typed getters that take the argument +// index position. Given this argument list: +// +// (12, true, "Something") +// +// You could read them out strongly typed like this: +// +// args.Int(0) +// args.Bool(1) +// args.String(2) +// +// For objects of your own type, use the generic Arguments.Get(index) method and make a type assertion: +// +// return args.Get(0).(*MyObject), args.Get(1).(*AnotherObjectOfMine) +// +// This may cause a panic if the object you are getting is nil (the type assertion will fail), in those +// cases you should check for nil first. +package mock diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock.go new file mode 100644 index 000000000..f73fa2516 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock.go @@ -0,0 +1,510 @@ +package mock + +import ( + "fmt" + "github.com/stretchr/objx" + "github.com/stretchr/testify/assert" + "reflect" + "runtime" + "strings" + "sync" +) + +// TestingT is an interface wrapper around *testing.T +type TestingT interface { + Logf(format string, args ...interface{}) + Errorf(format string, args ...interface{}) +} + +/* + Call +*/ + +// Call represents a method call and is used for setting expectations, +// as well as recording activity. +type Call struct { + + // The name of the method that was or will be called. + Method string + + // Holds the arguments of the method. + Arguments Arguments + + // Holds the arguments that should be returned when + // this method is called. + ReturnArguments Arguments + + // The number of times to return the return arguments when setting + // expectations. 0 means to always return the value. + Repeatability int +} + +// Mock is the workhorse used to track activity on another object. +// For an example of its usage, refer to the "Example Usage" section at the top of this document. +type Mock struct { + + // The method name that is currently + // being referred to by the On method. + onMethodName string + + // An array of the arguments that are + // currently being referred to by the On method. + onMethodArguments Arguments + + // Represents the calls that are expected of + // an object. + ExpectedCalls []Call + + // Holds the calls that were made to this mocked object. + Calls []Call + + // TestData holds any data that might be useful for testing. Testify ignores + // this data completely allowing you to do whatever you like with it. + testData objx.Map + + mutex sync.Mutex +} + +// TestData holds any data that might be useful for testing. Testify ignores +// this data completely allowing you to do whatever you like with it. +func (m *Mock) TestData() objx.Map { + + if m.testData == nil { + m.testData = make(objx.Map) + } + + return m.testData +} + +/* + Setting expectations +*/ + +// On starts a description of an expectation of the specified method +// being called. +// +// Mock.On("MyMethod", arg1, arg2) +func (m *Mock) On(methodName string, arguments ...interface{}) *Mock { + m.onMethodName = methodName + m.onMethodArguments = arguments + return m +} + +// Return finishes a description of an expectation of the method (and arguments) +// specified in the most recent On method call. +// +// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2) +func (m *Mock) Return(returnArguments ...interface{}) *Mock { + m.ExpectedCalls = append(m.ExpectedCalls, Call{m.onMethodName, m.onMethodArguments, returnArguments, 0}) + return m +} + +// Once indicates that that the mock should only return the value once. +// +// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Once() +func (m *Mock) Once() { + m.ExpectedCalls[len(m.ExpectedCalls)-1].Repeatability = 1 +} + +// Twice indicates that that the mock should only return the value twice. +// +// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Twice() +func (m *Mock) Twice() { + m.ExpectedCalls[len(m.ExpectedCalls)-1].Repeatability = 2 +} + +// Times indicates that that the mock should only return the indicated number +// of times. +// +// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Times(5) +func (m *Mock) Times(i int) { + m.ExpectedCalls[len(m.ExpectedCalls)-1].Repeatability = i +} + +/* + Recording and responding to activity +*/ + +func (m *Mock) findExpectedCall(method string, arguments ...interface{}) (int, *Call) { + for i, call := range m.ExpectedCalls { + if call.Method == method && call.Repeatability > -1 { + + _, diffCount := call.Arguments.Diff(arguments) + if diffCount == 0 { + return i, &call + } + + } + } + return -1, nil +} + +func (m *Mock) findClosestCall(method string, arguments ...interface{}) (bool, *Call) { + + diffCount := 0 + var closestCall *Call = nil + + for _, call := range m.ExpectedCalls { + if call.Method == method { + + _, tempDiffCount := call.Arguments.Diff(arguments) + if tempDiffCount < diffCount || diffCount == 0 { + diffCount = tempDiffCount + closestCall = &call + } + + } + } + + if closestCall == nil { + return false, nil + } + + return true, closestCall +} + +func callString(method string, arguments Arguments, includeArgumentValues bool) string { + + var argValsString string = "" + if includeArgumentValues { + var argVals []string + for argIndex, arg := range arguments { + argVals = append(argVals, fmt.Sprintf("%d: %v", argIndex, arg)) + } + argValsString = fmt.Sprintf("\n\t\t%s", strings.Join(argVals, "\n\t\t")) + } + + return fmt.Sprintf("%s(%s)%s", method, arguments.String(), argValsString) +} + +// Called tells the mock object that a method has been called, and gets an array +// of arguments to return. Panics if the call is unexpected (i.e. not preceeded by +// appropriate .On .Return() calls) +func (m *Mock) Called(arguments ...interface{}) Arguments { + defer m.mutex.Unlock() + m.mutex.Lock() + + // get the calling function's name + pc, _, _, ok := runtime.Caller(1) + if !ok { + panic("Couldn't get the caller information") + } + functionPath := runtime.FuncForPC(pc).Name() + parts := strings.Split(functionPath, ".") + functionName := parts[len(parts)-1] + + found, call := m.findExpectedCall(functionName, arguments...) + + switch { + case found < 0: + // we have to fail here - because we don't know what to do + // as the return arguments. This is because: + // + // a) this is a totally unexpected call to this method, + // b) the arguments are not what was expected, or + // c) the developer has forgotten to add an accompanying On...Return pair. + + closestFound, closestCall := m.findClosestCall(functionName, arguments...) + + if closestFound { + panic(fmt.Sprintf("\n\nmock: Unexpected Method Call\n-----------------------------\n\n%s\n\nThe closest call I have is: \n\n%s\n", callString(functionName, arguments, true), callString(functionName, closestCall.Arguments, true))) + } else { + panic(fmt.Sprintf("\nassert: mock: I don't know what to return because the method call was unexpected.\n\tEither do Mock.On(\"%s\").Return(...) first, or remove the %s() call.\n\tThis method was unexpected:\n\t\t%s\n\tat: %s", functionName, functionName, callString(functionName, arguments, true), assert.CallerInfo())) + } + case call.Repeatability == 1: + call.Repeatability = -1 + m.ExpectedCalls[found] = *call + case call.Repeatability > 1: + call.Repeatability -= 1 + m.ExpectedCalls[found] = *call + } + + // add the call + m.Calls = append(m.Calls, Call{functionName, arguments, make([]interface{}, 0), 0}) + + return call.ReturnArguments + +} + +/* + Assertions +*/ + +// AssertExpectationsForObjects asserts that everything specified with On and Return +// of the specified objects was in fact called as expected. +// +// Calls may have occurred in any order. +func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool { + var success bool = true + for _, obj := range testObjects { + mockObj := obj.(Mock) + success = success && mockObj.AssertExpectations(t) + } + return success +} + +// AssertExpectations asserts that everything specified with On and Return was +// in fact called as expected. Calls may have occurred in any order. +func (m *Mock) AssertExpectations(t TestingT) bool { + + var somethingMissing bool = false + var failedExpectations int = 0 + + // iterate through each expectation + for _, expectedCall := range m.ExpectedCalls { + switch { + case !m.methodWasCalled(expectedCall.Method, expectedCall.Arguments): + somethingMissing = true + failedExpectations++ + t.Logf("\u274C\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String()) + case expectedCall.Repeatability > 0: + somethingMissing = true + failedExpectations++ + default: + t.Logf("\u2705\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String()) + } + } + + if somethingMissing { + t.Errorf("FAIL: %d out of %d expectation(s) were met.\n\tThe code you are testing needs to make %d more call(s).\n\tat: %s", len(m.ExpectedCalls)-failedExpectations, len(m.ExpectedCalls), failedExpectations, assert.CallerInfo()) + } + + return !somethingMissing +} + +// AssertNumberOfCalls asserts that the method was called expectedCalls times. +func (m *Mock) AssertNumberOfCalls(t TestingT, methodName string, expectedCalls int) bool { + var actualCalls int = 0 + for _, call := range m.Calls { + if call.Method == methodName { + actualCalls++ + } + } + return assert.Equal(t, actualCalls, expectedCalls, fmt.Sprintf("Expected number of calls (%d) does not match the actual number of calls (%d).", expectedCalls, actualCalls)) +} + +// AssertCalled asserts that the method was called. +func (m *Mock) AssertCalled(t TestingT, methodName string, arguments ...interface{}) bool { + if !assert.True(t, m.methodWasCalled(methodName, arguments), fmt.Sprintf("The \"%s\" method should have been called with %d argument(s), but was not.", methodName, len(arguments))) { + t.Logf("%s", m.ExpectedCalls) + return false + } + return true +} + +// AssertNotCalled asserts that the method was not called. +func (m *Mock) AssertNotCalled(t TestingT, methodName string, arguments ...interface{}) bool { + if !assert.False(t, m.methodWasCalled(methodName, arguments), fmt.Sprintf("The \"%s\" method was called with %d argument(s), but should NOT have been.", methodName, len(arguments))) { + t.Logf("%s", m.ExpectedCalls) + return false + } + return true +} + +func (m *Mock) methodWasCalled(methodName string, expected []interface{}) bool { + for _, call := range m.Calls { + if call.Method == methodName { + + _, differences := Arguments(expected).Diff(call.Arguments) + + if differences == 0 { + // found the expected call + return true + } + + } + } + // we didn't find the expected call + return false +} + +/* + Arguments +*/ + +// Arguments holds an array of method arguments or return values. +type Arguments []interface{} + +const ( + // The "any" argument. Used in Diff and Assert when + // the argument being tested shouldn't be taken into consideration. + Anything string = "mock.Anything" +) + +// AnythingOfTypeArgument is a string that contains the type of an argument +// for use when type checking. Used in Diff and Assert. +type AnythingOfTypeArgument string + +// AnythingOfType returns an AnythingOfTypeArgument object containing the +// name of the type to check for. Used in Diff and Assert. +// +// For example: +// Assert(t, AnythingOfType("string"), AnythingOfType("int")) +func AnythingOfType(t string) AnythingOfTypeArgument { + return AnythingOfTypeArgument(t) +} + +// Get Returns the argument at the specified index. +func (args Arguments) Get(index int) interface{} { + if index+1 > len(args) { + panic(fmt.Sprintf("assert: arguments: Cannot call Get(%d) because there are %d argument(s).", index, len(args))) + } + return args[index] +} + +// Is gets whether the objects match the arguments specified. +func (args Arguments) Is(objects ...interface{}) bool { + for i, obj := range args { + if obj != objects[i] { + return false + } + } + return true +} + +// Diff gets a string describing the differences between the arguments +// and the specified objects. +// +// Returns the diff string and number of differences found. +func (args Arguments) Diff(objects []interface{}) (string, int) { + + var output string = "\n" + var differences int + + var maxArgCount int = len(args) + if len(objects) > maxArgCount { + maxArgCount = len(objects) + } + + for i := 0; i < maxArgCount; i++ { + var actual, expected interface{} + + if len(objects) <= i { + actual = "(Missing)" + } else { + actual = objects[i] + } + + if len(args) <= i { + expected = "(Missing)" + } else { + expected = args[i] + } + + if reflect.TypeOf(expected) == reflect.TypeOf((*AnythingOfTypeArgument)(nil)).Elem() { + + // type checking + if reflect.TypeOf(actual).Name() != string(expected.(AnythingOfTypeArgument)) && reflect.TypeOf(actual).String() != string(expected.(AnythingOfTypeArgument)) { + // not match + differences++ + output = fmt.Sprintf("%s\t%d: \u274C type %s != type %s - %s\n", output, i, expected, reflect.TypeOf(actual).Name(), actual) + } + + } else { + + // normal checking + + if assert.ObjectsAreEqual(expected, Anything) || assert.ObjectsAreEqual(actual, Anything) || assert.ObjectsAreEqual(actual, expected) { + // match + output = fmt.Sprintf("%s\t%d: \u2705 %s == %s\n", output, i, actual, expected) + } else { + // not match + differences++ + output = fmt.Sprintf("%s\t%d: \u274C %s != %s\n", output, i, actual, expected) + } + } + + } + + if differences == 0 { + return "No differences.", differences + } + + return output, differences + +} + +// Assert compares the arguments with the specified objects and fails if +// they do not exactly match. +func (args Arguments) Assert(t TestingT, objects ...interface{}) bool { + + // get the differences + diff, diffCount := args.Diff(objects) + + if diffCount == 0 { + return true + } + + // there are differences... report them... + t.Logf(diff) + t.Errorf("%sArguments do not match.", assert.CallerInfo()) + + return false + +} + +// String gets the argument at the specified index. Panics if there is no argument, or +// if the argument is of the wrong type. +// +// If no index is provided, String() returns a complete string representation +// of the arguments. +func (args Arguments) String(indexOrNil ...int) string { + + if len(indexOrNil) == 0 { + // normal String() method - return a string representation of the args + var argsStr []string + for _, arg := range args { + argsStr = append(argsStr, fmt.Sprintf("%s", reflect.TypeOf(arg))) + } + return strings.Join(argsStr, ",") + } else if len(indexOrNil) == 1 { + // Index has been specified - get the argument at that index + var index int = indexOrNil[0] + var s string + var ok bool + if s, ok = args.Get(index).(string); !ok { + panic(fmt.Sprintf("assert: arguments: String(%d) failed because object wasn't correct type: %s", index, args.Get(index))) + } + return s + } + + panic(fmt.Sprintf("assert: arguments: Wrong number of arguments passed to String. Must be 0 or 1, not %d", len(indexOrNil))) + +} + +// Int gets the argument at the specified index. Panics if there is no argument, or +// if the argument is of the wrong type. +func (args Arguments) Int(index int) int { + var s int + var ok bool + if s, ok = args.Get(index).(int); !ok { + panic(fmt.Sprintf("assert: arguments: Int(%d) failed because object wasn't correct type: %v", index, args.Get(index))) + } + return s +} + +// Error gets the argument at the specified index. Panics if there is no argument, or +// if the argument is of the wrong type. +func (args Arguments) Error(index int) error { + obj := args.Get(index) + var s error + var ok bool + if obj == nil { + return nil + } + if s, ok = obj.(error); !ok { + panic(fmt.Sprintf("assert: arguments: Error(%d) failed because object wasn't correct type: %v", index, args.Get(index))) + } + return s +} + +// Bool gets the argument at the specified index. Panics if there is no argument, or +// if the argument is of the wrong type. +func (args Arguments) Bool(index int) bool { + var s bool + var ok bool + if s, ok = args.Get(index).(bool); !ok { + panic(fmt.Sprintf("assert: arguments: Bool(%d) failed because object wasn't correct type: %v", index, args.Get(index))) + } + return s +} diff --git a/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock_test.go b/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock_test.go new file mode 100644 index 000000000..a4457e071 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/github.com/stretchr/testify/mock/mock_test.go @@ -0,0 +1,669 @@ +package mock + +import ( + "errors" + "github.com/stretchr/testify/assert" + "testing" +) + +/* + Test objects +*/ + +// ExampleInterface represents an example interface. +type ExampleInterface interface { + TheExampleMethod(a, b, c int) (int, error) +} + +// TestExampleImplementation is a test implementation of ExampleInterface +type TestExampleImplementation struct { + Mock +} + +func (i *TestExampleImplementation) TheExampleMethod(a, b, c int) (int, error) { + args := i.Called(a, b, c) + return args.Int(0), errors.New("Whoops") +} + +func (i *TestExampleImplementation) TheExampleMethod2(yesorno bool) { + i.Called(yesorno) +} + +type ExampleType struct{} + +func (i *TestExampleImplementation) TheExampleMethod3(et *ExampleType) error { + args := i.Called(et) + return args.Error(0) +} + +/* + Mock +*/ + +func Test_Mock_TestData(t *testing.T) { + + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + if assert.NotNil(t, mockedService.TestData()) { + + mockedService.TestData().Set("something", 123) + assert.Equal(t, 123, mockedService.TestData().Get("something").Data()) + + } + +} + +func Test_Mock_On(t *testing.T) { + + // make a test impl object + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + assert.Equal(t, mockedService.On("TheExampleMethod"), &mockedService.Mock) + assert.Equal(t, "TheExampleMethod", mockedService.onMethodName) + +} + +func Test_Mock_On_WithArgs(t *testing.T) { + + // make a test impl object + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + assert.Equal(t, mockedService.On("TheExampleMethod", 1, 2, 3), &mockedService.Mock) + assert.Equal(t, "TheExampleMethod", mockedService.onMethodName) + assert.Equal(t, 1, mockedService.onMethodArguments[0]) + assert.Equal(t, 2, mockedService.onMethodArguments[1]) + assert.Equal(t, 3, mockedService.onMethodArguments[2]) + +} + +func Test_Mock_Return(t *testing.T) { + + // make a test impl object + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + assert.Equal(t, mockedService.On("TheExampleMethod", "A", "B", true).Return(1, "two", true), &mockedService.Mock) + + // ensure the call was created + if assert.Equal(t, 1, len(mockedService.ExpectedCalls)) { + call := mockedService.ExpectedCalls[0] + + assert.Equal(t, "TheExampleMethod", call.Method) + assert.Equal(t, "A", call.Arguments[0]) + assert.Equal(t, "B", call.Arguments[1]) + assert.Equal(t, true, call.Arguments[2]) + assert.Equal(t, 1, call.ReturnArguments[0]) + assert.Equal(t, "two", call.ReturnArguments[1]) + assert.Equal(t, true, call.ReturnArguments[2]) + assert.Equal(t, 0, call.Repeatability) + + } + +} + +func Test_Mock_Return_Once(t *testing.T) { + + // make a test impl object + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + mockedService.On("TheExampleMethod", "A", "B", true).Return(1, "two", true).Once() + + // ensure the call was created + if assert.Equal(t, 1, len(mockedService.ExpectedCalls)) { + call := mockedService.ExpectedCalls[0] + + assert.Equal(t, "TheExampleMethod", call.Method) + assert.Equal(t, "A", call.Arguments[0]) + assert.Equal(t, "B", call.Arguments[1]) + assert.Equal(t, true, call.Arguments[2]) + assert.Equal(t, 1, call.ReturnArguments[0]) + assert.Equal(t, "two", call.ReturnArguments[1]) + assert.Equal(t, true, call.ReturnArguments[2]) + assert.Equal(t, 1, call.Repeatability) + + } + +} + +func Test_Mock_Return_Twice(t *testing.T) { + + // make a test impl object + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + mockedService.On("TheExampleMethod", "A", "B", true).Return(1, "two", true).Twice() + + // ensure the call was created + if assert.Equal(t, 1, len(mockedService.ExpectedCalls)) { + call := mockedService.ExpectedCalls[0] + + assert.Equal(t, "TheExampleMethod", call.Method) + assert.Equal(t, "A", call.Arguments[0]) + assert.Equal(t, "B", call.Arguments[1]) + assert.Equal(t, true, call.Arguments[2]) + assert.Equal(t, 1, call.ReturnArguments[0]) + assert.Equal(t, "two", call.ReturnArguments[1]) + assert.Equal(t, true, call.ReturnArguments[2]) + assert.Equal(t, 2, call.Repeatability) + + } + +} + +func Test_Mock_Return_Times(t *testing.T) { + + // make a test impl object + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + mockedService.On("TheExampleMethod", "A", "B", true).Return(1, "two", true).Times(5) + + // ensure the call was created + if assert.Equal(t, 1, len(mockedService.ExpectedCalls)) { + call := mockedService.ExpectedCalls[0] + + assert.Equal(t, "TheExampleMethod", call.Method) + assert.Equal(t, "A", call.Arguments[0]) + assert.Equal(t, "B", call.Arguments[1]) + assert.Equal(t, true, call.Arguments[2]) + assert.Equal(t, 1, call.ReturnArguments[0]) + assert.Equal(t, "two", call.ReturnArguments[1]) + assert.Equal(t, true, call.ReturnArguments[2]) + assert.Equal(t, 5, call.Repeatability) + + } + +} + +func Test_Mock_Return_Nothing(t *testing.T) { + + // make a test impl object + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + assert.Equal(t, mockedService.On("TheExampleMethod", "A", "B", true).Return(), &mockedService.Mock) + + // ensure the call was created + if assert.Equal(t, 1, len(mockedService.ExpectedCalls)) { + call := mockedService.ExpectedCalls[0] + + assert.Equal(t, "TheExampleMethod", call.Method) + assert.Equal(t, "A", call.Arguments[0]) + assert.Equal(t, "B", call.Arguments[1]) + assert.Equal(t, true, call.Arguments[2]) + assert.Equal(t, 0, len(call.ReturnArguments)) + + } + +} + +func Test_Mock_findExpectedCall(t *testing.T) { + + m := new(Mock) + m.On("One", 1).Return("one") + m.On("Two", 2).Return("two") + m.On("Two", 3).Return("three") + + f, c := m.findExpectedCall("Two", 3) + + if assert.Equal(t, 2, f) { + if assert.NotNil(t, c) { + assert.Equal(t, "Two", c.Method) + assert.Equal(t, 3, c.Arguments[0]) + assert.Equal(t, "three", c.ReturnArguments[0]) + } + } + +} + +func Test_Mock_findExpectedCall_For_Unknown_Method(t *testing.T) { + + m := new(Mock) + m.On("One", 1).Return("one") + m.On("Two", 2).Return("two") + m.On("Two", 3).Return("three") + + f, _ := m.findExpectedCall("Two") + + assert.Equal(t, -1, f) + +} + +func Test_Mock_findExpectedCall_Respects_Repeatability(t *testing.T) { + + m := new(Mock) + m.On("One", 1).Return("one") + m.On("Two", 2).Return("two").Once() + m.On("Two", 3).Return("three").Twice() + m.On("Two", 3).Return("three").Times(8) + + f, c := m.findExpectedCall("Two", 3) + + if assert.Equal(t, 2, f) { + if assert.NotNil(t, c) { + assert.Equal(t, "Two", c.Method) + assert.Equal(t, 3, c.Arguments[0]) + assert.Equal(t, "three", c.ReturnArguments[0]) + } + } + +} + +func Test_callString(t *testing.T) { + + assert.Equal(t, `Method(int,bool,string)`, callString("Method", []interface{}{1, true, "something"}, false)) + +} + +func Test_Mock_Called(t *testing.T) { + + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + mockedService.On("Test_Mock_Called", 1, 2, 3).Return(5, "6", true) + + returnArguments := mockedService.Called(1, 2, 3) + + if assert.Equal(t, 1, len(mockedService.Calls)) { + assert.Equal(t, "Test_Mock_Called", mockedService.Calls[0].Method) + assert.Equal(t, 1, mockedService.Calls[0].Arguments[0]) + assert.Equal(t, 2, mockedService.Calls[0].Arguments[1]) + assert.Equal(t, 3, mockedService.Calls[0].Arguments[2]) + } + + if assert.Equal(t, 3, len(returnArguments)) { + assert.Equal(t, 5, returnArguments[0]) + assert.Equal(t, "6", returnArguments[1]) + assert.Equal(t, true, returnArguments[2]) + } + +} + +func Test_Mock_Called_For_Bounded_Repeatability(t *testing.T) { + + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + mockedService.On("Test_Mock_Called_For_Bounded_Repeatability", 1, 2, 3).Return(5, "6", true).Once() + mockedService.On("Test_Mock_Called_For_Bounded_Repeatability", 1, 2, 3).Return(-1, "hi", false) + + returnArguments1 := mockedService.Called(1, 2, 3) + returnArguments2 := mockedService.Called(1, 2, 3) + + if assert.Equal(t, 2, len(mockedService.Calls)) { + assert.Equal(t, "Test_Mock_Called_For_Bounded_Repeatability", mockedService.Calls[0].Method) + assert.Equal(t, 1, mockedService.Calls[0].Arguments[0]) + assert.Equal(t, 2, mockedService.Calls[0].Arguments[1]) + assert.Equal(t, 3, mockedService.Calls[0].Arguments[2]) + + assert.Equal(t, "Test_Mock_Called_For_Bounded_Repeatability", mockedService.Calls[1].Method) + assert.Equal(t, 1, mockedService.Calls[1].Arguments[0]) + assert.Equal(t, 2, mockedService.Calls[1].Arguments[1]) + assert.Equal(t, 3, mockedService.Calls[1].Arguments[2]) + } + + if assert.Equal(t, 3, len(returnArguments1)) { + assert.Equal(t, 5, returnArguments1[0]) + assert.Equal(t, "6", returnArguments1[1]) + assert.Equal(t, true, returnArguments1[2]) + } + + if assert.Equal(t, 3, len(returnArguments2)) { + assert.Equal(t, -1, returnArguments2[0]) + assert.Equal(t, "hi", returnArguments2[1]) + assert.Equal(t, false, returnArguments2[2]) + } + +} + +func Test_Mock_Called_For_SetTime_Expectation(t *testing.T) { + + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + mockedService.On("TheExampleMethod", 1, 2, 3).Return(5, "6", true).Times(4) + + mockedService.TheExampleMethod(1, 2, 3) + mockedService.TheExampleMethod(1, 2, 3) + mockedService.TheExampleMethod(1, 2, 3) + mockedService.TheExampleMethod(1, 2, 3) + assert.Panics(t, func() { + mockedService.TheExampleMethod(1, 2, 3) + }) + +} + +func Test_Mock_Called_Unexpected(t *testing.T) { + + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + // make sure it panics if no expectation was made + assert.Panics(t, func() { + mockedService.Called(1, 2, 3) + }, "Calling unexpected method should panic") + +} + +func Test_AssertExpectationsForObjects_Helper(t *testing.T) { + + var mockedService1 *TestExampleImplementation = new(TestExampleImplementation) + var mockedService2 *TestExampleImplementation = new(TestExampleImplementation) + var mockedService3 *TestExampleImplementation = new(TestExampleImplementation) + + mockedService1.On("Test_AssertExpectationsForObjects_Helper", 1).Return() + mockedService2.On("Test_AssertExpectationsForObjects_Helper", 2).Return() + mockedService3.On("Test_AssertExpectationsForObjects_Helper", 3).Return() + + mockedService1.Called(1) + mockedService2.Called(2) + mockedService3.Called(3) + + assert.True(t, AssertExpectationsForObjects(t, mockedService1.Mock, mockedService2.Mock, mockedService3.Mock)) + +} + +func Test_AssertExpectationsForObjects_Helper_Failed(t *testing.T) { + + var mockedService1 *TestExampleImplementation = new(TestExampleImplementation) + var mockedService2 *TestExampleImplementation = new(TestExampleImplementation) + var mockedService3 *TestExampleImplementation = new(TestExampleImplementation) + + mockedService1.On("Test_AssertExpectationsForObjects_Helper_Failed", 1).Return() + mockedService2.On("Test_AssertExpectationsForObjects_Helper_Failed", 2).Return() + mockedService3.On("Test_AssertExpectationsForObjects_Helper_Failed", 3).Return() + + mockedService1.Called(1) + mockedService3.Called(3) + + tt := new(testing.T) + assert.False(t, AssertExpectationsForObjects(tt, mockedService1.Mock, mockedService2.Mock, mockedService3.Mock)) + +} + +func Test_Mock_AssertExpectations(t *testing.T) { + + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + mockedService.On("Test_Mock_AssertExpectations", 1, 2, 3).Return(5, 6, 7) + + tt := new(testing.T) + assert.False(t, mockedService.AssertExpectations(tt)) + + // make the call now + mockedService.Called(1, 2, 3) + + // now assert expectations + assert.True(t, mockedService.AssertExpectations(tt)) + +} + +func Test_Mock_AssertExpectationsCustomType(t *testing.T) { + + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + mockedService.On("TheExampleMethod3", AnythingOfType("*mock.ExampleType")).Return(nil).Once() + + tt := new(testing.T) + assert.False(t, mockedService.AssertExpectations(tt)) + + // make the call now + mockedService.TheExampleMethod3(&ExampleType{}) + + // now assert expectations + assert.True(t, mockedService.AssertExpectations(tt)) + +} + +func Test_Mock_AssertExpectations_With_Repeatability(t *testing.T) { + + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + mockedService.On("Test_Mock_AssertExpectations_With_Repeatability", 1, 2, 3).Return(5, 6, 7).Twice() + + tt := new(testing.T) + assert.False(t, mockedService.AssertExpectations(tt)) + + // make the call now + mockedService.Called(1, 2, 3) + + assert.False(t, mockedService.AssertExpectations(tt)) + + mockedService.Called(1, 2, 3) + + // now assert expectations + assert.True(t, mockedService.AssertExpectations(tt)) + +} + +func Test_Mock_TwoCallsWithDifferentArguments(t *testing.T) { + + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + mockedService.On("Test_Mock_TwoCallsWithDifferentArguments", 1, 2, 3).Return(5, 6, 7) + mockedService.On("Test_Mock_TwoCallsWithDifferentArguments", 4, 5, 6).Return(5, 6, 7) + + args1 := mockedService.Called(1, 2, 3) + assert.Equal(t, 5, args1.Int(0)) + assert.Equal(t, 6, args1.Int(1)) + assert.Equal(t, 7, args1.Int(2)) + + args2 := mockedService.Called(4, 5, 6) + assert.Equal(t, 5, args2.Int(0)) + assert.Equal(t, 6, args2.Int(1)) + assert.Equal(t, 7, args2.Int(2)) + +} + +func Test_Mock_AssertNumberOfCalls(t *testing.T) { + + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + mockedService.On("Test_Mock_AssertNumberOfCalls", 1, 2, 3).Return(5, 6, 7) + + mockedService.Called(1, 2, 3) + assert.True(t, mockedService.AssertNumberOfCalls(t, "Test_Mock_AssertNumberOfCalls", 1)) + + mockedService.Called(1, 2, 3) + assert.True(t, mockedService.AssertNumberOfCalls(t, "Test_Mock_AssertNumberOfCalls", 2)) + +} + +func Test_Mock_AssertCalled(t *testing.T) { + + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + mockedService.On("Test_Mock_AssertCalled", 1, 2, 3).Return(5, 6, 7) + + mockedService.Called(1, 2, 3) + + assert.True(t, mockedService.AssertCalled(t, "Test_Mock_AssertCalled", 1, 2, 3)) + +} + +func Test_Mock_AssertCalled_WithAnythingOfTypeArgument(t *testing.T) { + + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + mockedService.On("Test_Mock_AssertCalled_WithAnythingOfTypeArgument", Anything, Anything, Anything).Return() + + mockedService.Called(1, "two", []uint8("three")) + + assert.True(t, mockedService.AssertCalled(t, "Test_Mock_AssertCalled_WithAnythingOfTypeArgument", AnythingOfType("int"), AnythingOfType("string"), AnythingOfType("[]uint8"))) + +} + +func Test_Mock_AssertCalled_WithArguments(t *testing.T) { + + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + mockedService.On("Test_Mock_AssertCalled_WithArguments", 1, 2, 3).Return(5, 6, 7) + + mockedService.Called(1, 2, 3) + + tt := new(testing.T) + assert.True(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments", 1, 2, 3)) + assert.False(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments", 2, 3, 4)) + +} + +func Test_Mock_AssertCalled_WithArguments_With_Repeatability(t *testing.T) { + + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + mockedService.On("Test_Mock_AssertCalled_WithArguments_With_Repeatability", 1, 2, 3).Return(5, 6, 7).Once() + mockedService.On("Test_Mock_AssertCalled_WithArguments_With_Repeatability", 2, 3, 4).Return(5, 6, 7).Once() + + mockedService.Called(1, 2, 3) + mockedService.Called(2, 3, 4) + + tt := new(testing.T) + assert.True(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments_With_Repeatability", 1, 2, 3)) + assert.True(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments_With_Repeatability", 2, 3, 4)) + assert.False(t, mockedService.AssertCalled(tt, "Test_Mock_AssertCalled_WithArguments_With_Repeatability", 3, 4, 5)) + +} + +func Test_Mock_AssertNotCalled(t *testing.T) { + + var mockedService *TestExampleImplementation = new(TestExampleImplementation) + + mockedService.On("Test_Mock_AssertNotCalled", 1, 2, 3).Return(5, 6, 7) + + mockedService.Called(1, 2, 3) + + assert.True(t, mockedService.AssertNotCalled(t, "Test_Mock_NotCalled")) + +} + +/* + Arguments helper methods +*/ +func Test_Arguments_Get(t *testing.T) { + + var args Arguments = []interface{}{"string", 123, true} + + assert.Equal(t, "string", args.Get(0).(string)) + assert.Equal(t, 123, args.Get(1).(int)) + assert.Equal(t, true, args.Get(2).(bool)) + +} + +func Test_Arguments_Is(t *testing.T) { + + var args Arguments = []interface{}{"string", 123, true} + + assert.True(t, args.Is("string", 123, true)) + assert.False(t, args.Is("wrong", 456, false)) + +} + +func Test_Arguments_Diff(t *testing.T) { + + var args Arguments = []interface{}{"Hello World", 123, true} + var diff string + var count int + diff, count = args.Diff([]interface{}{"Hello World", 456, "false"}) + + assert.Equal(t, 2, count) + assert.Contains(t, diff, `%!s(int=456) != %!s(int=123)`) + assert.Contains(t, diff, `false != %!s(bool=true)`) + +} + +func Test_Arguments_Diff_DifferentNumberOfArgs(t *testing.T) { + + var args Arguments = []interface{}{"string", 123, true} + var diff string + var count int + diff, count = args.Diff([]interface{}{"string", 456, "false", "extra"}) + + assert.Equal(t, 3, count) + assert.Contains(t, diff, `extra != (Missing)`) + +} + +func Test_Arguments_Diff_WithAnythingArgument(t *testing.T) { + + var args Arguments = []interface{}{"string", 123, true} + var count int + _, count = args.Diff([]interface{}{"string", Anything, true}) + + assert.Equal(t, 0, count) + +} + +func Test_Arguments_Diff_WithAnythingArgument_InActualToo(t *testing.T) { + + var args Arguments = []interface{}{"string", Anything, true} + var count int + _, count = args.Diff([]interface{}{"string", 123, true}) + + assert.Equal(t, 0, count) + +} + +func Test_Arguments_Diff_WithAnythingOfTypeArgument(t *testing.T) { + + var args Arguments = []interface{}{"string", AnythingOfType("int"), true} + var count int + _, count = args.Diff([]interface{}{"string", 123, true}) + + assert.Equal(t, 0, count) + +} + +func Test_Arguments_Diff_WithAnythingOfTypeArgument_Failing(t *testing.T) { + + var args Arguments = []interface{}{"string", AnythingOfType("string"), true} + var count int + var diff string + diff, count = args.Diff([]interface{}{"string", 123, true}) + + assert.Equal(t, 1, count) + assert.Contains(t, diff, `string != type int - %!s(int=123)`) + +} + +func Test_Arguments_Assert(t *testing.T) { + + var args Arguments = []interface{}{"string", 123, true} + + assert.True(t, args.Assert(t, "string", 123, true)) + +} + +func Test_Arguments_String_Representation(t *testing.T) { + + var args Arguments = []interface{}{"string", 123, true} + assert.Equal(t, `string,int,bool`, args.String()) + +} + +func Test_Arguments_String(t *testing.T) { + + var args Arguments = []interface{}{"string", 123, true} + assert.Equal(t, "string", args.String(0)) + +} + +func Test_Arguments_Error(t *testing.T) { + + var err error = errors.New("An Error") + var args Arguments = []interface{}{"string", 123, true, err} + assert.Equal(t, err, args.Error(3)) + +} + +func Test_Arguments_Error_Nil(t *testing.T) { + + var args Arguments = []interface{}{"string", 123, true, nil} + assert.Equal(t, nil, args.Error(3)) + +} + +func Test_Arguments_Int(t *testing.T) { + + var args Arguments = []interface{}{"string", 123, true} + assert.Equal(t, 123, args.Int(1)) + +} + +func Test_Arguments_Bool(t *testing.T) { + + var args Arguments = []interface{}{"string", 123, true} + assert.Equal(t, true, args.Bool(2)) + +} diff --git a/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/.gitignore b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/.gitignore new file mode 100644 index 000000000..191a5360b --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/.gitignore @@ -0,0 +1,4 @@ +_* +*.swp +*.[568] +[568].out diff --git a/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/LICENSE b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/LICENSE new file mode 100644 index 000000000..545cf2d33 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/LICENSE @@ -0,0 +1,25 @@ +Gocheck - A rich testing framework for Go + +Copyright (c) 2010-2013 Gustavo Niemeyer + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/README.md b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/README.md new file mode 100644 index 000000000..0ca9e5726 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/README.md @@ -0,0 +1,20 @@ +Instructions +============ + +Install the package with: + + go get gopkg.in/check.v1 + +Import it with: + + import "gopkg.in/check.v1" + +and use _check_ as the package name inside the code. + +For more details, visit the project page: + +* http://labix.org/gocheck + +and the API documentation: + +* https://gopkg.in/check.v1 diff --git a/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/TODO b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/TODO new file mode 100644 index 000000000..33498270e --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/TODO @@ -0,0 +1,2 @@ +- Assert(slice, Contains, item) +- Parallel test support diff --git a/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/benchmark.go b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/benchmark.go new file mode 100644 index 000000000..48cb8c811 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/benchmark.go @@ -0,0 +1,163 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package check + +import ( + "fmt" + "runtime" + "time" +) + +var memStats runtime.MemStats + +// testingB is a type passed to Benchmark functions to manage benchmark +// timing and to specify the number of iterations to run. +type timer struct { + start time.Time // Time test or benchmark started + duration time.Duration + N int + bytes int64 + timerOn bool + benchTime time.Duration + // The initial states of memStats.Mallocs and memStats.TotalAlloc. + startAllocs uint64 + startBytes uint64 + // The net total of this test after being run. + netAllocs uint64 + netBytes uint64 +} + +// StartTimer starts timing a test. This function is called automatically +// before a benchmark starts, but it can also used to resume timing after +// a call to StopTimer. +func (c *C) StartTimer() { + if !c.timerOn { + c.start = time.Now() + c.timerOn = true + + runtime.ReadMemStats(&memStats) + c.startAllocs = memStats.Mallocs + c.startBytes = memStats.TotalAlloc + } +} + +// StopTimer stops timing a test. This can be used to pause the timer +// while performing complex initialization that you don't +// want to measure. +func (c *C) StopTimer() { + if c.timerOn { + c.duration += time.Now().Sub(c.start) + c.timerOn = false + runtime.ReadMemStats(&memStats) + c.netAllocs += memStats.Mallocs - c.startAllocs + c.netBytes += memStats.TotalAlloc - c.startBytes + } +} + +// ResetTimer sets the elapsed benchmark time to zero. +// It does not affect whether the timer is running. +func (c *C) ResetTimer() { + if c.timerOn { + c.start = time.Now() + runtime.ReadMemStats(&memStats) + c.startAllocs = memStats.Mallocs + c.startBytes = memStats.TotalAlloc + } + c.duration = 0 + c.netAllocs = 0 + c.netBytes = 0 +} + +// SetBytes informs the number of bytes that the benchmark processes +// on each iteration. If this is called in a benchmark it will also +// report MB/s. +func (c *C) SetBytes(n int64) { + c.bytes = n +} + +func (c *C) nsPerOp() int64 { + if c.N <= 0 { + return 0 + } + return c.duration.Nanoseconds() / int64(c.N) +} + +func (c *C) mbPerSec() float64 { + if c.bytes <= 0 || c.duration <= 0 || c.N <= 0 { + return 0 + } + return (float64(c.bytes) * float64(c.N) / 1e6) / c.duration.Seconds() +} + +func (c *C) timerString() string { + if c.N <= 0 { + return fmt.Sprintf("%3.3fs", float64(c.duration.Nanoseconds())/1e9) + } + mbs := c.mbPerSec() + mb := "" + if mbs != 0 { + mb = fmt.Sprintf("\t%7.2f MB/s", mbs) + } + nsop := c.nsPerOp() + ns := fmt.Sprintf("%10d ns/op", nsop) + if c.N > 0 && nsop < 100 { + // The format specifiers here make sure that + // the ones digits line up for all three possible formats. + if nsop < 10 { + ns = fmt.Sprintf("%13.2f ns/op", float64(c.duration.Nanoseconds())/float64(c.N)) + } else { + ns = fmt.Sprintf("%12.1f ns/op", float64(c.duration.Nanoseconds())/float64(c.N)) + } + } + memStats := "" + if c.benchMem { + allocedBytes := fmt.Sprintf("%8d B/op", int64(c.netBytes)/int64(c.N)) + allocs := fmt.Sprintf("%8d allocs/op", int64(c.netAllocs)/int64(c.N)) + memStats = fmt.Sprintf("\t%s\t%s", allocedBytes, allocs) + } + return fmt.Sprintf("%8d\t%s%s%s", c.N, ns, mb, memStats) +} + +func min(x, y int) int { + if x > y { + return y + } + return x +} + +func max(x, y int) int { + if x < y { + return y + } + return x +} + +// roundDown10 rounds a number down to the nearest power of 10. +func roundDown10(n int) int { + var tens = 0 + // tens = floor(log_10(n)) + for n > 10 { + n = n / 10 + tens++ + } + // result = 10^tens + result := 1 + for i := 0; i < tens; i++ { + result *= 10 + } + return result +} + +// roundUp rounds x up to a number of the form [1eX, 2eX, 5eX]. +func roundUp(n int) int { + base := roundDown10(n) + if n < (2 * base) { + return 2 * base + } + if n < (5 * base) { + return 5 * base + } + return 10 * base +} diff --git a/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/benchmark_test.go b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/benchmark_test.go new file mode 100644 index 000000000..4dd827c16 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/benchmark_test.go @@ -0,0 +1,91 @@ +// These tests verify the test running logic. + +package check_test + +import ( + "time" + . "gopkg.in/check.v1" +) + +var benchmarkS = Suite(&BenchmarkS{}) + +type BenchmarkS struct{} + +func (s *BenchmarkS) TestCountSuite(c *C) { + suitesRun += 1 +} + +func (s *BenchmarkS) TestBasicTestTiming(c *C) { + helper := FixtureHelper{sleepOn: "Test1", sleep: 1000000 * time.Nanosecond} + output := String{} + runConf := RunConf{Output: &output, Verbose: true} + Run(&helper, &runConf) + + expected := "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Test1\t0\\.001s\n" + + "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Test2\t0\\.000s\n" + c.Assert(output.value, Matches, expected) +} + +func (s *BenchmarkS) TestStreamTestTiming(c *C) { + helper := FixtureHelper{sleepOn: "SetUpSuite", sleep: 1000000 * time.Nanosecond} + output := String{} + runConf := RunConf{Output: &output, Stream: true} + Run(&helper, &runConf) + + expected := "(?s).*\nPASS: check_test\\.go:[0-9]+: FixtureHelper\\.SetUpSuite\t *0\\.001s\n.*" + c.Assert(output.value, Matches, expected) +} + +func (s *BenchmarkS) TestBenchmark(c *C) { + helper := FixtureHelper{sleep: 100000} + output := String{} + runConf := RunConf{ + Output: &output, + Benchmark: true, + BenchmarkTime: 10000000, + Filter: "Benchmark1", + } + Run(&helper, &runConf) + c.Check(helper.calls[0], Equals, "SetUpSuite") + c.Check(helper.calls[1], Equals, "SetUpTest") + c.Check(helper.calls[2], Equals, "Benchmark1") + c.Check(helper.calls[3], Equals, "TearDownTest") + c.Check(helper.calls[4], Equals, "SetUpTest") + c.Check(helper.calls[5], Equals, "Benchmark1") + c.Check(helper.calls[6], Equals, "TearDownTest") + // ... and more. + + expected := "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Benchmark1\t *100\t *[12][0-9]{5} ns/op\n" + c.Assert(output.value, Matches, expected) +} + +func (s *BenchmarkS) TestBenchmarkBytes(c *C) { + helper := FixtureHelper{sleep: 100000} + output := String{} + runConf := RunConf{ + Output: &output, + Benchmark: true, + BenchmarkTime: 10000000, + Filter: "Benchmark2", + } + Run(&helper, &runConf) + + expected := "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Benchmark2\t *100\t *[12][0-9]{5} ns/op\t *[4-9]\\.[0-9]{2} MB/s\n" + c.Assert(output.value, Matches, expected) +} + +func (s *BenchmarkS) TestBenchmarkMem(c *C) { + helper := FixtureHelper{sleep: 100000} + output := String{} + runConf := RunConf{ + Output: &output, + Benchmark: true, + BenchmarkMem: true, + BenchmarkTime: 10000000, + Filter: "Benchmark3", + } + Run(&helper, &runConf) + + expected := "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Benchmark3\t *100\t *[12][0-9]{5} ns/op\t *[0-9]+ B/op\t *[1-9] allocs/op\n" + c.Assert(output.value, Matches, expected) +} diff --git a/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/bootstrap_test.go b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/bootstrap_test.go new file mode 100644 index 000000000..e55f327c7 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/bootstrap_test.go @@ -0,0 +1,82 @@ +// These initial tests are for bootstrapping. They verify that we can +// basically use the testing infrastructure itself to check if the test +// system is working. +// +// These tests use will break down the test runner badly in case of +// errors because if they simply fail, we can't be sure the developer +// will ever see anything (because failing means the failing system +// somehow isn't working! :-) +// +// Do not assume *any* internal functionality works as expected besides +// what's actually tested here. + +package check_test + +import ( + "fmt" + "gopkg.in/check.v1" + "strings" +) + +type BootstrapS struct{} + +var boostrapS = check.Suite(&BootstrapS{}) + +func (s *BootstrapS) TestCountSuite(c *check.C) { + suitesRun += 1 +} + +func (s *BootstrapS) TestFailedAndFail(c *check.C) { + if c.Failed() { + critical("c.Failed() must be false first!") + } + c.Fail() + if !c.Failed() { + critical("c.Fail() didn't put the test in a failed state!") + } + c.Succeed() +} + +func (s *BootstrapS) TestFailedAndSucceed(c *check.C) { + c.Fail() + c.Succeed() + if c.Failed() { + critical("c.Succeed() didn't put the test back in a non-failed state") + } +} + +func (s *BootstrapS) TestLogAndGetTestLog(c *check.C) { + c.Log("Hello there!") + log := c.GetTestLog() + if log != "Hello there!\n" { + critical(fmt.Sprintf("Log() or GetTestLog() is not working! Got: %#v", log)) + } +} + +func (s *BootstrapS) TestLogfAndGetTestLog(c *check.C) { + c.Logf("Hello %v", "there!") + log := c.GetTestLog() + if log != "Hello there!\n" { + critical(fmt.Sprintf("Logf() or GetTestLog() is not working! Got: %#v", log)) + } +} + +func (s *BootstrapS) TestRunShowsErrors(c *check.C) { + output := String{} + check.Run(&FailHelper{}, &check.RunConf{Output: &output}) + if strings.Index(output.value, "Expected failure!") == -1 { + critical(fmt.Sprintf("RunWithWriter() output did not contain the "+ + "expected failure! Got: %#v", + output.value)) + } +} + +func (s *BootstrapS) TestRunDoesntShowSuccesses(c *check.C) { + output := String{} + check.Run(&SuccessHelper{}, &check.RunConf{Output: &output}) + if strings.Index(output.value, "Expected success!") != -1 { + critical(fmt.Sprintf("RunWithWriter() output contained a successful "+ + "test! Got: %#v", + output.value)) + } +} diff --git a/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/check.go b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/check.go new file mode 100644 index 000000000..ca8c0f92d --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/check.go @@ -0,0 +1,945 @@ +// Package check is a rich testing extension for Go's testing package. +// +// For details about the project, see: +// +// http://labix.org/gocheck +// +package check + +import ( + "bytes" + "errors" + "fmt" + "io" + "math/rand" + "os" + "path" + "path/filepath" + "reflect" + "regexp" + "runtime" + "strconv" + "strings" + "sync" + "time" +) + +// ----------------------------------------------------------------------- +// Internal type which deals with suite method calling. + +const ( + fixtureKd = iota + testKd +) + +type funcKind int + +const ( + succeededSt = iota + failedSt + skippedSt + panickedSt + fixturePanickedSt + missedSt +) + +type funcStatus int + +// A method value can't reach its own Method structure. +type methodType struct { + reflect.Value + Info reflect.Method +} + +func newMethod(receiver reflect.Value, i int) *methodType { + return &methodType{receiver.Method(i), receiver.Type().Method(i)} +} + +func (method *methodType) PC() uintptr { + return method.Info.Func.Pointer() +} + +func (method *methodType) suiteName() string { + t := method.Info.Type.In(0) + if t.Kind() == reflect.Ptr { + t = t.Elem() + } + return t.Name() +} + +func (method *methodType) String() string { + return method.suiteName() + "." + method.Info.Name +} + +func (method *methodType) matches(re *regexp.Regexp) bool { + return (re.MatchString(method.Info.Name) || + re.MatchString(method.suiteName()) || + re.MatchString(method.String())) +} + +type C struct { + method *methodType + kind funcKind + testName string + status funcStatus + logb *logger + logw io.Writer + done chan *C + reason string + mustFail bool + tempDir *tempDir + benchMem bool + startTime time.Time + timer +} + +func (c *C) stopNow() { + runtime.Goexit() +} + +// logger is a concurrency safe byte.Buffer +type logger struct { + sync.Mutex + writer bytes.Buffer +} + +func (l *logger) Write(buf []byte) (int, error) { + l.Lock() + defer l.Unlock() + return l.writer.Write(buf) +} + +func (l *logger) WriteTo(w io.Writer) (int64, error) { + l.Lock() + defer l.Unlock() + return l.writer.WriteTo(w) +} + +func (l *logger) String() string { + l.Lock() + defer l.Unlock() + return l.writer.String() +} + +// ----------------------------------------------------------------------- +// Handling of temporary files and directories. + +type tempDir struct { + sync.Mutex + path string + counter int +} + +func (td *tempDir) newPath() string { + td.Lock() + defer td.Unlock() + if td.path == "" { + var err error + for i := 0; i != 100; i++ { + path := fmt.Sprintf("%s%ccheck-%d", os.TempDir(), os.PathSeparator, rand.Int()) + if err = os.Mkdir(path, 0700); err == nil { + td.path = path + break + } + } + if td.path == "" { + panic("Couldn't create temporary directory: " + err.Error()) + } + } + result := filepath.Join(td.path, strconv.Itoa(td.counter)) + td.counter += 1 + return result +} + +func (td *tempDir) removeAll() { + td.Lock() + defer td.Unlock() + if td.path != "" { + err := os.RemoveAll(td.path) + if err != nil { + fmt.Fprintf(os.Stderr, "WARNING: Error cleaning up temporaries: "+err.Error()) + } + } +} + +// Create a new temporary directory which is automatically removed after +// the suite finishes running. +func (c *C) MkDir() string { + path := c.tempDir.newPath() + if err := os.Mkdir(path, 0700); err != nil { + panic(fmt.Sprintf("Couldn't create temporary directory %s: %s", path, err.Error())) + } + return path +} + +// ----------------------------------------------------------------------- +// Low-level logging functions. + +func (c *C) log(args ...interface{}) { + c.writeLog([]byte(fmt.Sprint(args...) + "\n")) +} + +func (c *C) logf(format string, args ...interface{}) { + c.writeLog([]byte(fmt.Sprintf(format+"\n", args...))) +} + +func (c *C) logNewLine() { + c.writeLog([]byte{'\n'}) +} + +func (c *C) writeLog(buf []byte) { + c.logb.Write(buf) + if c.logw != nil { + c.logw.Write(buf) + } +} + +func hasStringOrError(x interface{}) (ok bool) { + _, ok = x.(fmt.Stringer) + if ok { + return + } + _, ok = x.(error) + return +} + +func (c *C) logValue(label string, value interface{}) { + if label == "" { + if hasStringOrError(value) { + c.logf("... %#v (%q)", value, value) + } else { + c.logf("... %#v", value) + } + } else if value == nil { + c.logf("... %s = nil", label) + } else { + if hasStringOrError(value) { + fv := fmt.Sprintf("%#v", value) + qv := fmt.Sprintf("%q", value) + if fv != qv { + c.logf("... %s %s = %s (%s)", label, reflect.TypeOf(value), fv, qv) + return + } + } + if s, ok := value.(string); ok && isMultiLine(s) { + c.logf(`... %s %s = "" +`, label, reflect.TypeOf(value)) + c.logMultiLine(s) + } else { + c.logf("... %s %s = %#v", label, reflect.TypeOf(value), value) + } + } +} + +func (c *C) logMultiLine(s string) { + b := make([]byte, 0, len(s)*2) + i := 0 + n := len(s) + for i < n { + j := i + 1 + for j < n && s[j-1] != '\n' { + j++ + } + b = append(b, "... "...) + b = strconv.AppendQuote(b, s[i:j]) + if j < n { + b = append(b, " +"...) + } + b = append(b, '\n') + i = j + } + c.writeLog(b) +} + +func isMultiLine(s string) bool { + for i := 0; i+1 < len(s); i++ { + if s[i] == '\n' { + return true + } + } + return false +} + +func (c *C) logString(issue string) { + c.log("... ", issue) +} + +func (c *C) logCaller(skip int) { + // This is a bit heavier than it ought to be. + skip += 1 // Our own frame. + pc, callerFile, callerLine, ok := runtime.Caller(skip) + if !ok { + return + } + var testFile string + var testLine int + testFunc := runtime.FuncForPC(c.method.PC()) + if runtime.FuncForPC(pc) != testFunc { + for { + skip += 1 + if pc, file, line, ok := runtime.Caller(skip); ok { + // Note that the test line may be different on + // distinct calls for the same test. Showing + // the "internal" line is helpful when debugging. + if runtime.FuncForPC(pc) == testFunc { + testFile, testLine = file, line + break + } + } else { + break + } + } + } + if testFile != "" && (testFile != callerFile || testLine != callerLine) { + c.logCode(testFile, testLine) + } + c.logCode(callerFile, callerLine) +} + +func (c *C) logCode(path string, line int) { + c.logf("%s:%d:", nicePath(path), line) + code, err := printLine(path, line) + if code == "" { + code = "..." // XXX Open the file and take the raw line. + if err != nil { + code += err.Error() + } + } + c.log(indent(code, " ")) +} + +var valueGo = filepath.Join("reflect", "value.go") +var asmGo = filepath.Join("runtime", "asm_") + +func (c *C) logPanic(skip int, value interface{}) { + skip++ // Our own frame. + initialSkip := skip + for ; ; skip++ { + if pc, file, line, ok := runtime.Caller(skip); ok { + if skip == initialSkip { + c.logf("... Panic: %s (PC=0x%X)\n", value, pc) + } + name := niceFuncName(pc) + path := nicePath(file) + if strings.Contains(path, "/gopkg.in/check.v") { + continue + } + if name == "Value.call" && strings.HasSuffix(path, valueGo) { + continue + } + if name == "call16" && strings.Contains(path, asmGo) { + continue + } + c.logf("%s:%d\n in %s", nicePath(file), line, name) + } else { + break + } + } +} + +func (c *C) logSoftPanic(issue string) { + c.log("... Panic: ", issue) +} + +func (c *C) logArgPanic(method *methodType, expectedType string) { + c.logf("... Panic: %s argument should be %s", + niceFuncName(method.PC()), expectedType) +} + +// ----------------------------------------------------------------------- +// Some simple formatting helpers. + +var initWD, initWDErr = os.Getwd() + +func init() { + if initWDErr == nil { + initWD = strings.Replace(initWD, "\\", "/", -1) + "/" + } +} + +func nicePath(path string) string { + if initWDErr == nil { + if strings.HasPrefix(path, initWD) { + return path[len(initWD):] + } + } + return path +} + +func niceFuncPath(pc uintptr) string { + function := runtime.FuncForPC(pc) + if function != nil { + filename, line := function.FileLine(pc) + return fmt.Sprintf("%s:%d", nicePath(filename), line) + } + return "" +} + +func niceFuncName(pc uintptr) string { + function := runtime.FuncForPC(pc) + if function != nil { + name := path.Base(function.Name()) + if i := strings.Index(name, "."); i > 0 { + name = name[i+1:] + } + if strings.HasPrefix(name, "(*") { + if i := strings.Index(name, ")"); i > 0 { + name = name[2:i] + name[i+1:] + } + } + if i := strings.LastIndex(name, ".*"); i != -1 { + name = name[:i] + "." + name[i+2:] + } + if i := strings.LastIndex(name, "·"); i != -1 { + name = name[:i] + "." + name[i+2:] + } + return name + } + return "" +} + +// ----------------------------------------------------------------------- +// Result tracker to aggregate call results. + +type Result struct { + Succeeded int + Failed int + Skipped int + Panicked int + FixturePanicked int + ExpectedFailures int + Missed int // Not even tried to run, related to a panic in the fixture. + RunError error // Houston, we've got a problem. + WorkDir string // If KeepWorkDir is true +} + +type resultTracker struct { + result Result + _lastWasProblem bool + _waiting int + _missed int + _expectChan chan *C + _doneChan chan *C + _stopChan chan bool +} + +func newResultTracker() *resultTracker { + return &resultTracker{_expectChan: make(chan *C), // Synchronous + _doneChan: make(chan *C, 32), // Asynchronous + _stopChan: make(chan bool)} // Synchronous +} + +func (tracker *resultTracker) start() { + go tracker._loopRoutine() +} + +func (tracker *resultTracker) waitAndStop() { + <-tracker._stopChan +} + +func (tracker *resultTracker) expectCall(c *C) { + tracker._expectChan <- c +} + +func (tracker *resultTracker) callDone(c *C) { + tracker._doneChan <- c +} + +func (tracker *resultTracker) _loopRoutine() { + for { + var c *C + if tracker._waiting > 0 { + // Calls still running. Can't stop. + select { + // XXX Reindent this (not now to make diff clear) + case c = <-tracker._expectChan: + tracker._waiting += 1 + case c = <-tracker._doneChan: + tracker._waiting -= 1 + switch c.status { + case succeededSt: + if c.kind == testKd { + if c.mustFail { + tracker.result.ExpectedFailures++ + } else { + tracker.result.Succeeded++ + } + } + case failedSt: + tracker.result.Failed++ + case panickedSt: + if c.kind == fixtureKd { + tracker.result.FixturePanicked++ + } else { + tracker.result.Panicked++ + } + case fixturePanickedSt: + // Track it as missed, since the panic + // was on the fixture, not on the test. + tracker.result.Missed++ + case missedSt: + tracker.result.Missed++ + case skippedSt: + if c.kind == testKd { + tracker.result.Skipped++ + } + } + } + } else { + // No calls. Can stop, but no done calls here. + select { + case tracker._stopChan <- true: + return + case c = <-tracker._expectChan: + tracker._waiting += 1 + case c = <-tracker._doneChan: + panic("Tracker got an unexpected done call.") + } + } + } +} + +// ----------------------------------------------------------------------- +// The underlying suite runner. + +type suiteRunner struct { + suite interface{} + setUpSuite, tearDownSuite *methodType + setUpTest, tearDownTest *methodType + tests []*methodType + tracker *resultTracker + tempDir *tempDir + keepDir bool + output *outputWriter + reportedProblemLast bool + benchTime time.Duration + benchMem bool +} + +type RunConf struct { + Output io.Writer + Stream bool + Verbose bool + Filter string + Benchmark bool + BenchmarkTime time.Duration // Defaults to 1 second + BenchmarkMem bool + KeepWorkDir bool +} + +// Create a new suiteRunner able to run all methods in the given suite. +func newSuiteRunner(suite interface{}, runConf *RunConf) *suiteRunner { + var conf RunConf + if runConf != nil { + conf = *runConf + } + if conf.Output == nil { + conf.Output = os.Stdout + } + if conf.Benchmark { + conf.Verbose = true + } + + suiteType := reflect.TypeOf(suite) + suiteNumMethods := suiteType.NumMethod() + suiteValue := reflect.ValueOf(suite) + + runner := &suiteRunner{ + suite: suite, + output: newOutputWriter(conf.Output, conf.Stream, conf.Verbose), + tracker: newResultTracker(), + benchTime: conf.BenchmarkTime, + benchMem: conf.BenchmarkMem, + tempDir: &tempDir{}, + keepDir: conf.KeepWorkDir, + tests: make([]*methodType, 0, suiteNumMethods), + } + if runner.benchTime == 0 { + runner.benchTime = 1 * time.Second + } + + var filterRegexp *regexp.Regexp + if conf.Filter != "" { + if regexp, err := regexp.Compile(conf.Filter); err != nil { + msg := "Bad filter expression: " + err.Error() + runner.tracker.result.RunError = errors.New(msg) + return runner + } else { + filterRegexp = regexp + } + } + + for i := 0; i != suiteNumMethods; i++ { + method := newMethod(suiteValue, i) + switch method.Info.Name { + case "SetUpSuite": + runner.setUpSuite = method + case "TearDownSuite": + runner.tearDownSuite = method + case "SetUpTest": + runner.setUpTest = method + case "TearDownTest": + runner.tearDownTest = method + default: + prefix := "Test" + if conf.Benchmark { + prefix = "Benchmark" + } + if !strings.HasPrefix(method.Info.Name, prefix) { + continue + } + if filterRegexp == nil || method.matches(filterRegexp) { + runner.tests = append(runner.tests, method) + } + } + } + return runner +} + +// Run all methods in the given suite. +func (runner *suiteRunner) run() *Result { + if runner.tracker.result.RunError == nil && len(runner.tests) > 0 { + runner.tracker.start() + if runner.checkFixtureArgs() { + c := runner.runFixture(runner.setUpSuite, "", nil) + if c == nil || c.status == succeededSt { + for i := 0; i != len(runner.tests); i++ { + c := runner.runTest(runner.tests[i]) + if c.status == fixturePanickedSt { + runner.skipTests(missedSt, runner.tests[i+1:]) + break + } + } + } else if c != nil && c.status == skippedSt { + runner.skipTests(skippedSt, runner.tests) + } else { + runner.skipTests(missedSt, runner.tests) + } + runner.runFixture(runner.tearDownSuite, "", nil) + } else { + runner.skipTests(missedSt, runner.tests) + } + runner.tracker.waitAndStop() + if runner.keepDir { + runner.tracker.result.WorkDir = runner.tempDir.path + } else { + runner.tempDir.removeAll() + } + } + return &runner.tracker.result +} + +// Create a call object with the given suite method, and fork a +// goroutine with the provided dispatcher for running it. +func (runner *suiteRunner) forkCall(method *methodType, kind funcKind, testName string, logb *logger, dispatcher func(c *C)) *C { + var logw io.Writer + if runner.output.Stream { + logw = runner.output + } + if logb == nil { + logb = new(logger) + } + c := &C{ + method: method, + kind: kind, + testName: testName, + logb: logb, + logw: logw, + tempDir: runner.tempDir, + done: make(chan *C, 1), + timer: timer{benchTime: runner.benchTime}, + startTime: time.Now(), + benchMem: runner.benchMem, + } + runner.tracker.expectCall(c) + go (func() { + runner.reportCallStarted(c) + defer runner.callDone(c) + dispatcher(c) + })() + return c +} + +// Same as forkCall(), but wait for call to finish before returning. +func (runner *suiteRunner) runFunc(method *methodType, kind funcKind, testName string, logb *logger, dispatcher func(c *C)) *C { + c := runner.forkCall(method, kind, testName, logb, dispatcher) + <-c.done + return c +} + +// Handle a finished call. If there were any panics, update the call status +// accordingly. Then, mark the call as done and report to the tracker. +func (runner *suiteRunner) callDone(c *C) { + value := recover() + if value != nil { + switch v := value.(type) { + case *fixturePanic: + if v.status == skippedSt { + c.status = skippedSt + } else { + c.logSoftPanic("Fixture has panicked (see related PANIC)") + c.status = fixturePanickedSt + } + default: + c.logPanic(1, value) + c.status = panickedSt + } + } + if c.mustFail { + switch c.status { + case failedSt: + c.status = succeededSt + case succeededSt: + c.status = failedSt + c.logString("Error: Test succeeded, but was expected to fail") + c.logString("Reason: " + c.reason) + } + } + + runner.reportCallDone(c) + c.done <- c +} + +// Runs a fixture call synchronously. The fixture will still be run in a +// goroutine like all suite methods, but this method will not return +// while the fixture goroutine is not done, because the fixture must be +// run in a desired order. +func (runner *suiteRunner) runFixture(method *methodType, testName string, logb *logger) *C { + if method != nil { + c := runner.runFunc(method, fixtureKd, testName, logb, func(c *C) { + c.ResetTimer() + c.StartTimer() + defer c.StopTimer() + c.method.Call([]reflect.Value{reflect.ValueOf(c)}) + }) + return c + } + return nil +} + +// Run the fixture method with runFixture(), but panic with a fixturePanic{} +// in case the fixture method panics. This makes it easier to track the +// fixture panic together with other call panics within forkTest(). +func (runner *suiteRunner) runFixtureWithPanic(method *methodType, testName string, logb *logger, skipped *bool) *C { + if skipped != nil && *skipped { + return nil + } + c := runner.runFixture(method, testName, logb) + if c != nil && c.status != succeededSt { + if skipped != nil { + *skipped = c.status == skippedSt + } + panic(&fixturePanic{c.status, method}) + } + return c +} + +type fixturePanic struct { + status funcStatus + method *methodType +} + +// Run the suite test method, together with the test-specific fixture, +// asynchronously. +func (runner *suiteRunner) forkTest(method *methodType) *C { + testName := method.String() + return runner.forkCall(method, testKd, testName, nil, func(c *C) { + var skipped bool + defer runner.runFixtureWithPanic(runner.tearDownTest, testName, nil, &skipped) + defer c.StopTimer() + benchN := 1 + for { + runner.runFixtureWithPanic(runner.setUpTest, testName, c.logb, &skipped) + mt := c.method.Type() + if mt.NumIn() != 1 || mt.In(0) != reflect.TypeOf(c) { + // Rather than a plain panic, provide a more helpful message when + // the argument type is incorrect. + c.status = panickedSt + c.logArgPanic(c.method, "*check.C") + return + } + if strings.HasPrefix(c.method.Info.Name, "Test") { + c.ResetTimer() + c.StartTimer() + c.method.Call([]reflect.Value{reflect.ValueOf(c)}) + return + } + if !strings.HasPrefix(c.method.Info.Name, "Benchmark") { + panic("unexpected method prefix: " + c.method.Info.Name) + } + + runtime.GC() + c.N = benchN + c.ResetTimer() + c.StartTimer() + c.method.Call([]reflect.Value{reflect.ValueOf(c)}) + c.StopTimer() + if c.status != succeededSt || c.duration >= c.benchTime || benchN >= 1e9 { + return + } + perOpN := int(1e9) + if c.nsPerOp() != 0 { + perOpN = int(c.benchTime.Nanoseconds() / c.nsPerOp()) + } + + // Logic taken from the stock testing package: + // - Run more iterations than we think we'll need for a second (1.5x). + // - Don't grow too fast in case we had timing errors previously. + // - Be sure to run at least one more than last time. + benchN = max(min(perOpN+perOpN/2, 100*benchN), benchN+1) + benchN = roundUp(benchN) + + skipped = true // Don't run the deferred one if this panics. + runner.runFixtureWithPanic(runner.tearDownTest, testName, nil, nil) + skipped = false + } + }) +} + +// Same as forkTest(), but wait for the test to finish before returning. +func (runner *suiteRunner) runTest(method *methodType) *C { + c := runner.forkTest(method) + <-c.done + return c +} + +// Helper to mark tests as skipped or missed. A bit heavy for what +// it does, but it enables homogeneous handling of tracking, including +// nice verbose output. +func (runner *suiteRunner) skipTests(status funcStatus, methods []*methodType) { + for _, method := range methods { + runner.runFunc(method, testKd, "", nil, func(c *C) { + c.status = status + }) + } +} + +// Verify if the fixture arguments are *check.C. In case of errors, +// log the error as a panic in the fixture method call, and return false. +func (runner *suiteRunner) checkFixtureArgs() bool { + succeeded := true + argType := reflect.TypeOf(&C{}) + for _, method := range []*methodType{runner.setUpSuite, runner.tearDownSuite, runner.setUpTest, runner.tearDownTest} { + if method != nil { + mt := method.Type() + if mt.NumIn() != 1 || mt.In(0) != argType { + succeeded = false + runner.runFunc(method, fixtureKd, "", nil, func(c *C) { + c.logArgPanic(method, "*check.C") + c.status = panickedSt + }) + } + } + } + return succeeded +} + +func (runner *suiteRunner) reportCallStarted(c *C) { + runner.output.WriteCallStarted("START", c) +} + +func (runner *suiteRunner) reportCallDone(c *C) { + runner.tracker.callDone(c) + switch c.status { + case succeededSt: + if c.mustFail { + runner.output.WriteCallSuccess("FAIL EXPECTED", c) + } else { + runner.output.WriteCallSuccess("PASS", c) + } + case skippedSt: + runner.output.WriteCallSuccess("SKIP", c) + case failedSt: + runner.output.WriteCallProblem("FAIL", c) + case panickedSt: + runner.output.WriteCallProblem("PANIC", c) + case fixturePanickedSt: + // That's a testKd call reporting that its fixture + // has panicked. The fixture call which caused the + // panic itself was tracked above. We'll report to + // aid debugging. + runner.output.WriteCallProblem("PANIC", c) + case missedSt: + runner.output.WriteCallSuccess("MISS", c) + } +} + +// ----------------------------------------------------------------------- +// Output writer manages atomic output writing according to settings. + +type outputWriter struct { + m sync.Mutex + writer io.Writer + wroteCallProblemLast bool + Stream bool + Verbose bool +} + +func newOutputWriter(writer io.Writer, stream, verbose bool) *outputWriter { + return &outputWriter{writer: writer, Stream: stream, Verbose: verbose} +} + +func (ow *outputWriter) Write(content []byte) (n int, err error) { + ow.m.Lock() + n, err = ow.writer.Write(content) + ow.m.Unlock() + return +} + +func (ow *outputWriter) WriteCallStarted(label string, c *C) { + if ow.Stream { + header := renderCallHeader(label, c, "", "\n") + ow.m.Lock() + ow.writer.Write([]byte(header)) + ow.m.Unlock() + } +} + +func (ow *outputWriter) WriteCallProblem(label string, c *C) { + var prefix string + if !ow.Stream { + prefix = "\n-----------------------------------" + + "-----------------------------------\n" + } + header := renderCallHeader(label, c, prefix, "\n\n") + ow.m.Lock() + ow.wroteCallProblemLast = true + ow.writer.Write([]byte(header)) + if !ow.Stream { + c.logb.WriteTo(ow.writer) + } + ow.m.Unlock() +} + +func (ow *outputWriter) WriteCallSuccess(label string, c *C) { + if ow.Stream || (ow.Verbose && c.kind == testKd) { + // TODO Use a buffer here. + var suffix string + if c.reason != "" { + suffix = " (" + c.reason + ")" + } + if c.status == succeededSt { + suffix += "\t" + c.timerString() + } + suffix += "\n" + if ow.Stream { + suffix += "\n" + } + header := renderCallHeader(label, c, "", suffix) + ow.m.Lock() + // Resist temptation of using line as prefix above due to race. + if !ow.Stream && ow.wroteCallProblemLast { + header = "\n-----------------------------------" + + "-----------------------------------\n" + + header + } + ow.wroteCallProblemLast = false + ow.writer.Write([]byte(header)) + ow.m.Unlock() + } +} + +func renderCallHeader(label string, c *C, prefix, suffix string) string { + pc := c.method.PC() + return fmt.Sprintf("%s%s: %s: %s%s", prefix, label, niceFuncPath(pc), + niceFuncName(pc), suffix) +} diff --git a/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/check_test.go b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/check_test.go new file mode 100644 index 000000000..871b32527 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/check_test.go @@ -0,0 +1,207 @@ +// This file contains just a few generic helpers which are used by the +// other test files. + +package check_test + +import ( + "flag" + "fmt" + "os" + "regexp" + "runtime" + "testing" + "time" + + "gopkg.in/check.v1" +) + +// We count the number of suites run at least to get a vague hint that the +// test suite is behaving as it should. Otherwise a bug introduced at the +// very core of the system could go unperceived. +const suitesRunExpected = 8 + +var suitesRun int = 0 + +func Test(t *testing.T) { + check.TestingT(t) + if suitesRun != suitesRunExpected && flag.Lookup("check.f").Value.String() == "" { + critical(fmt.Sprintf("Expected %d suites to run rather than %d", + suitesRunExpected, suitesRun)) + } +} + +// ----------------------------------------------------------------------- +// Helper functions. + +// Break down badly. This is used in test cases which can't yet assume +// that the fundamental bits are working. +func critical(error string) { + fmt.Fprintln(os.Stderr, "CRITICAL: "+error) + os.Exit(1) +} + +// Return the file line where it's called. +func getMyLine() int { + if _, _, line, ok := runtime.Caller(1); ok { + return line + } + return -1 +} + +// ----------------------------------------------------------------------- +// Helper type implementing a basic io.Writer for testing output. + +// Type implementing the io.Writer interface for analyzing output. +type String struct { + value string +} + +// The only function required by the io.Writer interface. Will append +// written data to the String.value string. +func (s *String) Write(p []byte) (n int, err error) { + s.value += string(p) + return len(p), nil +} + +// Trivial wrapper to test errors happening on a different file +// than the test itself. +func checkEqualWrapper(c *check.C, obtained, expected interface{}) (result bool, line int) { + return c.Check(obtained, check.Equals, expected), getMyLine() +} + +// ----------------------------------------------------------------------- +// Helper suite for testing basic fail behavior. + +type FailHelper struct { + testLine int +} + +func (s *FailHelper) TestLogAndFail(c *check.C) { + s.testLine = getMyLine() - 1 + c.Log("Expected failure!") + c.Fail() +} + +// ----------------------------------------------------------------------- +// Helper suite for testing basic success behavior. + +type SuccessHelper struct{} + +func (s *SuccessHelper) TestLogAndSucceed(c *check.C) { + c.Log("Expected success!") +} + +// ----------------------------------------------------------------------- +// Helper suite for testing ordering and behavior of fixture. + +type FixtureHelper struct { + calls []string + panicOn string + skip bool + skipOnN int + sleepOn string + sleep time.Duration + bytes int64 +} + +func (s *FixtureHelper) trace(name string, c *check.C) { + s.calls = append(s.calls, name) + if name == s.panicOn { + panic(name) + } + if s.sleep > 0 && s.sleepOn == name { + time.Sleep(s.sleep) + } + if s.skip && s.skipOnN == len(s.calls)-1 { + c.Skip("skipOnN == n") + } +} + +func (s *FixtureHelper) SetUpSuite(c *check.C) { + s.trace("SetUpSuite", c) +} + +func (s *FixtureHelper) TearDownSuite(c *check.C) { + s.trace("TearDownSuite", c) +} + +func (s *FixtureHelper) SetUpTest(c *check.C) { + s.trace("SetUpTest", c) +} + +func (s *FixtureHelper) TearDownTest(c *check.C) { + s.trace("TearDownTest", c) +} + +func (s *FixtureHelper) Test1(c *check.C) { + s.trace("Test1", c) +} + +func (s *FixtureHelper) Test2(c *check.C) { + s.trace("Test2", c) +} + +func (s *FixtureHelper) Benchmark1(c *check.C) { + s.trace("Benchmark1", c) + for i := 0; i < c.N; i++ { + time.Sleep(s.sleep) + } +} + +func (s *FixtureHelper) Benchmark2(c *check.C) { + s.trace("Benchmark2", c) + c.SetBytes(1024) + for i := 0; i < c.N; i++ { + time.Sleep(s.sleep) + } +} + +func (s *FixtureHelper) Benchmark3(c *check.C) { + var x []int64 + s.trace("Benchmark3", c) + for i := 0; i < c.N; i++ { + time.Sleep(s.sleep) + x = make([]int64, 5) + _ = x + } +} + +// ----------------------------------------------------------------------- +// Helper which checks the state of the test and ensures that it matches +// the given expectations. Depends on c.Errorf() working, so shouldn't +// be used to test this one function. + +type expectedState struct { + name string + result interface{} + failed bool + log string +} + +// Verify the state of the test. Note that since this also verifies if +// the test is supposed to be in a failed state, no other checks should +// be done in addition to what is being tested. +func checkState(c *check.C, result interface{}, expected *expectedState) { + failed := c.Failed() + c.Succeed() + log := c.GetTestLog() + matched, matchError := regexp.MatchString("^"+expected.log+"$", log) + if matchError != nil { + c.Errorf("Error in matching expression used in testing %s", + expected.name) + } else if !matched { + c.Errorf("%s logged:\n----------\n%s----------\n\nExpected:\n----------\n%s\n----------", + expected.name, log, expected.log) + } + if result != expected.result { + c.Errorf("%s returned %#v rather than %#v", + expected.name, result, expected.result) + } + if failed != expected.failed { + if failed { + c.Errorf("%s has failed when it shouldn't", expected.name) + } else { + c.Errorf("%s has not failed when it should", expected.name) + } + } +} diff --git a/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/checkers.go b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/checkers.go new file mode 100644 index 000000000..bac338729 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/checkers.go @@ -0,0 +1,458 @@ +package check + +import ( + "fmt" + "reflect" + "regexp" +) + +// ----------------------------------------------------------------------- +// CommentInterface and Commentf helper, to attach extra information to checks. + +type comment struct { + format string + args []interface{} +} + +// Commentf returns an infomational value to use with Assert or Check calls. +// If the checker test fails, the provided arguments will be passed to +// fmt.Sprintf, and will be presented next to the logged failure. +// +// For example: +// +// c.Assert(v, Equals, 42, Commentf("Iteration #%d failed.", i)) +// +// Note that if the comment is constant, a better option is to +// simply use a normal comment right above or next to the line, as +// it will also get printed with any errors: +// +// c.Assert(l, Equals, 8192) // Ensure buffer size is correct (bug #123) +// +func Commentf(format string, args ...interface{}) CommentInterface { + return &comment{format, args} +} + +// CommentInterface must be implemented by types that attach extra +// information to failed checks. See the Commentf function for details. +type CommentInterface interface { + CheckCommentString() string +} + +func (c *comment) CheckCommentString() string { + return fmt.Sprintf(c.format, c.args...) +} + +// ----------------------------------------------------------------------- +// The Checker interface. + +// The Checker interface must be provided by checkers used with +// the Assert and Check verification methods. +type Checker interface { + Info() *CheckerInfo + Check(params []interface{}, names []string) (result bool, error string) +} + +// See the Checker interface. +type CheckerInfo struct { + Name string + Params []string +} + +func (info *CheckerInfo) Info() *CheckerInfo { + return info +} + +// ----------------------------------------------------------------------- +// Not checker logic inverter. + +// The Not checker inverts the logic of the provided checker. The +// resulting checker will succeed where the original one failed, and +// vice-versa. +// +// For example: +// +// c.Assert(a, Not(Equals), b) +// +func Not(checker Checker) Checker { + return ¬Checker{checker} +} + +type notChecker struct { + sub Checker +} + +func (checker *notChecker) Info() *CheckerInfo { + info := *checker.sub.Info() + info.Name = "Not(" + info.Name + ")" + return &info +} + +func (checker *notChecker) Check(params []interface{}, names []string) (result bool, error string) { + result, error = checker.sub.Check(params, names) + result = !result + return +} + +// ----------------------------------------------------------------------- +// IsNil checker. + +type isNilChecker struct { + *CheckerInfo +} + +// The IsNil checker tests whether the obtained value is nil. +// +// For example: +// +// c.Assert(err, IsNil) +// +var IsNil Checker = &isNilChecker{ + &CheckerInfo{Name: "IsNil", Params: []string{"value"}}, +} + +func (checker *isNilChecker) Check(params []interface{}, names []string) (result bool, error string) { + return isNil(params[0]), "" +} + +func isNil(obtained interface{}) (result bool) { + if obtained == nil { + result = true + } else { + switch v := reflect.ValueOf(obtained); v.Kind() { + case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: + return v.IsNil() + } + } + return +} + +// ----------------------------------------------------------------------- +// NotNil checker. Alias for Not(IsNil), since it's so common. + +type notNilChecker struct { + *CheckerInfo +} + +// The NotNil checker verifies that the obtained value is not nil. +// +// For example: +// +// c.Assert(iface, NotNil) +// +// This is an alias for Not(IsNil), made available since it's a +// fairly common check. +// +var NotNil Checker = ¬NilChecker{ + &CheckerInfo{Name: "NotNil", Params: []string{"value"}}, +} + +func (checker *notNilChecker) Check(params []interface{}, names []string) (result bool, error string) { + return !isNil(params[0]), "" +} + +// ----------------------------------------------------------------------- +// Equals checker. + +type equalsChecker struct { + *CheckerInfo +} + +// The Equals checker verifies that the obtained value is equal to +// the expected value, according to usual Go semantics for ==. +// +// For example: +// +// c.Assert(value, Equals, 42) +// +var Equals Checker = &equalsChecker{ + &CheckerInfo{Name: "Equals", Params: []string{"obtained", "expected"}}, +} + +func (checker *equalsChecker) Check(params []interface{}, names []string) (result bool, error string) { + defer func() { + if v := recover(); v != nil { + result = false + error = fmt.Sprint(v) + } + }() + return params[0] == params[1], "" +} + +// ----------------------------------------------------------------------- +// DeepEquals checker. + +type deepEqualsChecker struct { + *CheckerInfo +} + +// The DeepEquals checker verifies that the obtained value is deep-equal to +// the expected value. The check will work correctly even when facing +// slices, interfaces, and values of different types (which always fail +// the test). +// +// For example: +// +// c.Assert(value, DeepEquals, 42) +// c.Assert(array, DeepEquals, []string{"hi", "there"}) +// +var DeepEquals Checker = &deepEqualsChecker{ + &CheckerInfo{Name: "DeepEquals", Params: []string{"obtained", "expected"}}, +} + +func (checker *deepEqualsChecker) Check(params []interface{}, names []string) (result bool, error string) { + return reflect.DeepEqual(params[0], params[1]), "" +} + +// ----------------------------------------------------------------------- +// HasLen checker. + +type hasLenChecker struct { + *CheckerInfo +} + +// The HasLen checker verifies that the obtained value has the +// provided length. In many cases this is superior to using Equals +// in conjuction with the len function because in case the check +// fails the value itself will be printed, instead of its length, +// providing more details for figuring the problem. +// +// For example: +// +// c.Assert(list, HasLen, 5) +// +var HasLen Checker = &hasLenChecker{ + &CheckerInfo{Name: "HasLen", Params: []string{"obtained", "n"}}, +} + +func (checker *hasLenChecker) Check(params []interface{}, names []string) (result bool, error string) { + n, ok := params[1].(int) + if !ok { + return false, "n must be an int" + } + value := reflect.ValueOf(params[0]) + switch value.Kind() { + case reflect.Map, reflect.Array, reflect.Slice, reflect.Chan, reflect.String: + default: + return false, "obtained value type has no length" + } + return value.Len() == n, "" +} + +// ----------------------------------------------------------------------- +// ErrorMatches checker. + +type errorMatchesChecker struct { + *CheckerInfo +} + +// The ErrorMatches checker verifies that the error value +// is non nil and matches the regular expression provided. +// +// For example: +// +// c.Assert(err, ErrorMatches, "perm.*denied") +// +var ErrorMatches Checker = errorMatchesChecker{ + &CheckerInfo{Name: "ErrorMatches", Params: []string{"value", "regex"}}, +} + +func (checker errorMatchesChecker) Check(params []interface{}, names []string) (result bool, errStr string) { + if params[0] == nil { + return false, "Error value is nil" + } + err, ok := params[0].(error) + if !ok { + return false, "Value is not an error" + } + params[0] = err.Error() + names[0] = "error" + return matches(params[0], params[1]) +} + +// ----------------------------------------------------------------------- +// Matches checker. + +type matchesChecker struct { + *CheckerInfo +} + +// The Matches checker verifies that the string provided as the obtained +// value (or the string resulting from obtained.String()) matches the +// regular expression provided. +// +// For example: +// +// c.Assert(err, Matches, "perm.*denied") +// +var Matches Checker = &matchesChecker{ + &CheckerInfo{Name: "Matches", Params: []string{"value", "regex"}}, +} + +func (checker *matchesChecker) Check(params []interface{}, names []string) (result bool, error string) { + return matches(params[0], params[1]) +} + +func matches(value, regex interface{}) (result bool, error string) { + reStr, ok := regex.(string) + if !ok { + return false, "Regex must be a string" + } + valueStr, valueIsStr := value.(string) + if !valueIsStr { + if valueWithStr, valueHasStr := value.(fmt.Stringer); valueHasStr { + valueStr, valueIsStr = valueWithStr.String(), true + } + } + if valueIsStr { + matches, err := regexp.MatchString("^"+reStr+"$", valueStr) + if err != nil { + return false, "Can't compile regex: " + err.Error() + } + return matches, "" + } + return false, "Obtained value is not a string and has no .String()" +} + +// ----------------------------------------------------------------------- +// Panics checker. + +type panicsChecker struct { + *CheckerInfo +} + +// The Panics checker verifies that calling the provided zero-argument +// function will cause a panic which is deep-equal to the provided value. +// +// For example: +// +// c.Assert(func() { f(1, 2) }, Panics, &SomeErrorType{"BOOM"}). +// +// +var Panics Checker = &panicsChecker{ + &CheckerInfo{Name: "Panics", Params: []string{"function", "expected"}}, +} + +func (checker *panicsChecker) Check(params []interface{}, names []string) (result bool, error string) { + f := reflect.ValueOf(params[0]) + if f.Kind() != reflect.Func || f.Type().NumIn() != 0 { + return false, "Function must take zero arguments" + } + defer func() { + // If the function has not panicked, then don't do the check. + if error != "" { + return + } + params[0] = recover() + names[0] = "panic" + result = reflect.DeepEqual(params[0], params[1]) + }() + f.Call(nil) + return false, "Function has not panicked" +} + +type panicMatchesChecker struct { + *CheckerInfo +} + +// The PanicMatches checker verifies that calling the provided zero-argument +// function will cause a panic with an error value matching +// the regular expression provided. +// +// For example: +// +// c.Assert(func() { f(1, 2) }, PanicMatches, `open.*: no such file or directory`). +// +// +var PanicMatches Checker = &panicMatchesChecker{ + &CheckerInfo{Name: "PanicMatches", Params: []string{"function", "expected"}}, +} + +func (checker *panicMatchesChecker) Check(params []interface{}, names []string) (result bool, errmsg string) { + f := reflect.ValueOf(params[0]) + if f.Kind() != reflect.Func || f.Type().NumIn() != 0 { + return false, "Function must take zero arguments" + } + defer func() { + // If the function has not panicked, then don't do the check. + if errmsg != "" { + return + } + obtained := recover() + names[0] = "panic" + if e, ok := obtained.(error); ok { + params[0] = e.Error() + } else if _, ok := obtained.(string); ok { + params[0] = obtained + } else { + errmsg = "Panic value is not a string or an error" + return + } + result, errmsg = matches(params[0], params[1]) + }() + f.Call(nil) + return false, "Function has not panicked" +} + +// ----------------------------------------------------------------------- +// FitsTypeOf checker. + +type fitsTypeChecker struct { + *CheckerInfo +} + +// The FitsTypeOf checker verifies that the obtained value is +// assignable to a variable with the same type as the provided +// sample value. +// +// For example: +// +// c.Assert(value, FitsTypeOf, int64(0)) +// c.Assert(value, FitsTypeOf, os.Error(nil)) +// +var FitsTypeOf Checker = &fitsTypeChecker{ + &CheckerInfo{Name: "FitsTypeOf", Params: []string{"obtained", "sample"}}, +} + +func (checker *fitsTypeChecker) Check(params []interface{}, names []string) (result bool, error string) { + obtained := reflect.ValueOf(params[0]) + sample := reflect.ValueOf(params[1]) + if !obtained.IsValid() { + return false, "" + } + if !sample.IsValid() { + return false, "Invalid sample value" + } + return obtained.Type().AssignableTo(sample.Type()), "" +} + +// ----------------------------------------------------------------------- +// Implements checker. + +type implementsChecker struct { + *CheckerInfo +} + +// The Implements checker verifies that the obtained value +// implements the interface specified via a pointer to an interface +// variable. +// +// For example: +// +// var e os.Error +// c.Assert(err, Implements, &e) +// +var Implements Checker = &implementsChecker{ + &CheckerInfo{Name: "Implements", Params: []string{"obtained", "ifaceptr"}}, +} + +func (checker *implementsChecker) Check(params []interface{}, names []string) (result bool, error string) { + obtained := reflect.ValueOf(params[0]) + ifaceptr := reflect.ValueOf(params[1]) + if !obtained.IsValid() { + return false, "" + } + if !ifaceptr.IsValid() || ifaceptr.Kind() != reflect.Ptr || ifaceptr.Elem().Kind() != reflect.Interface { + return false, "ifaceptr should be a pointer to an interface variable" + } + return obtained.Type().Implements(ifaceptr.Elem().Type()), "" +} diff --git a/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/checkers_test.go b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/checkers_test.go new file mode 100644 index 000000000..5c6974746 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/checkers_test.go @@ -0,0 +1,272 @@ +package check_test + +import ( + "errors" + "gopkg.in/check.v1" + "reflect" + "runtime" +) + +type CheckersS struct{} + +var _ = check.Suite(&CheckersS{}) + +func testInfo(c *check.C, checker check.Checker, name string, paramNames []string) { + info := checker.Info() + if info.Name != name { + c.Fatalf("Got name %s, expected %s", info.Name, name) + } + if !reflect.DeepEqual(info.Params, paramNames) { + c.Fatalf("Got param names %#v, expected %#v", info.Params, paramNames) + } +} + +func testCheck(c *check.C, checker check.Checker, result bool, error string, params ...interface{}) ([]interface{}, []string) { + info := checker.Info() + if len(params) != len(info.Params) { + c.Fatalf("unexpected param count in test; expected %d got %d", len(info.Params), len(params)) + } + names := append([]string{}, info.Params...) + result_, error_ := checker.Check(params, names) + if result_ != result || error_ != error { + c.Fatalf("%s.Check(%#v) returned (%#v, %#v) rather than (%#v, %#v)", + info.Name, params, result_, error_, result, error) + } + return params, names +} + +func (s *CheckersS) TestComment(c *check.C) { + bug := check.Commentf("a %d bc", 42) + comment := bug.CheckCommentString() + if comment != "a 42 bc" { + c.Fatalf("Commentf returned %#v", comment) + } +} + +func (s *CheckersS) TestIsNil(c *check.C) { + testInfo(c, check.IsNil, "IsNil", []string{"value"}) + + testCheck(c, check.IsNil, true, "", nil) + testCheck(c, check.IsNil, false, "", "a") + + testCheck(c, check.IsNil, true, "", (chan int)(nil)) + testCheck(c, check.IsNil, false, "", make(chan int)) + testCheck(c, check.IsNil, true, "", (error)(nil)) + testCheck(c, check.IsNil, false, "", errors.New("")) + testCheck(c, check.IsNil, true, "", ([]int)(nil)) + testCheck(c, check.IsNil, false, "", make([]int, 1)) + testCheck(c, check.IsNil, false, "", int(0)) +} + +func (s *CheckersS) TestNotNil(c *check.C) { + testInfo(c, check.NotNil, "NotNil", []string{"value"}) + + testCheck(c, check.NotNil, false, "", nil) + testCheck(c, check.NotNil, true, "", "a") + + testCheck(c, check.NotNil, false, "", (chan int)(nil)) + testCheck(c, check.NotNil, true, "", make(chan int)) + testCheck(c, check.NotNil, false, "", (error)(nil)) + testCheck(c, check.NotNil, true, "", errors.New("")) + testCheck(c, check.NotNil, false, "", ([]int)(nil)) + testCheck(c, check.NotNil, true, "", make([]int, 1)) +} + +func (s *CheckersS) TestNot(c *check.C) { + testInfo(c, check.Not(check.IsNil), "Not(IsNil)", []string{"value"}) + + testCheck(c, check.Not(check.IsNil), false, "", nil) + testCheck(c, check.Not(check.IsNil), true, "", "a") +} + +type simpleStruct struct { + i int +} + +func (s *CheckersS) TestEquals(c *check.C) { + testInfo(c, check.Equals, "Equals", []string{"obtained", "expected"}) + + // The simplest. + testCheck(c, check.Equals, true, "", 42, 42) + testCheck(c, check.Equals, false, "", 42, 43) + + // Different native types. + testCheck(c, check.Equals, false, "", int32(42), int64(42)) + + // With nil. + testCheck(c, check.Equals, false, "", 42, nil) + + // Slices + testCheck(c, check.Equals, false, "runtime error: comparing uncomparable type []uint8", []byte{1, 2}, []byte{1, 2}) + + // Struct values + testCheck(c, check.Equals, true, "", simpleStruct{1}, simpleStruct{1}) + testCheck(c, check.Equals, false, "", simpleStruct{1}, simpleStruct{2}) + + // Struct pointers + testCheck(c, check.Equals, false, "", &simpleStruct{1}, &simpleStruct{1}) + testCheck(c, check.Equals, false, "", &simpleStruct{1}, &simpleStruct{2}) +} + +func (s *CheckersS) TestDeepEquals(c *check.C) { + testInfo(c, check.DeepEquals, "DeepEquals", []string{"obtained", "expected"}) + + // The simplest. + testCheck(c, check.DeepEquals, true, "", 42, 42) + testCheck(c, check.DeepEquals, false, "", 42, 43) + + // Different native types. + testCheck(c, check.DeepEquals, false, "", int32(42), int64(42)) + + // With nil. + testCheck(c, check.DeepEquals, false, "", 42, nil) + + // Slices + testCheck(c, check.DeepEquals, true, "", []byte{1, 2}, []byte{1, 2}) + testCheck(c, check.DeepEquals, false, "", []byte{1, 2}, []byte{1, 3}) + + // Struct values + testCheck(c, check.DeepEquals, true, "", simpleStruct{1}, simpleStruct{1}) + testCheck(c, check.DeepEquals, false, "", simpleStruct{1}, simpleStruct{2}) + + // Struct pointers + testCheck(c, check.DeepEquals, true, "", &simpleStruct{1}, &simpleStruct{1}) + testCheck(c, check.DeepEquals, false, "", &simpleStruct{1}, &simpleStruct{2}) +} + +func (s *CheckersS) TestHasLen(c *check.C) { + testInfo(c, check.HasLen, "HasLen", []string{"obtained", "n"}) + + testCheck(c, check.HasLen, true, "", "abcd", 4) + testCheck(c, check.HasLen, true, "", []int{1, 2}, 2) + testCheck(c, check.HasLen, false, "", []int{1, 2}, 3) + + testCheck(c, check.HasLen, false, "n must be an int", []int{1, 2}, "2") + testCheck(c, check.HasLen, false, "obtained value type has no length", nil, 2) +} + +func (s *CheckersS) TestErrorMatches(c *check.C) { + testInfo(c, check.ErrorMatches, "ErrorMatches", []string{"value", "regex"}) + + testCheck(c, check.ErrorMatches, false, "Error value is nil", nil, "some error") + testCheck(c, check.ErrorMatches, false, "Value is not an error", 1, "some error") + testCheck(c, check.ErrorMatches, true, "", errors.New("some error"), "some error") + testCheck(c, check.ErrorMatches, true, "", errors.New("some error"), "so.*or") + + // Verify params mutation + params, names := testCheck(c, check.ErrorMatches, false, "", errors.New("some error"), "other error") + c.Assert(params[0], check.Equals, "some error") + c.Assert(names[0], check.Equals, "error") +} + +func (s *CheckersS) TestMatches(c *check.C) { + testInfo(c, check.Matches, "Matches", []string{"value", "regex"}) + + // Simple matching + testCheck(c, check.Matches, true, "", "abc", "abc") + testCheck(c, check.Matches, true, "", "abc", "a.c") + + // Must match fully + testCheck(c, check.Matches, false, "", "abc", "ab") + testCheck(c, check.Matches, false, "", "abc", "bc") + + // String()-enabled values accepted + testCheck(c, check.Matches, true, "", reflect.ValueOf("abc"), "a.c") + testCheck(c, check.Matches, false, "", reflect.ValueOf("abc"), "a.d") + + // Some error conditions. + testCheck(c, check.Matches, false, "Obtained value is not a string and has no .String()", 1, "a.c") + testCheck(c, check.Matches, false, "Can't compile regex: error parsing regexp: missing closing ]: `[c$`", "abc", "a[c") +} + +func (s *CheckersS) TestPanics(c *check.C) { + testInfo(c, check.Panics, "Panics", []string{"function", "expected"}) + + // Some errors. + testCheck(c, check.Panics, false, "Function has not panicked", func() bool { return false }, "BOOM") + testCheck(c, check.Panics, false, "Function must take zero arguments", 1, "BOOM") + + // Plain strings. + testCheck(c, check.Panics, true, "", func() { panic("BOOM") }, "BOOM") + testCheck(c, check.Panics, false, "", func() { panic("KABOOM") }, "BOOM") + testCheck(c, check.Panics, true, "", func() bool { panic("BOOM") }, "BOOM") + + // Error values. + testCheck(c, check.Panics, true, "", func() { panic(errors.New("BOOM")) }, errors.New("BOOM")) + testCheck(c, check.Panics, false, "", func() { panic(errors.New("KABOOM")) }, errors.New("BOOM")) + + type deep struct{ i int } + // Deep value + testCheck(c, check.Panics, true, "", func() { panic(&deep{99}) }, &deep{99}) + + // Verify params/names mutation + params, names := testCheck(c, check.Panics, false, "", func() { panic(errors.New("KABOOM")) }, errors.New("BOOM")) + c.Assert(params[0], check.ErrorMatches, "KABOOM") + c.Assert(names[0], check.Equals, "panic") + + // Verify a nil panic + testCheck(c, check.Panics, true, "", func() { panic(nil) }, nil) + testCheck(c, check.Panics, false, "", func() { panic(nil) }, "NOPE") +} + +func (s *CheckersS) TestPanicMatches(c *check.C) { + testInfo(c, check.PanicMatches, "PanicMatches", []string{"function", "expected"}) + + // Error matching. + testCheck(c, check.PanicMatches, true, "", func() { panic(errors.New("BOOM")) }, "BO.M") + testCheck(c, check.PanicMatches, false, "", func() { panic(errors.New("KABOOM")) }, "BO.M") + + // Some errors. + testCheck(c, check.PanicMatches, false, "Function has not panicked", func() bool { return false }, "BOOM") + testCheck(c, check.PanicMatches, false, "Function must take zero arguments", 1, "BOOM") + + // Plain strings. + testCheck(c, check.PanicMatches, true, "", func() { panic("BOOM") }, "BO.M") + testCheck(c, check.PanicMatches, false, "", func() { panic("KABOOM") }, "BOOM") + testCheck(c, check.PanicMatches, true, "", func() bool { panic("BOOM") }, "BO.M") + + // Verify params/names mutation + params, names := testCheck(c, check.PanicMatches, false, "", func() { panic(errors.New("KABOOM")) }, "BOOM") + c.Assert(params[0], check.Equals, "KABOOM") + c.Assert(names[0], check.Equals, "panic") + + // Verify a nil panic + testCheck(c, check.PanicMatches, false, "Panic value is not a string or an error", func() { panic(nil) }, "") +} + +func (s *CheckersS) TestFitsTypeOf(c *check.C) { + testInfo(c, check.FitsTypeOf, "FitsTypeOf", []string{"obtained", "sample"}) + + // Basic types + testCheck(c, check.FitsTypeOf, true, "", 1, 0) + testCheck(c, check.FitsTypeOf, false, "", 1, int64(0)) + + // Aliases + testCheck(c, check.FitsTypeOf, false, "", 1, errors.New("")) + testCheck(c, check.FitsTypeOf, false, "", "error", errors.New("")) + testCheck(c, check.FitsTypeOf, true, "", errors.New("error"), errors.New("")) + + // Structures + testCheck(c, check.FitsTypeOf, false, "", 1, simpleStruct{}) + testCheck(c, check.FitsTypeOf, false, "", simpleStruct{42}, &simpleStruct{}) + testCheck(c, check.FitsTypeOf, true, "", simpleStruct{42}, simpleStruct{}) + testCheck(c, check.FitsTypeOf, true, "", &simpleStruct{42}, &simpleStruct{}) + + // Some bad values + testCheck(c, check.FitsTypeOf, false, "Invalid sample value", 1, interface{}(nil)) + testCheck(c, check.FitsTypeOf, false, "", interface{}(nil), 0) +} + +func (s *CheckersS) TestImplements(c *check.C) { + testInfo(c, check.Implements, "Implements", []string{"obtained", "ifaceptr"}) + + var e error + var re runtime.Error + testCheck(c, check.Implements, true, "", errors.New(""), &e) + testCheck(c, check.Implements, false, "", errors.New(""), &re) + + // Some bad values + testCheck(c, check.Implements, false, "ifaceptr should be a pointer to an interface variable", 0, errors.New("")) + testCheck(c, check.Implements, false, "ifaceptr should be a pointer to an interface variable", 0, interface{}(nil)) + testCheck(c, check.Implements, false, "", interface{}(nil), &e) +} diff --git a/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/export_test.go b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/export_test.go new file mode 100644 index 000000000..0e6cfe0f2 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/export_test.go @@ -0,0 +1,9 @@ +package check + +func PrintLine(filename string, line int) (string, error) { + return printLine(filename, line) +} + +func Indent(s, with string) string { + return indent(s, with) +} diff --git a/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/fixture_test.go b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/fixture_test.go new file mode 100644 index 000000000..2bff9e163 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/fixture_test.go @@ -0,0 +1,484 @@ +// Tests for the behavior of the test fixture system. + +package check_test + +import ( + . "gopkg.in/check.v1" +) + +// ----------------------------------------------------------------------- +// Fixture test suite. + +type FixtureS struct{} + +var fixtureS = Suite(&FixtureS{}) + +func (s *FixtureS) TestCountSuite(c *C) { + suitesRun += 1 +} + +// ----------------------------------------------------------------------- +// Basic fixture ordering verification. + +func (s *FixtureS) TestOrder(c *C) { + helper := FixtureHelper{} + Run(&helper, nil) + c.Check(helper.calls[0], Equals, "SetUpSuite") + c.Check(helper.calls[1], Equals, "SetUpTest") + c.Check(helper.calls[2], Equals, "Test1") + c.Check(helper.calls[3], Equals, "TearDownTest") + c.Check(helper.calls[4], Equals, "SetUpTest") + c.Check(helper.calls[5], Equals, "Test2") + c.Check(helper.calls[6], Equals, "TearDownTest") + c.Check(helper.calls[7], Equals, "TearDownSuite") + c.Check(len(helper.calls), Equals, 8) +} + +// ----------------------------------------------------------------------- +// Check the behavior when panics occur within tests and fixtures. + +func (s *FixtureS) TestPanicOnTest(c *C) { + helper := FixtureHelper{panicOn: "Test1"} + output := String{} + Run(&helper, &RunConf{Output: &output}) + c.Check(helper.calls[0], Equals, "SetUpSuite") + c.Check(helper.calls[1], Equals, "SetUpTest") + c.Check(helper.calls[2], Equals, "Test1") + c.Check(helper.calls[3], Equals, "TearDownTest") + c.Check(helper.calls[4], Equals, "SetUpTest") + c.Check(helper.calls[5], Equals, "Test2") + c.Check(helper.calls[6], Equals, "TearDownTest") + c.Check(helper.calls[7], Equals, "TearDownSuite") + c.Check(len(helper.calls), Equals, 8) + + expected := "^\n-+\n" + + "PANIC: check_test\\.go:[0-9]+: FixtureHelper.Test1\n\n" + + "\\.\\.\\. Panic: Test1 \\(PC=[xA-F0-9]+\\)\n\n" + + ".+:[0-9]+\n" + + " in (go)?panic\n" + + ".*check_test.go:[0-9]+\n" + + " in FixtureHelper.trace\n" + + ".*check_test.go:[0-9]+\n" + + " in FixtureHelper.Test1\n" + + "(.|\n)*$" + + c.Check(output.value, Matches, expected) +} + +func (s *FixtureS) TestPanicOnSetUpTest(c *C) { + helper := FixtureHelper{panicOn: "SetUpTest"} + output := String{} + Run(&helper, &RunConf{Output: &output}) + c.Check(helper.calls[0], Equals, "SetUpSuite") + c.Check(helper.calls[1], Equals, "SetUpTest") + c.Check(helper.calls[2], Equals, "TearDownTest") + c.Check(helper.calls[3], Equals, "TearDownSuite") + c.Check(len(helper.calls), Equals, 4) + + expected := "^\n-+\n" + + "PANIC: check_test\\.go:[0-9]+: " + + "FixtureHelper\\.SetUpTest\n\n" + + "\\.\\.\\. Panic: SetUpTest \\(PC=[xA-F0-9]+\\)\n\n" + + ".+:[0-9]+\n" + + " in (go)?panic\n" + + ".*check_test.go:[0-9]+\n" + + " in FixtureHelper.trace\n" + + ".*check_test.go:[0-9]+\n" + + " in FixtureHelper.SetUpTest\n" + + "(.|\n)*" + + "\n-+\n" + + "PANIC: check_test\\.go:[0-9]+: " + + "FixtureHelper\\.Test1\n\n" + + "\\.\\.\\. Panic: Fixture has panicked " + + "\\(see related PANIC\\)\n$" + + c.Check(output.value, Matches, expected) +} + +func (s *FixtureS) TestPanicOnTearDownTest(c *C) { + helper := FixtureHelper{panicOn: "TearDownTest"} + output := String{} + Run(&helper, &RunConf{Output: &output}) + c.Check(helper.calls[0], Equals, "SetUpSuite") + c.Check(helper.calls[1], Equals, "SetUpTest") + c.Check(helper.calls[2], Equals, "Test1") + c.Check(helper.calls[3], Equals, "TearDownTest") + c.Check(helper.calls[4], Equals, "TearDownSuite") + c.Check(len(helper.calls), Equals, 5) + + expected := "^\n-+\n" + + "PANIC: check_test\\.go:[0-9]+: " + + "FixtureHelper.TearDownTest\n\n" + + "\\.\\.\\. Panic: TearDownTest \\(PC=[xA-F0-9]+\\)\n\n" + + ".+:[0-9]+\n" + + " in (go)?panic\n" + + ".*check_test.go:[0-9]+\n" + + " in FixtureHelper.trace\n" + + ".*check_test.go:[0-9]+\n" + + " in FixtureHelper.TearDownTest\n" + + "(.|\n)*" + + "\n-+\n" + + "PANIC: check_test\\.go:[0-9]+: " + + "FixtureHelper\\.Test1\n\n" + + "\\.\\.\\. Panic: Fixture has panicked " + + "\\(see related PANIC\\)\n$" + + c.Check(output.value, Matches, expected) +} + +func (s *FixtureS) TestPanicOnSetUpSuite(c *C) { + helper := FixtureHelper{panicOn: "SetUpSuite"} + output := String{} + Run(&helper, &RunConf{Output: &output}) + c.Check(helper.calls[0], Equals, "SetUpSuite") + c.Check(helper.calls[1], Equals, "TearDownSuite") + c.Check(len(helper.calls), Equals, 2) + + expected := "^\n-+\n" + + "PANIC: check_test\\.go:[0-9]+: " + + "FixtureHelper.SetUpSuite\n\n" + + "\\.\\.\\. Panic: SetUpSuite \\(PC=[xA-F0-9]+\\)\n\n" + + ".+:[0-9]+\n" + + " in (go)?panic\n" + + ".*check_test.go:[0-9]+\n" + + " in FixtureHelper.trace\n" + + ".*check_test.go:[0-9]+\n" + + " in FixtureHelper.SetUpSuite\n" + + "(.|\n)*$" + + c.Check(output.value, Matches, expected) +} + +func (s *FixtureS) TestPanicOnTearDownSuite(c *C) { + helper := FixtureHelper{panicOn: "TearDownSuite"} + output := String{} + Run(&helper, &RunConf{Output: &output}) + c.Check(helper.calls[0], Equals, "SetUpSuite") + c.Check(helper.calls[1], Equals, "SetUpTest") + c.Check(helper.calls[2], Equals, "Test1") + c.Check(helper.calls[3], Equals, "TearDownTest") + c.Check(helper.calls[4], Equals, "SetUpTest") + c.Check(helper.calls[5], Equals, "Test2") + c.Check(helper.calls[6], Equals, "TearDownTest") + c.Check(helper.calls[7], Equals, "TearDownSuite") + c.Check(len(helper.calls), Equals, 8) + + expected := "^\n-+\n" + + "PANIC: check_test\\.go:[0-9]+: " + + "FixtureHelper.TearDownSuite\n\n" + + "\\.\\.\\. Panic: TearDownSuite \\(PC=[xA-F0-9]+\\)\n\n" + + ".+:[0-9]+\n" + + " in (go)?panic\n" + + ".*check_test.go:[0-9]+\n" + + " in FixtureHelper.trace\n" + + ".*check_test.go:[0-9]+\n" + + " in FixtureHelper.TearDownSuite\n" + + "(.|\n)*$" + + c.Check(output.value, Matches, expected) +} + +// ----------------------------------------------------------------------- +// A wrong argument on a test or fixture will produce a nice error. + +func (s *FixtureS) TestPanicOnWrongTestArg(c *C) { + helper := WrongTestArgHelper{} + output := String{} + Run(&helper, &RunConf{Output: &output}) + c.Check(helper.calls[0], Equals, "SetUpSuite") + c.Check(helper.calls[1], Equals, "SetUpTest") + c.Check(helper.calls[2], Equals, "TearDownTest") + c.Check(helper.calls[3], Equals, "SetUpTest") + c.Check(helper.calls[4], Equals, "Test2") + c.Check(helper.calls[5], Equals, "TearDownTest") + c.Check(helper.calls[6], Equals, "TearDownSuite") + c.Check(len(helper.calls), Equals, 7) + + expected := "^\n-+\n" + + "PANIC: fixture_test\\.go:[0-9]+: " + + "WrongTestArgHelper\\.Test1\n\n" + + "\\.\\.\\. Panic: WrongTestArgHelper\\.Test1 argument " + + "should be \\*check\\.C\n" + + c.Check(output.value, Matches, expected) +} + +func (s *FixtureS) TestPanicOnWrongSetUpTestArg(c *C) { + helper := WrongSetUpTestArgHelper{} + output := String{} + Run(&helper, &RunConf{Output: &output}) + c.Check(len(helper.calls), Equals, 0) + + expected := + "^\n-+\n" + + "PANIC: fixture_test\\.go:[0-9]+: " + + "WrongSetUpTestArgHelper\\.SetUpTest\n\n" + + "\\.\\.\\. Panic: WrongSetUpTestArgHelper\\.SetUpTest argument " + + "should be \\*check\\.C\n" + + c.Check(output.value, Matches, expected) +} + +func (s *FixtureS) TestPanicOnWrongSetUpSuiteArg(c *C) { + helper := WrongSetUpSuiteArgHelper{} + output := String{} + Run(&helper, &RunConf{Output: &output}) + c.Check(len(helper.calls), Equals, 0) + + expected := + "^\n-+\n" + + "PANIC: fixture_test\\.go:[0-9]+: " + + "WrongSetUpSuiteArgHelper\\.SetUpSuite\n\n" + + "\\.\\.\\. Panic: WrongSetUpSuiteArgHelper\\.SetUpSuite argument " + + "should be \\*check\\.C\n" + + c.Check(output.value, Matches, expected) +} + +// ----------------------------------------------------------------------- +// Nice errors also when tests or fixture have wrong arg count. + +func (s *FixtureS) TestPanicOnWrongTestArgCount(c *C) { + helper := WrongTestArgCountHelper{} + output := String{} + Run(&helper, &RunConf{Output: &output}) + c.Check(helper.calls[0], Equals, "SetUpSuite") + c.Check(helper.calls[1], Equals, "SetUpTest") + c.Check(helper.calls[2], Equals, "TearDownTest") + c.Check(helper.calls[3], Equals, "SetUpTest") + c.Check(helper.calls[4], Equals, "Test2") + c.Check(helper.calls[5], Equals, "TearDownTest") + c.Check(helper.calls[6], Equals, "TearDownSuite") + c.Check(len(helper.calls), Equals, 7) + + expected := "^\n-+\n" + + "PANIC: fixture_test\\.go:[0-9]+: " + + "WrongTestArgCountHelper\\.Test1\n\n" + + "\\.\\.\\. Panic: WrongTestArgCountHelper\\.Test1 argument " + + "should be \\*check\\.C\n" + + c.Check(output.value, Matches, expected) +} + +func (s *FixtureS) TestPanicOnWrongSetUpTestArgCount(c *C) { + helper := WrongSetUpTestArgCountHelper{} + output := String{} + Run(&helper, &RunConf{Output: &output}) + c.Check(len(helper.calls), Equals, 0) + + expected := + "^\n-+\n" + + "PANIC: fixture_test\\.go:[0-9]+: " + + "WrongSetUpTestArgCountHelper\\.SetUpTest\n\n" + + "\\.\\.\\. Panic: WrongSetUpTestArgCountHelper\\.SetUpTest argument " + + "should be \\*check\\.C\n" + + c.Check(output.value, Matches, expected) +} + +func (s *FixtureS) TestPanicOnWrongSetUpSuiteArgCount(c *C) { + helper := WrongSetUpSuiteArgCountHelper{} + output := String{} + Run(&helper, &RunConf{Output: &output}) + c.Check(len(helper.calls), Equals, 0) + + expected := + "^\n-+\n" + + "PANIC: fixture_test\\.go:[0-9]+: " + + "WrongSetUpSuiteArgCountHelper\\.SetUpSuite\n\n" + + "\\.\\.\\. Panic: WrongSetUpSuiteArgCountHelper" + + "\\.SetUpSuite argument should be \\*check\\.C\n" + + c.Check(output.value, Matches, expected) +} + +// ----------------------------------------------------------------------- +// Helper test suites with wrong function arguments. + +type WrongTestArgHelper struct { + FixtureHelper +} + +func (s *WrongTestArgHelper) Test1(t int) { +} + +type WrongSetUpTestArgHelper struct { + FixtureHelper +} + +func (s *WrongSetUpTestArgHelper) SetUpTest(t int) { +} + +type WrongSetUpSuiteArgHelper struct { + FixtureHelper +} + +func (s *WrongSetUpSuiteArgHelper) SetUpSuite(t int) { +} + +type WrongTestArgCountHelper struct { + FixtureHelper +} + +func (s *WrongTestArgCountHelper) Test1(c *C, i int) { +} + +type WrongSetUpTestArgCountHelper struct { + FixtureHelper +} + +func (s *WrongSetUpTestArgCountHelper) SetUpTest(c *C, i int) { +} + +type WrongSetUpSuiteArgCountHelper struct { + FixtureHelper +} + +func (s *WrongSetUpSuiteArgCountHelper) SetUpSuite(c *C, i int) { +} + +// ----------------------------------------------------------------------- +// Ensure fixture doesn't run without tests. + +type NoTestsHelper struct { + hasRun bool +} + +func (s *NoTestsHelper) SetUpSuite(c *C) { + s.hasRun = true +} + +func (s *NoTestsHelper) TearDownSuite(c *C) { + s.hasRun = true +} + +func (s *FixtureS) TestFixtureDoesntRunWithoutTests(c *C) { + helper := NoTestsHelper{} + output := String{} + Run(&helper, &RunConf{Output: &output}) + c.Check(helper.hasRun, Equals, false) +} + +// ----------------------------------------------------------------------- +// Verify that checks and assertions work correctly inside the fixture. + +type FixtureCheckHelper struct { + fail string + completed bool +} + +func (s *FixtureCheckHelper) SetUpSuite(c *C) { + switch s.fail { + case "SetUpSuiteAssert": + c.Assert(false, Equals, true) + case "SetUpSuiteCheck": + c.Check(false, Equals, true) + } + s.completed = true +} + +func (s *FixtureCheckHelper) SetUpTest(c *C) { + switch s.fail { + case "SetUpTestAssert": + c.Assert(false, Equals, true) + case "SetUpTestCheck": + c.Check(false, Equals, true) + } + s.completed = true +} + +func (s *FixtureCheckHelper) Test(c *C) { + // Do nothing. +} + +func (s *FixtureS) TestSetUpSuiteCheck(c *C) { + helper := FixtureCheckHelper{fail: "SetUpSuiteCheck"} + output := String{} + Run(&helper, &RunConf{Output: &output}) + c.Assert(output.value, Matches, + "\n---+\n"+ + "FAIL: fixture_test\\.go:[0-9]+: "+ + "FixtureCheckHelper\\.SetUpSuite\n\n"+ + "fixture_test\\.go:[0-9]+:\n"+ + " c\\.Check\\(false, Equals, true\\)\n"+ + "\\.+ obtained bool = false\n"+ + "\\.+ expected bool = true\n\n") + c.Assert(helper.completed, Equals, true) +} + +func (s *FixtureS) TestSetUpSuiteAssert(c *C) { + helper := FixtureCheckHelper{fail: "SetUpSuiteAssert"} + output := String{} + Run(&helper, &RunConf{Output: &output}) + c.Assert(output.value, Matches, + "\n---+\n"+ + "FAIL: fixture_test\\.go:[0-9]+: "+ + "FixtureCheckHelper\\.SetUpSuite\n\n"+ + "fixture_test\\.go:[0-9]+:\n"+ + " c\\.Assert\\(false, Equals, true\\)\n"+ + "\\.+ obtained bool = false\n"+ + "\\.+ expected bool = true\n\n") + c.Assert(helper.completed, Equals, false) +} + +// ----------------------------------------------------------------------- +// Verify that logging within SetUpTest() persists within the test log itself. + +type FixtureLogHelper struct { + c *C +} + +func (s *FixtureLogHelper) SetUpTest(c *C) { + s.c = c + c.Log("1") +} + +func (s *FixtureLogHelper) Test(c *C) { + c.Log("2") + s.c.Log("3") + c.Log("4") + c.Fail() +} + +func (s *FixtureLogHelper) TearDownTest(c *C) { + s.c.Log("5") +} + +func (s *FixtureS) TestFixtureLogging(c *C) { + helper := FixtureLogHelper{} + output := String{} + Run(&helper, &RunConf{Output: &output}) + c.Assert(output.value, Matches, + "\n---+\n"+ + "FAIL: fixture_test\\.go:[0-9]+: "+ + "FixtureLogHelper\\.Test\n\n"+ + "1\n2\n3\n4\n5\n") +} + +// ----------------------------------------------------------------------- +// Skip() within fixture methods. + +func (s *FixtureS) TestSkipSuite(c *C) { + helper := FixtureHelper{skip: true, skipOnN: 0} + output := String{} + result := Run(&helper, &RunConf{Output: &output}) + c.Assert(output.value, Equals, "") + c.Assert(helper.calls[0], Equals, "SetUpSuite") + c.Assert(helper.calls[1], Equals, "TearDownSuite") + c.Assert(len(helper.calls), Equals, 2) + c.Assert(result.Skipped, Equals, 2) +} + +func (s *FixtureS) TestSkipTest(c *C) { + helper := FixtureHelper{skip: true, skipOnN: 1} + output := String{} + result := Run(&helper, &RunConf{Output: &output}) + c.Assert(helper.calls[0], Equals, "SetUpSuite") + c.Assert(helper.calls[1], Equals, "SetUpTest") + c.Assert(helper.calls[2], Equals, "SetUpTest") + c.Assert(helper.calls[3], Equals, "Test2") + c.Assert(helper.calls[4], Equals, "TearDownTest") + c.Assert(helper.calls[5], Equals, "TearDownSuite") + c.Assert(len(helper.calls), Equals, 6) + c.Assert(result.Skipped, Equals, 1) +} diff --git a/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/foundation_test.go b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/foundation_test.go new file mode 100644 index 000000000..8ecf7915f --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/foundation_test.go @@ -0,0 +1,335 @@ +// These tests check that the foundations of gocheck are working properly. +// They already assume that fundamental failing is working already, though, +// since this was tested in bootstrap_test.go. Even then, some care may +// still have to be taken when using external functions, since they should +// of course not rely on functionality tested here. + +package check_test + +import ( + "fmt" + "gopkg.in/check.v1" + "log" + "os" + "regexp" + "strings" +) + +// ----------------------------------------------------------------------- +// Foundation test suite. + +type FoundationS struct{} + +var foundationS = check.Suite(&FoundationS{}) + +func (s *FoundationS) TestCountSuite(c *check.C) { + suitesRun += 1 +} + +func (s *FoundationS) TestErrorf(c *check.C) { + // Do not use checkState() here. It depends on Errorf() working. + expectedLog := fmt.Sprintf("foundation_test.go:%d:\n"+ + " c.Errorf(\"Error %%v!\", \"message\")\n"+ + "... Error: Error message!\n\n", + getMyLine()+1) + c.Errorf("Error %v!", "message") + failed := c.Failed() + c.Succeed() + if log := c.GetTestLog(); log != expectedLog { + c.Logf("Errorf() logged %#v rather than %#v", log, expectedLog) + c.Fail() + } + if !failed { + c.Logf("Errorf() didn't put the test in a failed state") + c.Fail() + } +} + +func (s *FoundationS) TestError(c *check.C) { + expectedLog := fmt.Sprintf("foundation_test.go:%d:\n"+ + " c\\.Error\\(\"Error \", \"message!\"\\)\n"+ + "\\.\\.\\. Error: Error message!\n\n", + getMyLine()+1) + c.Error("Error ", "message!") + checkState(c, nil, + &expectedState{ + name: "Error(`Error `, `message!`)", + failed: true, + log: expectedLog, + }) +} + +func (s *FoundationS) TestFailNow(c *check.C) { + defer (func() { + if !c.Failed() { + c.Error("FailNow() didn't fail the test") + } else { + c.Succeed() + if c.GetTestLog() != "" { + c.Error("Something got logged:\n" + c.GetTestLog()) + } + } + })() + + c.FailNow() + c.Log("FailNow() didn't stop the test") +} + +func (s *FoundationS) TestSucceedNow(c *check.C) { + defer (func() { + if c.Failed() { + c.Error("SucceedNow() didn't succeed the test") + } + if c.GetTestLog() != "" { + c.Error("Something got logged:\n" + c.GetTestLog()) + } + })() + + c.Fail() + c.SucceedNow() + c.Log("SucceedNow() didn't stop the test") +} + +func (s *FoundationS) TestFailureHeader(c *check.C) { + output := String{} + failHelper := FailHelper{} + check.Run(&failHelper, &check.RunConf{Output: &output}) + header := fmt.Sprintf(""+ + "\n-----------------------------------"+ + "-----------------------------------\n"+ + "FAIL: check_test.go:%d: FailHelper.TestLogAndFail\n", + failHelper.testLine) + if strings.Index(output.value, header) == -1 { + c.Errorf(""+ + "Failure didn't print a proper header.\n"+ + "... Got:\n%s... Expected something with:\n%s", + output.value, header) + } +} + +func (s *FoundationS) TestFatal(c *check.C) { + var line int + defer (func() { + if !c.Failed() { + c.Error("Fatal() didn't fail the test") + } else { + c.Succeed() + expected := fmt.Sprintf("foundation_test.go:%d:\n"+ + " c.Fatal(\"Die \", \"now!\")\n"+ + "... Error: Die now!\n\n", + line) + if c.GetTestLog() != expected { + c.Error("Incorrect log:", c.GetTestLog()) + } + } + })() + + line = getMyLine() + 1 + c.Fatal("Die ", "now!") + c.Log("Fatal() didn't stop the test") +} + +func (s *FoundationS) TestFatalf(c *check.C) { + var line int + defer (func() { + if !c.Failed() { + c.Error("Fatalf() didn't fail the test") + } else { + c.Succeed() + expected := fmt.Sprintf("foundation_test.go:%d:\n"+ + " c.Fatalf(\"Die %%s!\", \"now\")\n"+ + "... Error: Die now!\n\n", + line) + if c.GetTestLog() != expected { + c.Error("Incorrect log:", c.GetTestLog()) + } + } + })() + + line = getMyLine() + 1 + c.Fatalf("Die %s!", "now") + c.Log("Fatalf() didn't stop the test") +} + +func (s *FoundationS) TestCallerLoggingInsideTest(c *check.C) { + log := fmt.Sprintf(""+ + "foundation_test.go:%d:\n"+ + " result := c.Check\\(10, check.Equals, 20\\)\n"+ + "\\.\\.\\. obtained int = 10\n"+ + "\\.\\.\\. expected int = 20\n\n", + getMyLine()+1) + result := c.Check(10, check.Equals, 20) + checkState(c, result, + &expectedState{ + name: "Check(10, Equals, 20)", + result: false, + failed: true, + log: log, + }) +} + +func (s *FoundationS) TestCallerLoggingInDifferentFile(c *check.C) { + result, line := checkEqualWrapper(c, 10, 20) + testLine := getMyLine() - 1 + log := fmt.Sprintf(""+ + "foundation_test.go:%d:\n"+ + " result, line := checkEqualWrapper\\(c, 10, 20\\)\n"+ + "check_test.go:%d:\n"+ + " return c.Check\\(obtained, check.Equals, expected\\), getMyLine\\(\\)\n"+ + "\\.\\.\\. obtained int = 10\n"+ + "\\.\\.\\. expected int = 20\n\n", + testLine, line) + checkState(c, result, + &expectedState{ + name: "Check(10, Equals, 20)", + result: false, + failed: true, + log: log, + }) +} + +// ----------------------------------------------------------------------- +// ExpectFailure() inverts the logic of failure. + +type ExpectFailureSucceedHelper struct{} + +func (s *ExpectFailureSucceedHelper) TestSucceed(c *check.C) { + c.ExpectFailure("It booms!") + c.Error("Boom!") +} + +type ExpectFailureFailHelper struct{} + +func (s *ExpectFailureFailHelper) TestFail(c *check.C) { + c.ExpectFailure("Bug #XYZ") +} + +func (s *FoundationS) TestExpectFailureFail(c *check.C) { + helper := ExpectFailureFailHelper{} + output := String{} + result := check.Run(&helper, &check.RunConf{Output: &output}) + + expected := "" + + "^\n-+\n" + + "FAIL: foundation_test\\.go:[0-9]+:" + + " ExpectFailureFailHelper\\.TestFail\n\n" + + "\\.\\.\\. Error: Test succeeded, but was expected to fail\n" + + "\\.\\.\\. Reason: Bug #XYZ\n$" + + matched, err := regexp.MatchString(expected, output.value) + if err != nil { + c.Error("Bad expression: ", expected) + } else if !matched { + c.Error("ExpectFailure() didn't log properly:\n", output.value) + } + + c.Assert(result.ExpectedFailures, check.Equals, 0) +} + +func (s *FoundationS) TestExpectFailureSucceed(c *check.C) { + helper := ExpectFailureSucceedHelper{} + output := String{} + result := check.Run(&helper, &check.RunConf{Output: &output}) + + c.Assert(output.value, check.Equals, "") + c.Assert(result.ExpectedFailures, check.Equals, 1) +} + +func (s *FoundationS) TestExpectFailureSucceedVerbose(c *check.C) { + helper := ExpectFailureSucceedHelper{} + output := String{} + result := check.Run(&helper, &check.RunConf{Output: &output, Verbose: true}) + + expected := "" + + "FAIL EXPECTED: foundation_test\\.go:[0-9]+:" + + " ExpectFailureSucceedHelper\\.TestSucceed \\(It booms!\\)\t *[.0-9]+s\n" + + matched, err := regexp.MatchString(expected, output.value) + if err != nil { + c.Error("Bad expression: ", expected) + } else if !matched { + c.Error("ExpectFailure() didn't log properly:\n", output.value) + } + + c.Assert(result.ExpectedFailures, check.Equals, 1) +} + +// ----------------------------------------------------------------------- +// Skip() allows stopping a test without positive/negative results. + +type SkipTestHelper struct{} + +func (s *SkipTestHelper) TestFail(c *check.C) { + c.Skip("Wrong platform or whatever") + c.Error("Boom!") +} + +func (s *FoundationS) TestSkip(c *check.C) { + helper := SkipTestHelper{} + output := String{} + check.Run(&helper, &check.RunConf{Output: &output}) + + if output.value != "" { + c.Error("Skip() logged something:\n", output.value) + } +} + +func (s *FoundationS) TestSkipVerbose(c *check.C) { + helper := SkipTestHelper{} + output := String{} + check.Run(&helper, &check.RunConf{Output: &output, Verbose: true}) + + expected := "SKIP: foundation_test\\.go:[0-9]+: SkipTestHelper\\.TestFail" + + " \\(Wrong platform or whatever\\)" + matched, err := regexp.MatchString(expected, output.value) + if err != nil { + c.Error("Bad expression: ", expected) + } else if !matched { + c.Error("Skip() didn't log properly:\n", output.value) + } +} + +// ----------------------------------------------------------------------- +// Check minimum *log.Logger interface provided by *check.C. + +type minLogger interface { + Output(calldepth int, s string) error +} + +func (s *BootstrapS) TestMinLogger(c *check.C) { + var logger minLogger + logger = log.New(os.Stderr, "", 0) + logger = c + logger.Output(0, "Hello there") + expected := `\[LOG\] [0-9]+:[0-9][0-9]\.[0-9][0-9][0-9] +Hello there\n` + output := c.GetTestLog() + c.Assert(output, check.Matches, expected) +} + +// ----------------------------------------------------------------------- +// Ensure that suites with embedded types are working fine, including the +// the workaround for issue 906. + +type EmbeddedInternalS struct { + called bool +} + +type EmbeddedS struct { + EmbeddedInternalS +} + +var embeddedS = check.Suite(&EmbeddedS{}) + +func (s *EmbeddedS) TestCountSuite(c *check.C) { + suitesRun += 1 +} + +func (s *EmbeddedInternalS) TestMethod(c *check.C) { + c.Error("TestMethod() of the embedded type was called!?") +} + +func (s *EmbeddedS) TestMethod(c *check.C) { + // http://code.google.com/p/go/issues/detail?id=906 + c.Check(s.called, check.Equals, false) // Go issue 906 is affecting the runner? + s.called = true +} diff --git a/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/helpers.go b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/helpers.go new file mode 100644 index 000000000..4b6c26da4 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/helpers.go @@ -0,0 +1,231 @@ +package check + +import ( + "fmt" + "strings" + "time" +) + +// TestName returns the current test name in the form "SuiteName.TestName" +func (c *C) TestName() string { + return c.testName +} + +// ----------------------------------------------------------------------- +// Basic succeeding/failing logic. + +// Failed returns whether the currently running test has already failed. +func (c *C) Failed() bool { + return c.status == failedSt +} + +// Fail marks the currently running test as failed. +// +// Something ought to have been previously logged so the developer can tell +// what went wrong. The higher level helper functions will fail the test +// and do the logging properly. +func (c *C) Fail() { + c.status = failedSt +} + +// FailNow marks the currently running test as failed and stops running it. +// Something ought to have been previously logged so the developer can tell +// what went wrong. The higher level helper functions will fail the test +// and do the logging properly. +func (c *C) FailNow() { + c.Fail() + c.stopNow() +} + +// Succeed marks the currently running test as succeeded, undoing any +// previous failures. +func (c *C) Succeed() { + c.status = succeededSt +} + +// SucceedNow marks the currently running test as succeeded, undoing any +// previous failures, and stops running the test. +func (c *C) SucceedNow() { + c.Succeed() + c.stopNow() +} + +// ExpectFailure informs that the running test is knowingly broken for +// the provided reason. If the test does not fail, an error will be reported +// to raise attention to this fact. This method is useful to temporarily +// disable tests which cover well known problems until a better time to +// fix the problem is found, without forgetting about the fact that a +// failure still exists. +func (c *C) ExpectFailure(reason string) { + if reason == "" { + panic("Missing reason why the test is expected to fail") + } + c.mustFail = true + c.reason = reason +} + +// Skip skips the running test for the provided reason. If run from within +// SetUpTest, the individual test being set up will be skipped, and if run +// from within SetUpSuite, the whole suite is skipped. +func (c *C) Skip(reason string) { + if reason == "" { + panic("Missing reason why the test is being skipped") + } + c.reason = reason + c.status = skippedSt + c.stopNow() +} + +// ----------------------------------------------------------------------- +// Basic logging. + +// GetTestLog returns the current test error output. +func (c *C) GetTestLog() string { + return c.logb.String() +} + +// Log logs some information into the test error output. +// The provided arguments are assembled together into a string with fmt.Sprint. +func (c *C) Log(args ...interface{}) { + c.log(args...) +} + +// Log logs some information into the test error output. +// The provided arguments are assembled together into a string with fmt.Sprintf. +func (c *C) Logf(format string, args ...interface{}) { + c.logf(format, args...) +} + +// Output enables *C to be used as a logger in functions that require only +// the minimum interface of *log.Logger. +func (c *C) Output(calldepth int, s string) error { + d := time.Now().Sub(c.startTime) + msec := d / time.Millisecond + sec := d / time.Second + min := d / time.Minute + + c.Logf("[LOG] %d:%02d.%03d %s", min, sec%60, msec%1000, s) + return nil +} + +// Error logs an error into the test error output and marks the test as failed. +// The provided arguments are assembled together into a string with fmt.Sprint. +func (c *C) Error(args ...interface{}) { + c.logCaller(1) + c.logString(fmt.Sprint("Error: ", fmt.Sprint(args...))) + c.logNewLine() + c.Fail() +} + +// Errorf logs an error into the test error output and marks the test as failed. +// The provided arguments are assembled together into a string with fmt.Sprintf. +func (c *C) Errorf(format string, args ...interface{}) { + c.logCaller(1) + c.logString(fmt.Sprintf("Error: "+format, args...)) + c.logNewLine() + c.Fail() +} + +// Fatal logs an error into the test error output, marks the test as failed, and +// stops the test execution. The provided arguments are assembled together into +// a string with fmt.Sprint. +func (c *C) Fatal(args ...interface{}) { + c.logCaller(1) + c.logString(fmt.Sprint("Error: ", fmt.Sprint(args...))) + c.logNewLine() + c.FailNow() +} + +// Fatlaf logs an error into the test error output, marks the test as failed, and +// stops the test execution. The provided arguments are assembled together into +// a string with fmt.Sprintf. +func (c *C) Fatalf(format string, args ...interface{}) { + c.logCaller(1) + c.logString(fmt.Sprint("Error: ", fmt.Sprintf(format, args...))) + c.logNewLine() + c.FailNow() +} + +// ----------------------------------------------------------------------- +// Generic checks and assertions based on checkers. + +// Check verifies if the first value matches the expected value according +// to the provided checker. If they do not match, an error is logged, the +// test is marked as failed, and the test execution continues. +// +// Some checkers may not need the expected argument (e.g. IsNil). +// +// Extra arguments provided to the function are logged next to the reported +// problem when the matching fails. +func (c *C) Check(obtained interface{}, checker Checker, args ...interface{}) bool { + return c.internalCheck("Check", obtained, checker, args...) +} + +// Assert ensures that the first value matches the expected value according +// to the provided checker. If they do not match, an error is logged, the +// test is marked as failed, and the test execution stops. +// +// Some checkers may not need the expected argument (e.g. IsNil). +// +// Extra arguments provided to the function are logged next to the reported +// problem when the matching fails. +func (c *C) Assert(obtained interface{}, checker Checker, args ...interface{}) { + if !c.internalCheck("Assert", obtained, checker, args...) { + c.stopNow() + } +} + +func (c *C) internalCheck(funcName string, obtained interface{}, checker Checker, args ...interface{}) bool { + if checker == nil { + c.logCaller(2) + c.logString(fmt.Sprintf("%s(obtained, nil!?, ...):", funcName)) + c.logString("Oops.. you've provided a nil checker!") + c.logNewLine() + c.Fail() + return false + } + + // If the last argument is a bug info, extract it out. + var comment CommentInterface + if len(args) > 0 { + if c, ok := args[len(args)-1].(CommentInterface); ok { + comment = c + args = args[:len(args)-1] + } + } + + params := append([]interface{}{obtained}, args...) + info := checker.Info() + + if len(params) != len(info.Params) { + names := append([]string{info.Params[0], info.Name}, info.Params[1:]...) + c.logCaller(2) + c.logString(fmt.Sprintf("%s(%s):", funcName, strings.Join(names, ", "))) + c.logString(fmt.Sprintf("Wrong number of parameters for %s: want %d, got %d", info.Name, len(names), len(params)+1)) + c.logNewLine() + c.Fail() + return false + } + + // Copy since it may be mutated by Check. + names := append([]string{}, info.Params...) + + // Do the actual check. + result, error := checker.Check(params, names) + if !result || error != "" { + c.logCaller(2) + for i := 0; i != len(params); i++ { + c.logValue(names[i], params[i]) + } + if comment != nil { + c.logString(comment.CheckCommentString()) + } + if error != "" { + c.logString(error) + } + c.logNewLine() + c.Fail() + return false + } + return true +} diff --git a/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/helpers_test.go b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/helpers_test.go new file mode 100644 index 000000000..4baa656ba --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/helpers_test.go @@ -0,0 +1,519 @@ +// These tests verify the inner workings of the helper methods associated +// with check.T. + +package check_test + +import ( + "gopkg.in/check.v1" + "os" + "reflect" + "runtime" + "sync" +) + +var helpersS = check.Suite(&HelpersS{}) + +type HelpersS struct{} + +func (s *HelpersS) TestCountSuite(c *check.C) { + suitesRun += 1 +} + +// ----------------------------------------------------------------------- +// Fake checker and bug info to verify the behavior of Assert() and Check(). + +type MyChecker struct { + info *check.CheckerInfo + params []interface{} + names []string + result bool + error string +} + +func (checker *MyChecker) Info() *check.CheckerInfo { + if checker.info == nil { + return &check.CheckerInfo{Name: "MyChecker", Params: []string{"myobtained", "myexpected"}} + } + return checker.info +} + +func (checker *MyChecker) Check(params []interface{}, names []string) (bool, string) { + rparams := checker.params + rnames := checker.names + checker.params = append([]interface{}{}, params...) + checker.names = append([]string{}, names...) + if rparams != nil { + copy(params, rparams) + } + if rnames != nil { + copy(names, rnames) + } + return checker.result, checker.error +} + +type myCommentType string + +func (c myCommentType) CheckCommentString() string { + return string(c) +} + +func myComment(s string) myCommentType { + return myCommentType(s) +} + +// ----------------------------------------------------------------------- +// Ensure a real checker actually works fine. + +func (s *HelpersS) TestCheckerInterface(c *check.C) { + testHelperSuccess(c, "Check(1, Equals, 1)", true, func() interface{} { + return c.Check(1, check.Equals, 1) + }) +} + +// ----------------------------------------------------------------------- +// Tests for Check(), mostly the same as for Assert() following these. + +func (s *HelpersS) TestCheckSucceedWithExpected(c *check.C) { + checker := &MyChecker{result: true} + testHelperSuccess(c, "Check(1, checker, 2)", true, func() interface{} { + return c.Check(1, checker, 2) + }) + if !reflect.DeepEqual(checker.params, []interface{}{1, 2}) { + c.Fatalf("Bad params for check: %#v", checker.params) + } +} + +func (s *HelpersS) TestCheckSucceedWithoutExpected(c *check.C) { + checker := &MyChecker{result: true, info: &check.CheckerInfo{Params: []string{"myvalue"}}} + testHelperSuccess(c, "Check(1, checker)", true, func() interface{} { + return c.Check(1, checker) + }) + if !reflect.DeepEqual(checker.params, []interface{}{1}) { + c.Fatalf("Bad params for check: %#v", checker.params) + } +} + +func (s *HelpersS) TestCheckFailWithExpected(c *check.C) { + checker := &MyChecker{result: false} + log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + + " return c\\.Check\\(1, checker, 2\\)\n" + + "\\.+ myobtained int = 1\n" + + "\\.+ myexpected int = 2\n\n" + testHelperFailure(c, "Check(1, checker, 2)", false, false, log, + func() interface{} { + return c.Check(1, checker, 2) + }) +} + +func (s *HelpersS) TestCheckFailWithExpectedAndComment(c *check.C) { + checker := &MyChecker{result: false} + log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + + " return c\\.Check\\(1, checker, 2, myComment\\(\"Hello world!\"\\)\\)\n" + + "\\.+ myobtained int = 1\n" + + "\\.+ myexpected int = 2\n" + + "\\.+ Hello world!\n\n" + testHelperFailure(c, "Check(1, checker, 2, msg)", false, false, log, + func() interface{} { + return c.Check(1, checker, 2, myComment("Hello world!")) + }) +} + +func (s *HelpersS) TestCheckFailWithExpectedAndStaticComment(c *check.C) { + checker := &MyChecker{result: false} + log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + + " // Nice leading comment\\.\n" + + " return c\\.Check\\(1, checker, 2\\) // Hello there\n" + + "\\.+ myobtained int = 1\n" + + "\\.+ myexpected int = 2\n\n" + testHelperFailure(c, "Check(1, checker, 2, msg)", false, false, log, + func() interface{} { + // Nice leading comment. + return c.Check(1, checker, 2) // Hello there + }) +} + +func (s *HelpersS) TestCheckFailWithoutExpected(c *check.C) { + checker := &MyChecker{result: false, info: &check.CheckerInfo{Params: []string{"myvalue"}}} + log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + + " return c\\.Check\\(1, checker\\)\n" + + "\\.+ myvalue int = 1\n\n" + testHelperFailure(c, "Check(1, checker)", false, false, log, + func() interface{} { + return c.Check(1, checker) + }) +} + +func (s *HelpersS) TestCheckFailWithoutExpectedAndMessage(c *check.C) { + checker := &MyChecker{result: false, info: &check.CheckerInfo{Params: []string{"myvalue"}}} + log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + + " return c\\.Check\\(1, checker, myComment\\(\"Hello world!\"\\)\\)\n" + + "\\.+ myvalue int = 1\n" + + "\\.+ Hello world!\n\n" + testHelperFailure(c, "Check(1, checker, msg)", false, false, log, + func() interface{} { + return c.Check(1, checker, myComment("Hello world!")) + }) +} + +func (s *HelpersS) TestCheckWithMissingExpected(c *check.C) { + checker := &MyChecker{result: true} + log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + + " return c\\.Check\\(1, checker\\)\n" + + "\\.+ Check\\(myobtained, MyChecker, myexpected\\):\n" + + "\\.+ Wrong number of parameters for MyChecker: " + + "want 3, got 2\n\n" + testHelperFailure(c, "Check(1, checker, !?)", false, false, log, + func() interface{} { + return c.Check(1, checker) + }) +} + +func (s *HelpersS) TestCheckWithTooManyExpected(c *check.C) { + checker := &MyChecker{result: true} + log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + + " return c\\.Check\\(1, checker, 2, 3\\)\n" + + "\\.+ Check\\(myobtained, MyChecker, myexpected\\):\n" + + "\\.+ Wrong number of parameters for MyChecker: " + + "want 3, got 4\n\n" + testHelperFailure(c, "Check(1, checker, 2, 3)", false, false, log, + func() interface{} { + return c.Check(1, checker, 2, 3) + }) +} + +func (s *HelpersS) TestCheckWithError(c *check.C) { + checker := &MyChecker{result: false, error: "Some not so cool data provided!"} + log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + + " return c\\.Check\\(1, checker, 2\\)\n" + + "\\.+ myobtained int = 1\n" + + "\\.+ myexpected int = 2\n" + + "\\.+ Some not so cool data provided!\n\n" + testHelperFailure(c, "Check(1, checker, 2)", false, false, log, + func() interface{} { + return c.Check(1, checker, 2) + }) +} + +func (s *HelpersS) TestCheckWithNilChecker(c *check.C) { + log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + + " return c\\.Check\\(1, nil\\)\n" + + "\\.+ Check\\(obtained, nil!\\?, \\.\\.\\.\\):\n" + + "\\.+ Oops\\.\\. you've provided a nil checker!\n\n" + testHelperFailure(c, "Check(obtained, nil)", false, false, log, + func() interface{} { + return c.Check(1, nil) + }) +} + +func (s *HelpersS) TestCheckWithParamsAndNamesMutation(c *check.C) { + checker := &MyChecker{result: false, params: []interface{}{3, 4}, names: []string{"newobtained", "newexpected"}} + log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + + " return c\\.Check\\(1, checker, 2\\)\n" + + "\\.+ newobtained int = 3\n" + + "\\.+ newexpected int = 4\n\n" + testHelperFailure(c, "Check(1, checker, 2) with mutation", false, false, log, + func() interface{} { + return c.Check(1, checker, 2) + }) +} + +// ----------------------------------------------------------------------- +// Tests for Assert(), mostly the same as for Check() above. + +func (s *HelpersS) TestAssertSucceedWithExpected(c *check.C) { + checker := &MyChecker{result: true} + testHelperSuccess(c, "Assert(1, checker, 2)", nil, func() interface{} { + c.Assert(1, checker, 2) + return nil + }) + if !reflect.DeepEqual(checker.params, []interface{}{1, 2}) { + c.Fatalf("Bad params for check: %#v", checker.params) + } +} + +func (s *HelpersS) TestAssertSucceedWithoutExpected(c *check.C) { + checker := &MyChecker{result: true, info: &check.CheckerInfo{Params: []string{"myvalue"}}} + testHelperSuccess(c, "Assert(1, checker)", nil, func() interface{} { + c.Assert(1, checker) + return nil + }) + if !reflect.DeepEqual(checker.params, []interface{}{1}) { + c.Fatalf("Bad params for check: %#v", checker.params) + } +} + +func (s *HelpersS) TestAssertFailWithExpected(c *check.C) { + checker := &MyChecker{result: false} + log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + + " c\\.Assert\\(1, checker, 2\\)\n" + + "\\.+ myobtained int = 1\n" + + "\\.+ myexpected int = 2\n\n" + testHelperFailure(c, "Assert(1, checker, 2)", nil, true, log, + func() interface{} { + c.Assert(1, checker, 2) + return nil + }) +} + +func (s *HelpersS) TestAssertFailWithExpectedAndMessage(c *check.C) { + checker := &MyChecker{result: false} + log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + + " c\\.Assert\\(1, checker, 2, myComment\\(\"Hello world!\"\\)\\)\n" + + "\\.+ myobtained int = 1\n" + + "\\.+ myexpected int = 2\n" + + "\\.+ Hello world!\n\n" + testHelperFailure(c, "Assert(1, checker, 2, msg)", nil, true, log, + func() interface{} { + c.Assert(1, checker, 2, myComment("Hello world!")) + return nil + }) +} + +func (s *HelpersS) TestAssertFailWithoutExpected(c *check.C) { + checker := &MyChecker{result: false, info: &check.CheckerInfo{Params: []string{"myvalue"}}} + log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + + " c\\.Assert\\(1, checker\\)\n" + + "\\.+ myvalue int = 1\n\n" + testHelperFailure(c, "Assert(1, checker)", nil, true, log, + func() interface{} { + c.Assert(1, checker) + return nil + }) +} + +func (s *HelpersS) TestAssertFailWithoutExpectedAndMessage(c *check.C) { + checker := &MyChecker{result: false, info: &check.CheckerInfo{Params: []string{"myvalue"}}} + log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + + " c\\.Assert\\(1, checker, myComment\\(\"Hello world!\"\\)\\)\n" + + "\\.+ myvalue int = 1\n" + + "\\.+ Hello world!\n\n" + testHelperFailure(c, "Assert(1, checker, msg)", nil, true, log, + func() interface{} { + c.Assert(1, checker, myComment("Hello world!")) + return nil + }) +} + +func (s *HelpersS) TestAssertWithMissingExpected(c *check.C) { + checker := &MyChecker{result: true} + log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + + " c\\.Assert\\(1, checker\\)\n" + + "\\.+ Assert\\(myobtained, MyChecker, myexpected\\):\n" + + "\\.+ Wrong number of parameters for MyChecker: " + + "want 3, got 2\n\n" + testHelperFailure(c, "Assert(1, checker, !?)", nil, true, log, + func() interface{} { + c.Assert(1, checker) + return nil + }) +} + +func (s *HelpersS) TestAssertWithError(c *check.C) { + checker := &MyChecker{result: false, error: "Some not so cool data provided!"} + log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + + " c\\.Assert\\(1, checker, 2\\)\n" + + "\\.+ myobtained int = 1\n" + + "\\.+ myexpected int = 2\n" + + "\\.+ Some not so cool data provided!\n\n" + testHelperFailure(c, "Assert(1, checker, 2)", nil, true, log, + func() interface{} { + c.Assert(1, checker, 2) + return nil + }) +} + +func (s *HelpersS) TestAssertWithNilChecker(c *check.C) { + log := "(?s)helpers_test\\.go:[0-9]+:.*\nhelpers_test\\.go:[0-9]+:\n" + + " c\\.Assert\\(1, nil\\)\n" + + "\\.+ Assert\\(obtained, nil!\\?, \\.\\.\\.\\):\n" + + "\\.+ Oops\\.\\. you've provided a nil checker!\n\n" + testHelperFailure(c, "Assert(obtained, nil)", nil, true, log, + func() interface{} { + c.Assert(1, nil) + return nil + }) +} + +// ----------------------------------------------------------------------- +// Ensure that values logged work properly in some interesting cases. + +func (s *HelpersS) TestValueLoggingWithArrays(c *check.C) { + checker := &MyChecker{result: false} + log := "(?s)helpers_test.go:[0-9]+:.*\nhelpers_test.go:[0-9]+:\n" + + " return c\\.Check\\(\\[\\]byte{1, 2}, checker, \\[\\]byte{1, 3}\\)\n" + + "\\.+ myobtained \\[\\]uint8 = \\[\\]byte{0x1, 0x2}\n" + + "\\.+ myexpected \\[\\]uint8 = \\[\\]byte{0x1, 0x3}\n\n" + testHelperFailure(c, "Check([]byte{1}, chk, []byte{3})", false, false, log, + func() interface{} { + return c.Check([]byte{1, 2}, checker, []byte{1, 3}) + }) +} + +func (s *HelpersS) TestValueLoggingWithMultiLine(c *check.C) { + checker := &MyChecker{result: false} + log := "(?s)helpers_test.go:[0-9]+:.*\nhelpers_test.go:[0-9]+:\n" + + " return c\\.Check\\(\"a\\\\nb\\\\n\", checker, \"a\\\\nb\\\\nc\"\\)\n" + + "\\.+ myobtained string = \"\" \\+\n" + + "\\.+ \"a\\\\n\" \\+\n" + + "\\.+ \"b\\\\n\"\n" + + "\\.+ myexpected string = \"\" \\+\n" + + "\\.+ \"a\\\\n\" \\+\n" + + "\\.+ \"b\\\\n\" \\+\n" + + "\\.+ \"c\"\n\n" + testHelperFailure(c, `Check("a\nb\n", chk, "a\nb\nc")`, false, false, log, + func() interface{} { + return c.Check("a\nb\n", checker, "a\nb\nc") + }) +} + +func (s *HelpersS) TestValueLoggingWithMultiLineException(c *check.C) { + // If the newline is at the end of the string, don't log as multi-line. + checker := &MyChecker{result: false} + log := "(?s)helpers_test.go:[0-9]+:.*\nhelpers_test.go:[0-9]+:\n" + + " return c\\.Check\\(\"a b\\\\n\", checker, \"a\\\\nb\"\\)\n" + + "\\.+ myobtained string = \"a b\\\\n\"\n" + + "\\.+ myexpected string = \"\" \\+\n" + + "\\.+ \"a\\\\n\" \\+\n" + + "\\.+ \"b\"\n\n" + testHelperFailure(c, `Check("a b\n", chk, "a\nb")`, false, false, log, + func() interface{} { + return c.Check("a b\n", checker, "a\nb") + }) +} + +// ----------------------------------------------------------------------- +// MakeDir() tests. + +type MkDirHelper struct { + path1 string + path2 string + isDir1 bool + isDir2 bool + isDir3 bool + isDir4 bool +} + +func (s *MkDirHelper) SetUpSuite(c *check.C) { + s.path1 = c.MkDir() + s.isDir1 = isDir(s.path1) +} + +func (s *MkDirHelper) Test(c *check.C) { + s.path2 = c.MkDir() + s.isDir2 = isDir(s.path2) +} + +func (s *MkDirHelper) TearDownSuite(c *check.C) { + s.isDir3 = isDir(s.path1) + s.isDir4 = isDir(s.path2) +} + +func (s *HelpersS) TestMkDir(c *check.C) { + helper := MkDirHelper{} + output := String{} + check.Run(&helper, &check.RunConf{Output: &output}) + c.Assert(output.value, check.Equals, "") + c.Check(helper.isDir1, check.Equals, true) + c.Check(helper.isDir2, check.Equals, true) + c.Check(helper.isDir3, check.Equals, true) + c.Check(helper.isDir4, check.Equals, true) + c.Check(helper.path1, check.Not(check.Equals), + helper.path2) + c.Check(isDir(helper.path1), check.Equals, false) + c.Check(isDir(helper.path2), check.Equals, false) +} + +func isDir(path string) bool { + if stat, err := os.Stat(path); err == nil { + return stat.IsDir() + } + return false +} + +// Concurrent logging should not corrupt the underling buffer. +// Use go test -race to detect the race in this test. +func (s *HelpersS) TestConcurrentLogging(c *check.C) { + defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(runtime.NumCPU())) + var start, stop sync.WaitGroup + start.Add(1) + for i, n := 0, runtime.NumCPU()*2; i < n; i++ { + stop.Add(1) + go func(i int) { + start.Wait() + for j := 0; j < 30; j++ { + c.Logf("Worker %d: line %d", i, j) + } + stop.Done() + }(i) + } + start.Done() + stop.Wait() +} + +// ----------------------------------------------------------------------- +// Test the TestName function + +type TestNameHelper struct { + name1 string + name2 string + name3 string + name4 string + name5 string +} + +func (s *TestNameHelper) SetUpSuite(c *check.C) { s.name1 = c.TestName() } +func (s *TestNameHelper) SetUpTest(c *check.C) { s.name2 = c.TestName() } +func (s *TestNameHelper) Test(c *check.C) { s.name3 = c.TestName() } +func (s *TestNameHelper) TearDownTest(c *check.C) { s.name4 = c.TestName() } +func (s *TestNameHelper) TearDownSuite(c *check.C) { s.name5 = c.TestName() } + +func (s *HelpersS) TestTestName(c *check.C) { + helper := TestNameHelper{} + output := String{} + check.Run(&helper, &check.RunConf{Output: &output}) + c.Check(helper.name1, check.Equals, "") + c.Check(helper.name2, check.Equals, "TestNameHelper.Test") + c.Check(helper.name3, check.Equals, "TestNameHelper.Test") + c.Check(helper.name4, check.Equals, "TestNameHelper.Test") + c.Check(helper.name5, check.Equals, "") +} + +// ----------------------------------------------------------------------- +// A couple of helper functions to test helper functions. :-) + +func testHelperSuccess(c *check.C, name string, expectedResult interface{}, closure func() interface{}) { + var result interface{} + defer (func() { + if err := recover(); err != nil { + panic(err) + } + checkState(c, result, + &expectedState{ + name: name, + result: expectedResult, + failed: false, + log: "", + }) + })() + result = closure() +} + +func testHelperFailure(c *check.C, name string, expectedResult interface{}, shouldStop bool, log string, closure func() interface{}) { + var result interface{} + defer (func() { + if err := recover(); err != nil { + panic(err) + } + checkState(c, result, + &expectedState{ + name: name, + result: expectedResult, + failed: true, + log: log, + }) + })() + result = closure() + if shouldStop { + c.Logf("%s didn't stop when it should", name) + } +} diff --git a/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/printer.go b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/printer.go new file mode 100644 index 000000000..e0f7557b5 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/printer.go @@ -0,0 +1,168 @@ +package check + +import ( + "bytes" + "go/ast" + "go/parser" + "go/printer" + "go/token" + "os" +) + +func indent(s, with string) (r string) { + eol := true + for i := 0; i != len(s); i++ { + c := s[i] + switch { + case eol && c == '\n' || c == '\r': + case c == '\n' || c == '\r': + eol = true + case eol: + eol = false + s = s[:i] + with + s[i:] + i += len(with) + } + } + return s +} + +func printLine(filename string, line int) (string, error) { + fset := token.NewFileSet() + file, err := os.Open(filename) + if err != nil { + return "", err + } + fnode, err := parser.ParseFile(fset, filename, file, parser.ParseComments) + if err != nil { + return "", err + } + config := &printer.Config{Mode: printer.UseSpaces, Tabwidth: 4} + lp := &linePrinter{fset: fset, fnode: fnode, line: line, config: config} + ast.Walk(lp, fnode) + result := lp.output.Bytes() + // Comments leave \n at the end. + n := len(result) + for n > 0 && result[n-1] == '\n' { + n-- + } + return string(result[:n]), nil +} + +type linePrinter struct { + config *printer.Config + fset *token.FileSet + fnode *ast.File + line int + output bytes.Buffer + stmt ast.Stmt +} + +func (lp *linePrinter) emit() bool { + if lp.stmt != nil { + lp.trim(lp.stmt) + lp.printWithComments(lp.stmt) + lp.stmt = nil + return true + } + return false +} + +func (lp *linePrinter) printWithComments(n ast.Node) { + nfirst := lp.fset.Position(n.Pos()).Line + nlast := lp.fset.Position(n.End()).Line + for _, g := range lp.fnode.Comments { + cfirst := lp.fset.Position(g.Pos()).Line + clast := lp.fset.Position(g.End()).Line + if clast == nfirst-1 && lp.fset.Position(n.Pos()).Column == lp.fset.Position(g.Pos()).Column { + for _, c := range g.List { + lp.output.WriteString(c.Text) + lp.output.WriteByte('\n') + } + } + if cfirst >= nfirst && cfirst <= nlast && n.End() <= g.List[0].Slash { + // The printer will not include the comment if it starts past + // the node itself. Trick it into printing by overlapping the + // slash with the end of the statement. + g.List[0].Slash = n.End() - 1 + } + } + node := &printer.CommentedNode{n, lp.fnode.Comments} + lp.config.Fprint(&lp.output, lp.fset, node) +} + +func (lp *linePrinter) Visit(n ast.Node) (w ast.Visitor) { + if n == nil { + if lp.output.Len() == 0 { + lp.emit() + } + return nil + } + first := lp.fset.Position(n.Pos()).Line + last := lp.fset.Position(n.End()).Line + if first <= lp.line && last >= lp.line { + // Print the innermost statement containing the line. + if stmt, ok := n.(ast.Stmt); ok { + if _, ok := n.(*ast.BlockStmt); !ok { + lp.stmt = stmt + } + } + if first == lp.line && lp.emit() { + return nil + } + return lp + } + return nil +} + +func (lp *linePrinter) trim(n ast.Node) bool { + stmt, ok := n.(ast.Stmt) + if !ok { + return true + } + line := lp.fset.Position(n.Pos()).Line + if line != lp.line { + return false + } + switch stmt := stmt.(type) { + case *ast.IfStmt: + stmt.Body = lp.trimBlock(stmt.Body) + case *ast.SwitchStmt: + stmt.Body = lp.trimBlock(stmt.Body) + case *ast.TypeSwitchStmt: + stmt.Body = lp.trimBlock(stmt.Body) + case *ast.CaseClause: + stmt.Body = lp.trimList(stmt.Body) + case *ast.CommClause: + stmt.Body = lp.trimList(stmt.Body) + case *ast.BlockStmt: + stmt.List = lp.trimList(stmt.List) + } + return true +} + +func (lp *linePrinter) trimBlock(stmt *ast.BlockStmt) *ast.BlockStmt { + if !lp.trim(stmt) { + return lp.emptyBlock(stmt) + } + stmt.Rbrace = stmt.Lbrace + return stmt +} + +func (lp *linePrinter) trimList(stmts []ast.Stmt) []ast.Stmt { + for i := 0; i != len(stmts); i++ { + if !lp.trim(stmts[i]) { + stmts[i] = lp.emptyStmt(stmts[i]) + break + } + } + return stmts +} + +func (lp *linePrinter) emptyStmt(n ast.Node) *ast.ExprStmt { + return &ast.ExprStmt{&ast.Ellipsis{n.Pos(), nil}} +} + +func (lp *linePrinter) emptyBlock(n ast.Node) *ast.BlockStmt { + p := n.Pos() + return &ast.BlockStmt{p, []ast.Stmt{lp.emptyStmt(n)}, p} +} diff --git a/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/printer_test.go b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/printer_test.go new file mode 100644 index 000000000..538b2d52e --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/printer_test.go @@ -0,0 +1,104 @@ +package check_test + +import ( + . "gopkg.in/check.v1" +) + +var _ = Suite(&PrinterS{}) + +type PrinterS struct{} + +func (s *PrinterS) TestCountSuite(c *C) { + suitesRun += 1 +} + +var printTestFuncLine int + +func init() { + printTestFuncLine = getMyLine() + 3 +} + +func printTestFunc() { + println(1) // Comment1 + if 2 == 2 { // Comment2 + println(3) // Comment3 + } + switch 5 { + case 6: println(6) // Comment6 + println(7) + } + switch interface{}(9).(type) {// Comment9 + case int: println(10) + println(11) + } + select { + case <-(chan bool)(nil): println(14) + println(15) + default: println(16) + println(17) + } + println(19, + 20) + _ = func() { println(21) + println(22) + } + println(24, func() { + println(25) + }) + // Leading comment + // with multiple lines. + println(29) // Comment29 +} + +var printLineTests = []struct { + line int + output string +}{ + {1, "println(1) // Comment1"}, + {2, "if 2 == 2 { // Comment2\n ...\n}"}, + {3, "println(3) // Comment3"}, + {5, "switch 5 {\n...\n}"}, + {6, "case 6:\n println(6) // Comment6\n ..."}, + {7, "println(7)"}, + {9, "switch interface{}(9).(type) { // Comment9\n...\n}"}, + {10, "case int:\n println(10)\n ..."}, + {14, "case <-(chan bool)(nil):\n println(14)\n ..."}, + {15, "println(15)"}, + {16, "default:\n println(16)\n ..."}, + {17, "println(17)"}, + {19, "println(19,\n 20)"}, + {20, "println(19,\n 20)"}, + {21, "_ = func() {\n println(21)\n println(22)\n}"}, + {22, "println(22)"}, + {24, "println(24, func() {\n println(25)\n})"}, + {25, "println(25)"}, + {26, "println(24, func() {\n println(25)\n})"}, + {29, "// Leading comment\n// with multiple lines.\nprintln(29) // Comment29"}, +} + +func (s *PrinterS) TestPrintLine(c *C) { + for _, test := range printLineTests { + output, err := PrintLine("printer_test.go", printTestFuncLine+test.line) + c.Assert(err, IsNil) + c.Assert(output, Equals, test.output) + } +} + +var indentTests = []struct { + in, out string +}{ + {"", ""}, + {"\n", "\n"}, + {"a", ">>>a"}, + {"a\n", ">>>a\n"}, + {"a\nb", ">>>a\n>>>b"}, + {" ", ">>> "}, +} + +func (s *PrinterS) TestIndent(c *C) { + for _, test := range indentTests { + out := Indent(test.in, ">>>") + c.Assert(out, Equals, test.out) + } + +} diff --git a/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/run.go b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/run.go new file mode 100644 index 000000000..da8fd7987 --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/run.go @@ -0,0 +1,175 @@ +package check + +import ( + "bufio" + "flag" + "fmt" + "os" + "testing" + "time" +) + +// ----------------------------------------------------------------------- +// Test suite registry. + +var allSuites []interface{} + +// Suite registers the given value as a test suite to be run. Any methods +// starting with the Test prefix in the given value will be considered as +// a test method. +func Suite(suite interface{}) interface{} { + allSuites = append(allSuites, suite) + return suite +} + +// ----------------------------------------------------------------------- +// Public running interface. + +var ( + oldFilterFlag = flag.String("gocheck.f", "", "Regular expression selecting which tests and/or suites to run") + oldVerboseFlag = flag.Bool("gocheck.v", false, "Verbose mode") + oldStreamFlag = flag.Bool("gocheck.vv", false, "Super verbose mode (disables output caching)") + oldBenchFlag = flag.Bool("gocheck.b", false, "Run benchmarks") + oldBenchTime = flag.Duration("gocheck.btime", 1*time.Second, "approximate run time for each benchmark") + oldListFlag = flag.Bool("gocheck.list", false, "List the names of all tests that will be run") + oldWorkFlag = flag.Bool("gocheck.work", false, "Display and do not remove the test working directory") + + newFilterFlag = flag.String("check.f", "", "Regular expression selecting which tests and/or suites to run") + newVerboseFlag = flag.Bool("check.v", false, "Verbose mode") + newStreamFlag = flag.Bool("check.vv", false, "Super verbose mode (disables output caching)") + newBenchFlag = flag.Bool("check.b", false, "Run benchmarks") + newBenchTime = flag.Duration("check.btime", 1*time.Second, "approximate run time for each benchmark") + newBenchMem = flag.Bool("check.bmem", false, "Report memory benchmarks") + newListFlag = flag.Bool("check.list", false, "List the names of all tests that will be run") + newWorkFlag = flag.Bool("check.work", false, "Display and do not remove the test working directory") +) + +// TestingT runs all test suites registered with the Suite function, +// printing results to stdout, and reporting any failures back to +// the "testing" package. +func TestingT(testingT *testing.T) { + benchTime := *newBenchTime + if benchTime == 1*time.Second { + benchTime = *oldBenchTime + } + conf := &RunConf{ + Filter: *oldFilterFlag + *newFilterFlag, + Verbose: *oldVerboseFlag || *newVerboseFlag, + Stream: *oldStreamFlag || *newStreamFlag, + Benchmark: *oldBenchFlag || *newBenchFlag, + BenchmarkTime: benchTime, + BenchmarkMem: *newBenchMem, + KeepWorkDir: *oldWorkFlag || *newWorkFlag, + } + if *oldListFlag || *newListFlag { + w := bufio.NewWriter(os.Stdout) + for _, name := range ListAll(conf) { + fmt.Fprintln(w, name) + } + w.Flush() + return + } + result := RunAll(conf) + println(result.String()) + if !result.Passed() { + testingT.Fail() + } +} + +// RunAll runs all test suites registered with the Suite function, using the +// provided run configuration. +func RunAll(runConf *RunConf) *Result { + result := Result{} + for _, suite := range allSuites { + result.Add(Run(suite, runConf)) + } + return &result +} + +// Run runs the provided test suite using the provided run configuration. +func Run(suite interface{}, runConf *RunConf) *Result { + runner := newSuiteRunner(suite, runConf) + return runner.run() +} + +// ListAll returns the names of all the test functions registered with the +// Suite function that will be run with the provided run configuration. +func ListAll(runConf *RunConf) []string { + var names []string + for _, suite := range allSuites { + names = append(names, List(suite, runConf)...) + } + return names +} + +// List returns the names of the test functions in the given +// suite that will be run with the provided run configuration. +func List(suite interface{}, runConf *RunConf) []string { + var names []string + runner := newSuiteRunner(suite, runConf) + for _, t := range runner.tests { + names = append(names, t.String()) + } + return names +} + +// ----------------------------------------------------------------------- +// Result methods. + +func (r *Result) Add(other *Result) { + r.Succeeded += other.Succeeded + r.Skipped += other.Skipped + r.Failed += other.Failed + r.Panicked += other.Panicked + r.FixturePanicked += other.FixturePanicked + r.ExpectedFailures += other.ExpectedFailures + r.Missed += other.Missed + if r.WorkDir != "" && other.WorkDir != "" { + r.WorkDir += ":" + other.WorkDir + } else if other.WorkDir != "" { + r.WorkDir = other.WorkDir + } +} + +func (r *Result) Passed() bool { + return (r.Failed == 0 && r.Panicked == 0 && + r.FixturePanicked == 0 && r.Missed == 0 && + r.RunError == nil) +} + +func (r *Result) String() string { + if r.RunError != nil { + return "ERROR: " + r.RunError.Error() + } + + var value string + if r.Failed == 0 && r.Panicked == 0 && r.FixturePanicked == 0 && + r.Missed == 0 { + value = "OK: " + } else { + value = "OOPS: " + } + value += fmt.Sprintf("%d passed", r.Succeeded) + if r.Skipped != 0 { + value += fmt.Sprintf(", %d skipped", r.Skipped) + } + if r.ExpectedFailures != 0 { + value += fmt.Sprintf(", %d expected failures", r.ExpectedFailures) + } + if r.Failed != 0 { + value += fmt.Sprintf(", %d FAILED", r.Failed) + } + if r.Panicked != 0 { + value += fmt.Sprintf(", %d PANICKED", r.Panicked) + } + if r.FixturePanicked != 0 { + value += fmt.Sprintf(", %d FIXTURE-PANICKED", r.FixturePanicked) + } + if r.Missed != 0 { + value += fmt.Sprintf(", %d MISSED", r.Missed) + } + if r.WorkDir != "" { + value += "\nWORK=" + r.WorkDir + } + return value +} diff --git a/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/run_test.go b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/run_test.go new file mode 100644 index 000000000..f41fffc3f --- /dev/null +++ b/pkg/api/Godeps/_workspace/src/gopkg.in/check.v1/run_test.go @@ -0,0 +1,419 @@ +// These tests verify the test running logic. + +package check_test + +import ( + "errors" + . "gopkg.in/check.v1" + "os" + "sync" +) + +var runnerS = Suite(&RunS{}) + +type RunS struct{} + +func (s *RunS) TestCountSuite(c *C) { + suitesRun += 1 +} + +// ----------------------------------------------------------------------- +// Tests ensuring result counting works properly. + +func (s *RunS) TestSuccess(c *C) { + output := String{} + result := Run(&SuccessHelper{}, &RunConf{Output: &output}) + c.Check(result.Succeeded, Equals, 1) + c.Check(result.Failed, Equals, 0) + c.Check(result.Skipped, Equals, 0) + c.Check(result.Panicked, Equals, 0) + c.Check(result.FixturePanicked, Equals, 0) + c.Check(result.Missed, Equals, 0) + c.Check(result.RunError, IsNil) +} + +func (s *RunS) TestFailure(c *C) { + output := String{} + result := Run(&FailHelper{}, &RunConf{Output: &output}) + c.Check(result.Succeeded, Equals, 0) + c.Check(result.Failed, Equals, 1) + c.Check(result.Skipped, Equals, 0) + c.Check(result.Panicked, Equals, 0) + c.Check(result.FixturePanicked, Equals, 0) + c.Check(result.Missed, Equals, 0) + c.Check(result.RunError, IsNil) +} + +func (s *RunS) TestFixture(c *C) { + output := String{} + result := Run(&FixtureHelper{}, &RunConf{Output: &output}) + c.Check(result.Succeeded, Equals, 2) + c.Check(result.Failed, Equals, 0) + c.Check(result.Skipped, Equals, 0) + c.Check(result.Panicked, Equals, 0) + c.Check(result.FixturePanicked, Equals, 0) + c.Check(result.Missed, Equals, 0) + c.Check(result.RunError, IsNil) +} + +func (s *RunS) TestPanicOnTest(c *C) { + output := String{} + helper := &FixtureHelper{panicOn: "Test1"} + result := Run(helper, &RunConf{Output: &output}) + c.Check(result.Succeeded, Equals, 1) + c.Check(result.Failed, Equals, 0) + c.Check(result.Skipped, Equals, 0) + c.Check(result.Panicked, Equals, 1) + c.Check(result.FixturePanicked, Equals, 0) + c.Check(result.Missed, Equals, 0) + c.Check(result.RunError, IsNil) +} + +func (s *RunS) TestPanicOnSetUpTest(c *C) { + output := String{} + helper := &FixtureHelper{panicOn: "SetUpTest"} + result := Run(helper, &RunConf{Output: &output}) + c.Check(result.Succeeded, Equals, 0) + c.Check(result.Failed, Equals, 0) + c.Check(result.Skipped, Equals, 0) + c.Check(result.Panicked, Equals, 0) + c.Check(result.FixturePanicked, Equals, 1) + c.Check(result.Missed, Equals, 2) + c.Check(result.RunError, IsNil) +} + +func (s *RunS) TestPanicOnSetUpSuite(c *C) { + output := String{} + helper := &FixtureHelper{panicOn: "SetUpSuite"} + result := Run(helper, &RunConf{Output: &output}) + c.Check(result.Succeeded, Equals, 0) + c.Check(result.Failed, Equals, 0) + c.Check(result.Skipped, Equals, 0) + c.Check(result.Panicked, Equals, 0) + c.Check(result.FixturePanicked, Equals, 1) + c.Check(result.Missed, Equals, 2) + c.Check(result.RunError, IsNil) +} + +// ----------------------------------------------------------------------- +// Check result aggregation. + +func (s *RunS) TestAdd(c *C) { + result := &Result{ + Succeeded: 1, + Skipped: 2, + Failed: 3, + Panicked: 4, + FixturePanicked: 5, + Missed: 6, + ExpectedFailures: 7, + } + result.Add(&Result{ + Succeeded: 10, + Skipped: 20, + Failed: 30, + Panicked: 40, + FixturePanicked: 50, + Missed: 60, + ExpectedFailures: 70, + }) + c.Check(result.Succeeded, Equals, 11) + c.Check(result.Skipped, Equals, 22) + c.Check(result.Failed, Equals, 33) + c.Check(result.Panicked, Equals, 44) + c.Check(result.FixturePanicked, Equals, 55) + c.Check(result.Missed, Equals, 66) + c.Check(result.ExpectedFailures, Equals, 77) + c.Check(result.RunError, IsNil) +} + +// ----------------------------------------------------------------------- +// Check the Passed() method. + +func (s *RunS) TestPassed(c *C) { + c.Assert((&Result{}).Passed(), Equals, true) + c.Assert((&Result{Succeeded: 1}).Passed(), Equals, true) + c.Assert((&Result{Skipped: 1}).Passed(), Equals, true) + c.Assert((&Result{Failed: 1}).Passed(), Equals, false) + c.Assert((&Result{Panicked: 1}).Passed(), Equals, false) + c.Assert((&Result{FixturePanicked: 1}).Passed(), Equals, false) + c.Assert((&Result{Missed: 1}).Passed(), Equals, false) + c.Assert((&Result{RunError: errors.New("!")}).Passed(), Equals, false) +} + +// ----------------------------------------------------------------------- +// Check that result printing is working correctly. + +func (s *RunS) TestPrintSuccess(c *C) { + result := &Result{Succeeded: 5} + c.Check(result.String(), Equals, "OK: 5 passed") +} + +func (s *RunS) TestPrintFailure(c *C) { + result := &Result{Failed: 5} + c.Check(result.String(), Equals, "OOPS: 0 passed, 5 FAILED") +} + +func (s *RunS) TestPrintSkipped(c *C) { + result := &Result{Skipped: 5} + c.Check(result.String(), Equals, "OK: 0 passed, 5 skipped") +} + +func (s *RunS) TestPrintExpectedFailures(c *C) { + result := &Result{ExpectedFailures: 5} + c.Check(result.String(), Equals, "OK: 0 passed, 5 expected failures") +} + +func (s *RunS) TestPrintPanicked(c *C) { + result := &Result{Panicked: 5} + c.Check(result.String(), Equals, "OOPS: 0 passed, 5 PANICKED") +} + +func (s *RunS) TestPrintFixturePanicked(c *C) { + result := &Result{FixturePanicked: 5} + c.Check(result.String(), Equals, "OOPS: 0 passed, 5 FIXTURE-PANICKED") +} + +func (s *RunS) TestPrintMissed(c *C) { + result := &Result{Missed: 5} + c.Check(result.String(), Equals, "OOPS: 0 passed, 5 MISSED") +} + +func (s *RunS) TestPrintAll(c *C) { + result := &Result{Succeeded: 1, Skipped: 2, ExpectedFailures: 3, + Panicked: 4, FixturePanicked: 5, Missed: 6} + c.Check(result.String(), Equals, + "OOPS: 1 passed, 2 skipped, 3 expected failures, 4 PANICKED, "+ + "5 FIXTURE-PANICKED, 6 MISSED") +} + +func (s *RunS) TestPrintRunError(c *C) { + result := &Result{Succeeded: 1, Failed: 1, + RunError: errors.New("Kaboom!")} + c.Check(result.String(), Equals, "ERROR: Kaboom!") +} + +// ----------------------------------------------------------------------- +// Verify that the method pattern flag works correctly. + +func (s *RunS) TestFilterTestName(c *C) { + helper := FixtureHelper{} + output := String{} + runConf := RunConf{Output: &output, Filter: "Test[91]"} + Run(&helper, &runConf) + c.Check(helper.calls[0], Equals, "SetUpSuite") + c.Check(helper.calls[1], Equals, "SetUpTest") + c.Check(helper.calls[2], Equals, "Test1") + c.Check(helper.calls[3], Equals, "TearDownTest") + c.Check(helper.calls[4], Equals, "TearDownSuite") + c.Check(len(helper.calls), Equals, 5) +} + +func (s *RunS) TestFilterTestNameWithAll(c *C) { + helper := FixtureHelper{} + output := String{} + runConf := RunConf{Output: &output, Filter: ".*"} + Run(&helper, &runConf) + c.Check(helper.calls[0], Equals, "SetUpSuite") + c.Check(helper.calls[1], Equals, "SetUpTest") + c.Check(helper.calls[2], Equals, "Test1") + c.Check(helper.calls[3], Equals, "TearDownTest") + c.Check(helper.calls[4], Equals, "SetUpTest") + c.Check(helper.calls[5], Equals, "Test2") + c.Check(helper.calls[6], Equals, "TearDownTest") + c.Check(helper.calls[7], Equals, "TearDownSuite") + c.Check(len(helper.calls), Equals, 8) +} + +func (s *RunS) TestFilterSuiteName(c *C) { + helper := FixtureHelper{} + output := String{} + runConf := RunConf{Output: &output, Filter: "FixtureHelper"} + Run(&helper, &runConf) + c.Check(helper.calls[0], Equals, "SetUpSuite") + c.Check(helper.calls[1], Equals, "SetUpTest") + c.Check(helper.calls[2], Equals, "Test1") + c.Check(helper.calls[3], Equals, "TearDownTest") + c.Check(helper.calls[4], Equals, "SetUpTest") + c.Check(helper.calls[5], Equals, "Test2") + c.Check(helper.calls[6], Equals, "TearDownTest") + c.Check(helper.calls[7], Equals, "TearDownSuite") + c.Check(len(helper.calls), Equals, 8) +} + +func (s *RunS) TestFilterSuiteNameAndTestName(c *C) { + helper := FixtureHelper{} + output := String{} + runConf := RunConf{Output: &output, Filter: "FixtureHelper\\.Test2"} + Run(&helper, &runConf) + c.Check(helper.calls[0], Equals, "SetUpSuite") + c.Check(helper.calls[1], Equals, "SetUpTest") + c.Check(helper.calls[2], Equals, "Test2") + c.Check(helper.calls[3], Equals, "TearDownTest") + c.Check(helper.calls[4], Equals, "TearDownSuite") + c.Check(len(helper.calls), Equals, 5) +} + +func (s *RunS) TestFilterAllOut(c *C) { + helper := FixtureHelper{} + output := String{} + runConf := RunConf{Output: &output, Filter: "NotFound"} + Run(&helper, &runConf) + c.Check(len(helper.calls), Equals, 0) +} + +func (s *RunS) TestRequirePartialMatch(c *C) { + helper := FixtureHelper{} + output := String{} + runConf := RunConf{Output: &output, Filter: "est"} + Run(&helper, &runConf) + c.Check(len(helper.calls), Equals, 8) +} + +func (s *RunS) TestFilterError(c *C) { + helper := FixtureHelper{} + output := String{} + runConf := RunConf{Output: &output, Filter: "]["} + result := Run(&helper, &runConf) + c.Check(result.String(), Equals, + "ERROR: Bad filter expression: error parsing regexp: missing closing ]: `[`") + c.Check(len(helper.calls), Equals, 0) +} + +// ----------------------------------------------------------------------- +// Verify that List works correctly. + +func (s *RunS) TestListFiltered(c *C) { + names := List(&FixtureHelper{}, &RunConf{Filter: "1"}) + c.Assert(names, DeepEquals, []string{ + "FixtureHelper.Test1", + }) +} + +func (s *RunS) TestList(c *C) { + names := List(&FixtureHelper{}, &RunConf{}) + c.Assert(names, DeepEquals, []string{ + "FixtureHelper.Test1", + "FixtureHelper.Test2", + }) +} + +// ----------------------------------------------------------------------- +// Verify that verbose mode prints tests which pass as well. + +func (s *RunS) TestVerboseMode(c *C) { + helper := FixtureHelper{} + output := String{} + runConf := RunConf{Output: &output, Verbose: true} + Run(&helper, &runConf) + + expected := "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Test1\t *[.0-9]+s\n" + + "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Test2\t *[.0-9]+s\n" + + c.Assert(output.value, Matches, expected) +} + +func (s *RunS) TestVerboseModeWithFailBeforePass(c *C) { + helper := FixtureHelper{panicOn: "Test1"} + output := String{} + runConf := RunConf{Output: &output, Verbose: true} + Run(&helper, &runConf) + + expected := "(?s).*PANIC.*\n-+\n" + // Should have an extra line. + "PASS: check_test\\.go:[0-9]+: FixtureHelper\\.Test2\t *[.0-9]+s\n" + + c.Assert(output.value, Matches, expected) +} + +// ----------------------------------------------------------------------- +// Verify the stream output mode. In this mode there's no output caching. + +type StreamHelper struct { + l2 sync.Mutex + l3 sync.Mutex +} + +func (s *StreamHelper) SetUpSuite(c *C) { + c.Log("0") +} + +func (s *StreamHelper) Test1(c *C) { + c.Log("1") + s.l2.Lock() + s.l3.Lock() + go func() { + s.l2.Lock() // Wait for "2". + c.Log("3") + s.l3.Unlock() + }() +} + +func (s *StreamHelper) Test2(c *C) { + c.Log("2") + s.l2.Unlock() + s.l3.Lock() // Wait for "3". + c.Fail() + c.Log("4") +} + +func (s *RunS) TestStreamMode(c *C) { + helper := &StreamHelper{} + output := String{} + runConf := RunConf{Output: &output, Stream: true} + Run(helper, &runConf) + + expected := "START: run_test\\.go:[0-9]+: StreamHelper\\.SetUpSuite\n0\n" + + "PASS: run_test\\.go:[0-9]+: StreamHelper\\.SetUpSuite\t *[.0-9]+s\n\n" + + "START: run_test\\.go:[0-9]+: StreamHelper\\.Test1\n1\n" + + "PASS: run_test\\.go:[0-9]+: StreamHelper\\.Test1\t *[.0-9]+s\n\n" + + "START: run_test\\.go:[0-9]+: StreamHelper\\.Test2\n2\n3\n4\n" + + "FAIL: run_test\\.go:[0-9]+: StreamHelper\\.Test2\n\n" + + c.Assert(output.value, Matches, expected) +} + +type StreamMissHelper struct{} + +func (s *StreamMissHelper) SetUpSuite(c *C) { + c.Log("0") + c.Fail() +} + +func (s *StreamMissHelper) Test1(c *C) { + c.Log("1") +} + +func (s *RunS) TestStreamModeWithMiss(c *C) { + helper := &StreamMissHelper{} + output := String{} + runConf := RunConf{Output: &output, Stream: true} + Run(helper, &runConf) + + expected := "START: run_test\\.go:[0-9]+: StreamMissHelper\\.SetUpSuite\n0\n" + + "FAIL: run_test\\.go:[0-9]+: StreamMissHelper\\.SetUpSuite\n\n" + + "START: run_test\\.go:[0-9]+: StreamMissHelper\\.Test1\n" + + "MISS: run_test\\.go:[0-9]+: StreamMissHelper\\.Test1\n\n" + + c.Assert(output.value, Matches, expected) +} + +// ----------------------------------------------------------------------- +// Verify that that the keep work dir request indeed does so. + +type WorkDirSuite struct {} + +func (s *WorkDirSuite) Test(c *C) { + c.MkDir() +} + +func (s *RunS) TestKeepWorkDir(c *C) { + output := String{} + runConf := RunConf{Output: &output, Verbose: true, KeepWorkDir: true} + result := Run(&WorkDirSuite{}, &runConf) + + c.Assert(result.String(), Matches, ".*\nWORK=" + result.WorkDir) + + stat, err := os.Stat(result.WorkDir) + c.Assert(err, IsNil) + c.Assert(stat.IsDir(), Equals, true) +} diff --git a/pkg/api/api_test.go b/pkg/api/api_test.go index 367226012..50d07a6ea 100644 --- a/pkg/api/api_test.go +++ b/pkg/api/api_test.go @@ -18,12 +18,9 @@ package api_test import ( "bytes" - "encoding/xml" "io" "io/ioutil" "log" - "net/http" - "net/http/httptest" "os" "reflect" "strconv" @@ -31,7 +28,10 @@ import ( "testing" "time" - "github.com/clbanning/mxj" + "encoding/xml" + "net/http" + "net/http/httptest" + "github.com/minio-io/minio/pkg/api" "github.com/minio-io/minio/pkg/drivers" "github.com/minio-io/minio/pkg/drivers/donut" @@ -116,34 +116,6 @@ func (s *MySuite) TearDownTest(c *C) { s.Root = "" } -/* **** SAMPLE ERROR RESPONSE **** - - - AccessDenied - Access Denied - /mybucket/myphoto.jpg - F19772218238A85A - GuWkjyviSiGHizehqpmsD1ndz5NClSP19DOT+s2mv7gXGQ8/X1lhbDGiIJEXpGFD - -*/ - -type responseMap struct { - res *http.Response // response headers - resMsg mxj.Map // Keys: Code, Message, Resource, RequestId, HostId -} - -// parseResponse returns a new initialized S3.Error structure -func parseResponse(res *http.Response) (*responseMap, error) { - var err error - resp := responseMap{} - resp.res = res - resp.resMsg, err = mxj.NewMapXmlReader(res.Body) - if err != nil { - return nil, err - } - return &resp, nil -} - func (s *MySuite) TestNonExistantObject(c *C) { switch driver := s.Driver.(type) { case *mocks.Driver: @@ -303,13 +275,7 @@ func (s *MySuite) TestMultipleObjects(c *C) { typedDriver.On("GetObjectMetadata", "bucket", "object", "").Return(drivers.ObjectMetadata{}, drivers.ObjectNotFound{}).Once() response, err := http.Get(testServer.URL + "/bucket/object") c.Assert(err, IsNil) - responseMap, err := parseResponse(response) - c.Assert(err, IsNil) - c.Assert(responseMap.res.StatusCode, Equals, http.StatusNotFound) - values, err := responseMap.resMsg.ValuesForKey("Code") - c.Assert(err, IsNil) - c.Assert(values[0], Equals, "NoSuchKey") - + verifyError(c, response, "NoSuchKey", "The specified key does not exist.", http.StatusNotFound) //// test object 1 // get object @@ -416,12 +382,7 @@ func (s *MySuite) TestHeader(c *C) { typedDriver.On("GetObjectMetadata", "bucket", "object", "").Return(drivers.ObjectMetadata{}, drivers.ObjectNotFound{}).Once() response, err := http.Get(testServer.URL + "/bucket/object") c.Assert(err, IsNil) - responseMap, err := parseResponse(response) - c.Assert(err, IsNil) - c.Assert(responseMap.res.StatusCode, Equals, http.StatusNotFound) - values, err := responseMap.resMsg.ValuesForKey("Code") - c.Assert(err, IsNil) - c.Assert(values[0], Equals, "NoSuchKey") + verifyError(c, response, "NoSuchKey", "The specified key does not exist.", http.StatusNotFound) buffer := bytes.NewBufferString("hello world") typedDriver.On("CreateBucket", "bucket").Return(nil).Once()