From 17f2782db65e89ccfc1af9dfd518703d20ef0cfa Mon Sep 17 00:00:00 2001 From: Jim Teeuwen Date: Wed, 30 Oct 2013 02:11:04 +0100 Subject: [PATCH] Implements output of debug code. Partially imlpements output of release code. Reorganizes testdata directory. --- asset.go | 12 ++ bytewriter.go | 37 ++++++ config.go | 16 ++- convert.go | 104 ++++++++++----- debug.go | 69 ++++++++++ go-bindata/main.go | 20 +-- go-bindata/version.go | 2 +- release.go | 215 ++++++++++++++++++++++++++++++++ stringwriter.go | 30 +++++ testdata/gophercolor.png | Bin 21899 -> 0 bytes testdata/{ => in}/a/test.asset | 0 testdata/{ => in}/b/test.asset | 0 testdata/in/c/test.asset | 1 + testdata/out/bindata_debug.go | 51 ++++++++ testdata/out/bindata_release.go | 24 ++++ 15 files changed, 534 insertions(+), 47 deletions(-) create mode 100644 asset.go create mode 100644 bytewriter.go create mode 100644 debug.go create mode 100644 release.go create mode 100644 stringwriter.go delete mode 100644 testdata/gophercolor.png rename testdata/{ => in}/a/test.asset (100%) rename testdata/{ => in}/b/test.asset (100%) create mode 100644 testdata/in/c/test.asset create mode 100644 testdata/out/bindata_debug.go create mode 100644 testdata/out/bindata_release.go diff --git a/asset.go b/asset.go new file mode 100644 index 0000000..6f9e50d --- /dev/null +++ b/asset.go @@ -0,0 +1,12 @@ +// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication +// license. Its contents can be found at: +// http://creativecommons.org/publicdomain/zero/1.0/ + +package bindata + +// File is an asset entry for the table of contents. +type Asset struct { + Path string // Full file path. + Name string // Key used in TOC -- name by which asset is referenced. + Func string // Function name for the procedure returning the asset contents. +} diff --git a/bytewriter.go b/bytewriter.go new file mode 100644 index 0000000..c9b602c --- /dev/null +++ b/bytewriter.go @@ -0,0 +1,37 @@ +// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication +// license. Its contents can be found at: +// http://creativecommons.org/publicdomain/zero/1.0/ + +package bindata + +import ( + "fmt" + "io" +) + +var newline = []byte{'\n'} + +type ByteWriter struct { + io.Writer + c int +} + +func (w *ByteWriter) Write(p []byte) (n int, err error) { + if len(p) == 0 { + return + } + + for n = range p { + if w.c%12 == 0 { + w.Writer.Write(newline) + w.c = 0 + } + + fmt.Fprintf(w.Writer, "0x%02x,", p[n]) + w.c++ + } + + n++ + + return +} diff --git a/config.go b/config.go index c9d7f96..e27a860 100644 --- a/config.go +++ b/config.go @@ -6,11 +6,14 @@ package bindata // Config defines a set of options for the asset conversion. type Config struct { + // Name of the package to use. Defaults to 'main'. + Package string + // Tags specify a set of optional build tags, which should be // included in the generated output. The tags are appended to a // `// +build` line in the beginning of the output file // and must follow the build tags syntax specified by the go tool. - Tags []string + Tags string // Input defines the directory path, containing all asset files. // This may contain sub directories, which will be included in the @@ -86,7 +89,16 @@ type Config struct { /* Compress means the assets are GZIP compressed before being turned into Go code. The generated function will automatically unzip - the file data when called. + the file data when called. Defaults to true. */ Compress bool } + +// NewConfig returns a default configuration struct. +func NewConfig() *Config { + c := new(Config) + c.Package = "main" + c.NoMemCopy = false + c.Compress = true + return c +} diff --git a/convert.go b/convert.go index 757add6..7f77ddc 100644 --- a/convert.go +++ b/convert.go @@ -27,32 +27,67 @@ type ProgressFunc func(file string, current, total int) bool // to Go code and writes new files to the output directory specified // in the given configuration. func Translate(c *Config, pf ProgressFunc) error { - toc := make(map[string]string) - err := findFiles(c.Input, c.Prefix, toc) + var toc []Asset + err := findFiles(c.Input, c.Prefix, &toc) if err != nil { return err } + // Open output files. + debug, release, err := openOutput(c.Output) + if err != nil { + return err + } + + defer func() { + debug.Close() + release.Close() + }() + + // Prepare files -- write package header and build tags. + writeDebugHeader(debug, c) + writeReleaseHeader(release, c) + + // Convert assets and write them to the output files. var current int - for key, value := range toc { + for i := range toc { if pf != nil { current++ - if pf(key, current, len(toc)) { + if pf(toc[i].Path, current, len(toc)) { return nil } } - _ = value + writeDebug(debug, c, &toc[i]) + writeRelease(release, c, &toc[i]) } + // Generate TOC file. return nil } +// openOutput opens two output files. One for debug code and +// one for release code. +func openOutput(dir string) (*os.File, *os.File, error) { + debug, err := os.Create(filepath.Join(dir, "bindata_debug.go")) + if err != nil { + return nil, nil, err + } + + release, err := os.Create(filepath.Join(dir, "bindata_release.go")) + if err != nil { + debug.Close() + return nil, nil, err + } + + return debug, release, nil +} + // fillTOC recursively finds all the file paths in the given directory tree. // They are added to the given map as keys. Values will be safe function names // for each file, which will be used when generating the output code. -func findFiles(dir, prefix string, toc map[string]string) error { +func findFiles(dir, prefix string, toc *[]Asset) error { if len(prefix) > 0 { dir, _ = filepath.Abs(dir) prefix, _ = filepath.Abs(prefix) @@ -71,28 +106,32 @@ func findFiles(dir, prefix string, toc map[string]string) error { } for _, file := range list { - key := filepath.Join(dir, file.Name()) + var asset Asset + asset.Path = filepath.Join(dir, file.Name()) + asset.Name = asset.Path if file.IsDir() { - findFiles(key, prefix, toc) - } else { - if strings.HasPrefix(key, prefix) { - key = key[len(prefix):] - } - - // If we have a leading slash, get rid of it. - if len(key) > 0 && key[0] == '/' { - key = key[1:] - } - - // This shouldn't happen. - if len(key) == 0 { - return fmt.Errorf("Invalid file: %v", filepath.Join(dir, file.Name())) - } - - value := safeFunctionName(key) - toc[key] = value + findFiles(asset.Path, prefix, toc) + continue } + + if strings.HasPrefix(asset.Name, prefix) { + asset.Name = asset.Name[len(prefix):] + } + + // If we have a leading slash, get rid of it. + if len(asset.Name) > 0 && asset.Name[0] == '/' { + asset.Name = asset.Name[1:] + } + + // This shouldn't happen. + if len(asset.Name) == 0 { + return fmt.Errorf("Invalid file: %v", asset.Path) + } + + asset.Func = safeFunctionName(asset.Name) + asset.Path, _ = filepath.Abs(asset.Path) + *toc = append(*toc, asset) } return nil @@ -106,15 +145,20 @@ func safeFunctionName(name string) string { name = strings.ToLower(name) name = regFuncName.ReplaceAllString(name, "_") - // Identifier can't start with a digit. - if unicode.IsDigit(rune(name[0])) { - name = "_" + name - } - // Get rid of "__" instances for niceness. for strings.Index(name, "__") > -1 { name = strings.Replace(name, "__", "_", -1) } + // Leading underscores are silly (unless they prefix a digit (see below)). + for len(name) > 1 && name[0] == '_' { + name = name[1:] + } + + // Identifier can't start with a digit. + if unicode.IsDigit(rune(name[0])) { + name = "_" + name + } + return name } diff --git a/debug.go b/debug.go new file mode 100644 index 0000000..0b70c8a --- /dev/null +++ b/debug.go @@ -0,0 +1,69 @@ +// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication +// license. Its contents can be found at: +// http://creativecommons.org/publicdomain/zero/1.0/ + +package bindata + +import ( + "fmt" + "io" +) + +// writeDebugHeader writes output file headers with the given build tags. +// This targets debug builds. +func writeDebugHeader(w io.Writer, c *Config) { + // Write build tags, if applicable. + if len(c.Tags) > 0 { + fmt.Fprintf(w, "// +build !release %s\n\n", c.Tags) + } else { + fmt.Fprintf(w, "// +build !release\n\n") + } + + // Write package declaration + fmt.Fprintf(w, "package %s\n\n", c.Package) + + // Define packages we need to import. + // And add the asset_read function. This is called + // from asset-specific functions. + fmt.Fprintf(w, `import ( + "bytes" + "io" + "log" + "os" +) + +// bindata_read reads the given file from disk. +// It panics if anything went wrong. +func bindata_read(path, name string) []byte { + fd, err := os.Open(path) + if err != nil { + log.Fatalf("Read %%s: %%v", name, err) + } + + defer fd.Close() + + var buf bytes.Buffer + _, err = io.Copy(&buf, fd) + if err != nil { + log.Fatalf("Read %%s: %%v", name, err) + } + + return buf.Bytes() +} + +`) +} + +// writeDebug write a debug entry for the given asset. +// A debug entry is simply a function which reads the asset from +// the original file (e.g.: from disk). +func writeDebug(w io.Writer, c *Config, asset *Asset) { + fmt.Fprintf(w, `func %s() []byte { + return bindata_read( + %q, + %q, + ) +} + +`, asset.Func, asset.Path, asset.Name) +} diff --git a/go-bindata/main.go b/go-bindata/main.go index bd07afe..df3f006 100644 --- a/go-bindata/main.go +++ b/go-bindata/main.go @@ -10,7 +10,6 @@ import ( "github.com/jteeuwen/go-bindata" "os" "path/filepath" - "strings" ) func main() { @@ -29,19 +28,19 @@ func main() { // any of the command line options are incorrect. func parseArgs() (*bindata.Config, bindata.ProgressFunc) { var version, quiet bool - var tagstr string - c := new(bindata.Config) + c := bindata.NewConfig() flag.Usage = func() { fmt.Printf("Usage: %s [options] []\n\n", os.Args[0]) flag.PrintDefaults() } - flag.StringVar(&tagstr, "tags", "", "Comma-separated list of build tags to include.") - flag.StringVar(&c.Prefix, "prefix", "", "Optional path prefix to strip off map keys and function names.") - flag.BoolVar(&c.NoMemCopy, "nomemcopy", false, "Use a .rodata hack to get rid of unnecessary memcopies. Refer to the documentation to see what implications this carries.") - flag.BoolVar(&c.Compress, "compress", false, "Assets will be GZIP compressed when this flag is specified.") + flag.StringVar(&c.Tags, "tags", c.Tags, "Comma-separated list of build tags to include.") + flag.StringVar(&c.Prefix, "prefix", c.Prefix, "Optional path prefix to strip off map keys and function names.") + flag.StringVar(&c.Package, "pkg", c.Package, "Package name to use in the generated code.") + flag.BoolVar(&c.NoMemCopy, "nomemcopy", c.NoMemCopy, "Use a .rodata hack to get rid of unnecessary memcopies. Refer to the documentation to see what implications this carries.") + flag.BoolVar(&c.Compress, "compress", c.Compress, "Assets will be GZIP compressed when this flag is specified.") flag.BoolVar(&version, "version", false, "Displays version information.") flag.BoolVar(&quiet, "quiet", false, "Do not print conversion status.") flag.Parse() @@ -102,13 +101,6 @@ func parseArgs() (*bindata.Config, bindata.ProgressFunc) { } } - // Process build tags. - if len(tagstr) > 0 { - c.Tags = strings.Split(tagstr, ",") - } else { - c.Tags = append(c.Tags, "debug") - } - if quiet { return c, nil } diff --git a/go-bindata/version.go b/go-bindata/version.go index 25e75cd..a12508e 100644 --- a/go-bindata/version.go +++ b/go-bindata/version.go @@ -10,7 +10,7 @@ import ( ) const ( - AppName = "bindata" + AppName = "go-bindata" AppVersionMajor = 3 AppVersionMinor = 1 ) diff --git a/release.go b/release.go new file mode 100644 index 0000000..a893001 --- /dev/null +++ b/release.go @@ -0,0 +1,215 @@ +// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication +// license. Its contents can be found at: +// http://creativecommons.org/publicdomain/zero/1.0/ + +package bindata + +import ( + "compress/gzip" + "fmt" + "io" + "os" +) + +// writeReleaseHeader writes output file headers with the given build tags. +// This targets release builds. +func writeReleaseHeader(w io.Writer, c *Config) { + // Write build tags, if applicable. + if len(c.Tags) > 0 { + fmt.Fprintf(w, "// +build release %s\n\n", c.Tags) + } else { + fmt.Fprintf(w, "// +build release\n\n") + } + + // Write package declaration + fmt.Fprintf(w, "package %s\n\n", c.Package) + + if c.Compress { + if c.NoMemCopy { + header_compressed_nomemcopy(w) + } else { + header_compressed_memcopy(w) + } + } else { + if c.NoMemCopy { + header_uncompressed_nomemcopy(w) + } else { + header_uncompressed_memcopy(w) + } + } +} + +// writeRelease write a release entry for the given asset. +// A release entry is a function which embeds and returns +// the file's byte content. +func writeRelease(w io.Writer, c *Config, asset *Asset) error { + fd, err := os.Open(asset.Path) + if err != nil { + return err + } + + defer fd.Close() + + if c.Compress { + if c.NoMemCopy { + compressed_nomemcopy(w, asset, fd) + } else { + compressed_memcopy(w, asset, fd) + } + } else { + if c.NoMemCopy { + uncompressed_nomemcopy(w, asset, fd) + } else { + uncompressed_memcopy(w, asset, fd) + } + } + + return nil +} + +func header_compressed_nomemcopy(w io.Writer) { + fmt.Fprintf(w, ` +import ( + "bytes" + "compress/gzip" + "io" + "log" + "reflect" + "unsafe" +) + +func bindata_read(data, name string) []byte { + var empty [0]byte + sx := (*reflect.StringHeader)(unsafe.Pointer(&data)) + b := empty[:] + bx := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + bx.Data = sx.Data + bx.Len = len(data) + bx.Cap = bx.Len + + gz, err := gzip.NewReader(bytes.NewBuffer(b)) + if err != nil { + log.Fatalf("Read %%q: %%v", name, err) + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, gz) + gz.Close() + + if err != nil { + log.Fatalf("Read %%q: %%v", name, err) + } + + return buf.Bytes() +} + +`) +} + +func header_compressed_memcopy(w io.Writer) { + fmt.Fprintf(w, ` +import ( + "bytes" + "compress/gzip" + "io" + "log" +) + +func bindata_read(data []byte, name string) []byte { + gz, err := gzip.NewReader(bytes.NewBuffer(data)) + if err != nil { + log.Fatalf("Read %%q: %%v", name, err) + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, gz) + gz.Close() + + if err != nil { + log.Fatalf("Read %%q: %%v", name, err) + } + + return buf.Bytes() +} + +`) +} + +func header_uncompressed_nomemcopy(w io.Writer) { + fmt.Fprintf(w, ` +import ( + "log" + "reflect" + "unsafe" +) + +func bindata_read(data, name string) []byte { + var empty [0]byte + sx := (*reflect.StringHeader)(unsafe.Pointer(&data)) + b := empty[:] + bx := (*reflect.SliceHeader)(unsafe.Pointer(&b)) + bx.Data = sx.Data + bx.Len = len(data) + bx.Cap = bx.Len + return b +} + +`) +} + +func header_uncompressed_memcopy(w io.Writer) { + // nop -- We require no imports or helper functions. +} + +func compressed_nomemcopy(w io.Writer, asset *Asset, r io.Reader) { + fmt.Fprintf(w, `var _%s = "`, asset.Func) + + gz := gzip.NewWriter(&StringWriter{Writer: w}) + io.Copy(gz, r) + gz.Close() + + fmt.Fprintf(w, `" + +func %s() []byte { + return bindata_read( + _%s, + %q, + ) +} + +`, asset.Func, asset.Func, asset.Name) +} + +func compressed_memcopy(w io.Writer, asset *Asset, r io.Reader) { + fmt.Fprintf(w, `func %s() []byte { + return bindata_read([]byte{`, asset.Func) + + gz := gzip.NewWriter(&ByteWriter{Writer: w}) + io.Copy(gz, r) + gz.Close() + + fmt.Fprintf(w, ` + }, + %q, + ) +} + +`, asset.Name) +} + +func uncompressed_nomemcopy(w io.Writer, asset *Asset, r io.Reader) { + +} + +func uncompressed_memcopy(w io.Writer, asset *Asset, r io.Reader) { + fmt.Fprintf(w, `func %s() []byte { + return []byte{`, asset.Func) + + io.Copy(&ByteWriter{Writer: w}, r) + + fmt.Fprintf(w, ` + } +} + +`) +} diff --git a/stringwriter.go b/stringwriter.go new file mode 100644 index 0000000..278f35b --- /dev/null +++ b/stringwriter.go @@ -0,0 +1,30 @@ +// This work is subject to the CC0 1.0 Universal (CC0 1.0) Public Domain Dedication +// license. Its contents can be found at: +// http://creativecommons.org/publicdomain/zero/1.0/ + +package bindata + +import ( + "fmt" + "io" +) + +type StringWriter struct { + io.Writer + c int +} + +func (w *StringWriter) Write(p []byte) (n int, err error) { + if len(p) == 0 { + return + } + + for n = range p { + fmt.Fprintf(w.Writer, "\\x%02x", p[n]) + w.c++ + } + + n++ + + return +} diff --git a/testdata/gophercolor.png b/testdata/gophercolor.png deleted file mode 100644 index c9697c77ac18494d3465006c8d1328c8fe7de5d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21899 zcmXtXzQ{17rySuwJ=XcJADawCGgvWyifk22-l48oh->3f`u%Ch7p{LsXAP~HQrKqT)qJ_PSy|abA z1BsNVD2aoUy_uzrDG21ToS|Z_s&a(I4_UtzkqPxrkg-?Bge6fHiSWmWrJ^H+Ly-<8 z%~`@!>OmD3|A;@F9SR*4<^Km$iQ!8){6Cmo(%h)ud7&s#t9tQXoL`x9>sivkDb zHyL$PFx{|Uk|f!bIQ+kqh!CM}{vPTd+}dRl`UOwn078MSGa+?;C5Hk%`10}5lXb&% zf}lLW2(X}Tx%6%pf{=IQW06!{DE~mHZkO0^GO+#_AR(_PkwTD=1eAY93Y7{d`y=Sb zn6c3gNRbirgW7K&4D!!-Nc{-~(n%o2gvyQuk)WG~ih(S6LFH5G;o=}o77&J+Og}g1 zA0voGO2bSNRNVyXoY1;Ks+u_%QG(Skny1pOE$C-(parh+get~L0s=qphU=zx_< zt>tT>;1>U-1Iy?LqoKh>L^COcO^?B8_`xtuh^f~z6_@oFJM!kuI0%#-iwT_V&8x>G zQsv|%XH+AS0poGk=XWwAqn)?CsWJy45NONAcjk?Oxem{t_p`t4TQ24KM+<#~Y*$Ex zSuL_q11S4wS>wjxzqJw1iD_9{+S}dzC*3ciV>qhe^Jd;_(5>-m^XSX>0=e7l+@|=& zs`u;r$A`_{@mtvff~h#TK%>?D=pVv5duf#?bdN)F_%R-P;fl=(^3mXO0FI+TY^$)|C7E zh2ZP=Y)X*7nN*x32&6AY!K6A`CpZKP0*Ph+qN^6hzwNAO5^J%pQ;pGQspa?~O zuLz0=yoo=7(+}G601=wtiE2W+AIx(?gzVi)7QyijNKCzI%}D$X$WMl_nLRY^zu-O! z55uAxk}iir8HH<-N5NvJ20f7WNPa|%pdc9u#ZV%XiRF;|svNFLq9#dr&F}PqJ49Ea zHI{c6#2WAt-2VM*!mnB-{<$v=qAkT-c!3hR2-7AmU(=$oveT!X>hbvhaONCLmsub$ zM+=A!v2-8ez_9h(urLkwiPU^!fQvUCt061@QZ|TJtzHh@7ItSmRpb55sYVnZ2_^YI&^78T}vdAPoCD89XtAdn0yF*>;45X81wf~ zs5uR8It~nuIj%cSRf=pOE;s^rNR@@_>q*K%Dsrm5nkHQ%oi}FeD14%HB2^+j9kXgl zX<_MlDT3OK+L&r|iN1>7ie_CXQ^W869q22yLpvS8O=9Q{-^6HDH1bZsfGgl!T0r6oDsqHNM^ z8gROj3B`0Z?NtP*%LHYUimVK!#BX;XwOH;JhXD9B&ydZ zBwApYXqdbe7~3+#mp3mFDS`aQa!_}NV#jvSb}*0XGZiV7jNGx@d783ZOCfC`uPm?Z z(8Tye?!-bWM>_x4Mb?A#gY?Dpjiw*k9@-3z#f{CTQnkCiYT9~r z5)~O0lnZSYZAGX>E%Nd5Wtj`+ebrZuBaJ0ZxYc|AKCe_Z+BW(anj2x8Hw{$woyT{? z`?UH*zVgE$hAbhK5o#0qI@dd4@Tl{wr%nDn7xWppO*&#W*PKF``p34@h(1Q!Z<(Qz z4*qVAZQkPi`zACZOeSEADOrFi9e;3bxMNq^<<3!W%WL*7BfT!Y_pErO>YVf3@;qcU zYn(lcHdBkudAe^{bW>?>Mi3z@k;QtW+*d(V;g@;C0XefVbF4kNn-_-Rpe@ROC+yWey$oOZb=0hvx?` zZ_=(PL7o-U``V>5;Xm0e!kEI*0TlszJr$%D!>2J7q>zJ@$=FFtq##A#!-Z)W!+pbu zKHo3YK_NjJ!Gci^p_+IzUz0i9XI4d>H^iRAlEl{2&A%#eS20R+&S@A7%wX(Mg z4l2=(C&d6; z0mEKPAazMhyDXyYS~^cAR+<}$Eh|4y$JgI+u`!M!rKEE4jpoPZ`(|!q<)%TkZv%D_ zP0U1zFeBD=G3B4M7~va53J+DaX%^{VYRyeG%(^DRM!A#9GU+GI#_L8`Vz~ZZWWArE z^`dRXH5LTRXfP6L?st@1ao6%Wdal6lV1A+xR{vbi*BstRXFIP@cBYYB>Dxi&C1?Fh zzh^X{rvb|P1VIgcFUaR)b@5D3L6cc)qrvbgI0Ih*Gc3FkV+A`I)9)Y6s>dFFi2Z0+ z>S{uLNm+l3$&}fw+0p(wW2O#LQfcyjGLjwQ(sDiGhI;+k-M#nCr>dv#nl*yshKe5cDkcD-1bO<6_I)JmDz)rj0<;0 zL{3Dt$iIWz527u3gzf*J##AtKu=RJ$5S*|B z206md3G0U99?9b-QQZ%&dNgd=C0O^%i>(NV* z=#RRybWZ9U2hUUns5N+ z?2e*%;2AgvNiAm(NLS*&2NXtvs4(y(jEj_DvF6I(T2kYghy%&h@g7ghK9n@g@=aI(2+fHqO9feWLwmZa#AW0r9Wb{Ys^xqD@574CMo4OI{Gdx zIh4`2$D#C7zu74Z6H*Gp63|G+NUiDQJzkZi^AkD^0)=3OD|w@Z$pwBKWd0`LPm1-k znbt)iSLLuPGdvv^FgHavoajlRHMQG&$=dC5sh)O!MoMRVqExfJZCL48^=CMl*AYWz zu+aX{+F9pMu*c3wC$$JBikWp~#-Rx(Db)Qq#kU-hUTGUn_K~Q{x0fS7;V}>^rBF&e zDneI-D7}fg&SLMgNB{wWw3H}n01w=JbBCxko!IvrI(RdIt00tr?3h)C)t60o-Y<9F zZ_724Txt>&$;=rz_G7Bni)d==Y3CGnk{lCa2F2BF*$OMq6*X3@QU51ncy4y-vD86Y z;n6!}jJb=&_r;_0{p}e&%CmZC;>)QsZ>{2Ym1!a{JFwo2h0-aDgxVo&IHl(69~qJcY}XsPDF2Dx|^6p5C8d7b;E#I8>(N5iVfilLGB7J zoNrfJjPHU5Z&j~6c%RnIm8)MRFx?zU{%Be`bvNApPbGS)oOJqd52i;geWuTz!$N+?RvJ~dc0t^KsJ@$BiHesifuM{N;F-@+2wro z>QbTlHedpA309c|xZHC%1kF)9ZprAZgfzXLo^`s5m0OJJy?0td#9!%4GthAnhF9J) z&A+J+%lVzw4B_y5u^Sp1Vw;E~Opc9>82nKbz zofnvQDS_B!$|vUBLt-*^cuELA^__&1vB-rb2u$tT*lM?084E07>V;NMhlVnF;^MxW z(i#bkLi<&xjOP%iG>{GgWq zD|xZr0f&SnU>}fmuCFZJXtN~J=5{72Cr8QtEtJxrD=0TqW&J==num}WCmkp~tDJnD~?Z9m|b6*C8ULqI?x5*1trARRuE7WtSdz;Kq*4mf-eB+8gYOxHPQi z>`LMcBg+)=Tjju*CenlTpKWWJzKU5Z1*N6iHhEJ;D)*QtZ`)zm8^Y2Sv-xm02UFBc zOqF6f212!y8N6)v>wH$KCEds>`h6J(+g$U=nFiCxm?Vt zGRWs6!Teo%WPS~1%PAsHxs^_H+0Bh630C?uBED}v{MN$^%l*X9i#=cA_;rtP?W@Ef zMvI-N`a}u)R=umi6ALN%79* zcCjuuk;Vb_aJSL~hX}{B=jchq?9Rs%@EW2b{|EtgSEi0#%U+oJun2G;91YbMkE+>zJb1iA z9&Zi|l;fcLhlXx$!3xmR4HuVS?H_G&#tYy3Xt6PUN4wtBcR_9UMB5J1Pq-IZCzJFJ z1OW^ab)ov()hj+fyVN+I0K>BTm_tpFm zx2k|9;0Qg~@k}kuyu&@{kfu~4ieDxrf6rjW?5JA&HckW)BqFMl5OONpHi7>B_|N=d z`^?;N&og{t8J_gP@XG2P?~4EDJqiYfs?kDwHuO@PJF~E`FyB=_dJ!KJ2S+0CWd#9O zi{nW}(}$RhGakdO$&$>0vXgeM7dSIH0^dQm+m1G{RNIyOn))xxeF~i?3)GI3wObyL zh4v@$(3G5|r84DgCy9 zcgJrnXJEr_e<<(QyTva=eE;58s+)?k|K|97QnBJF9jx&lE{=r{Xy&8{;zGh-#Q zp`y-DAL*O9?xwJ#*X4&s!S^5xTs<@6Wc#U1CvV zK7%LiH%km(!2RrN&J1Vup}sxUOQn1Cra{k*_Vy<=ORKh6e*6+{T?G^3SHTN*%TNz) zxq4sz5b`!k4!NE!Cn5_xbiezIB{9A+R$C6$O&V5DQ};T>8ZtaSG5URXydzYoJ?NeR z>zm&zbV(V&VwUS@TcN(T=U7&N6z7}0vQ4EuO{CMy(6sn}^2HkFY#U7&zSmsYgMh{H zQ_6g{apV@7%H&VwcBYCJc%s3iS05*Cs|J^-P=oG?rTLkc!~%mZ`wprer#h^=X;|x= z70B8a%i?|cbc(HR#i}6wW3%cJhuA+x>hOQtHm!76AspsZq|F`tMtv3E`WQ}$NK0uj zsSOhH@OThURYrj4d0vk1o$@`LCS{k)b30q+yBTNeWI3qPJ7COeKBO`8JJs1far)_D zbJ!Lb^f~MD)bD~DmW0$Qrl16CW(v2bXW|-@+vV?AgCoC38FV}QrT*8W$Q}>Z*W5}m z`oC^cN(m887blf%=jB7P>6{Z;w2j%ep!qTln9U(dYk1RCes|R}jK1Eg^?Xkw!p4`5 zkQ1-h_`P$a$VB6&>;=Q~6P18mv^YZUhKN2)PVI9m^ef zH9Qa|$gR`dl=wnVs=D6Vr>b;YY6T^*vA=nvVxo@rYh;j<*= zU0GpJdK4PISkhLA-{!WKB3>I`!7E&>J#SzP(<3|hlu>-O2dIM@O|&Pf?tYz?iyrgi zSL%&pjv&Z}-}~RmbPnqUxJp;aYV%00Rfl!T&tZ+jd3+-)V zELX-{Y+R;Avq0FlF_x%ys999BQw;L=XA*P?BogXHAE&205qP~>XeZ$)zfx-4f$G1F z#pdrj9dP%ZV zf~;mI?uB5Jxr8Jv!GZMbENIs~&JC~m^xy9#NrlwZYMobKGTO8L>?{#XjrOp}<>rz7 zYk{DA-6JbT!8NO_)%8Sbh{JX{VQ(zixNb@Qn8s#+!0a$s7?Qs7-)!3XurY4|gN%>o z#kjO2Q?nAk&6mlT_4`1gsBiKov!L);zSmnMO=+&fsRx#f`rAl&gU*BFQ5u<^V4?R% zXrkr}>og7u9=g9b6BH``;`CfB7X2_^2ze4T^gZ`-M@y@RYE8$m7Ao~*TwK_tq@?-> z1~PVMUS4jdTn?vyDd-c+*7YwBtYfLE;c&mvcc!*|6o-57V`od(x@`#cMH3OJB&9yk zV6T|HYxQ-25_;91e>8hRcpIk<&)vN8NNuvf>>KiVi(bjIR4vzxjfp{N*JpNXBc!El ztu#)f;^yXV)@5R4dtaJ!G(Twkatw|nDcWgITw#$*bM*`WdRcs$c57L@%gI7yDx3NB zlFn3&YL!`-3tzCM(^r!Mq130sp< z!ob^@)%ei6RjfkIY`@|bF^DxYQ?GsawDIpu?flXMC}z1{;%0s?@cMcX`lDqz-iN6= z`^O5eF5g#=gA8|hC&Q_My*m#+cI$;dk@#F_yY+Pz$2bITE8OS}C**xn>wYPS_?$5* zDVlVqe-jhM#R9AF#zs>wwi$W=gN@DiAyH%fwd)0RqsM&ITe?|D&RpdBKQ=2JeE z*7opy%y3^P<>0^+S2~r9iCBcjX%Fw|MmU+IHjvrHn)UMq2nnw zYgZL6-uqJsekit*9!T_xMut;lw=KKS~Lnx+@B zdaq)?RGV;socG7K2J!6~zQ$!8wE{(i5*U{Szz59xtx1uz#F)MdoO7l6VGZf-EY6eO zjrJSzkn=U>l5#Hl_3?_Pb?J%+I$56sPp1426G1{;UjY21Rd2-qLwC!`_IWwi6{O=L zUJ|gfR`)j{HP2}5`{-hpk0c;Xd{3IJHw?{Qs=xT-vYAa6$RwkYdj2Yyn4H|-3LyrR zN@f%x?<}Bq&}(bkA?rUutGpI2u@YOZeLqH1ib`-)qDoYXt~cJ_AaNs49gy`r!@gi$ zr94(P>P{CaHwflE!};l4((t8X{&)vJ`)%vBqoXK;8I0SX%7R}+EvM-8VDy4@J=y=_5z>nTZg;6 zLVu5%X^FOnnsVRp`F=2&!CV@6FrM0H+q4#(OH-Z>f!e36-F;6QyTEU}I*f7j-{Bv| z|DnX&9eVE4*ng%URx06RjdQeS?tO^{H&36L{Sjam+2&ob_123~K?vAMnmU}e%VKqA z6T@S?K8dku9M*AZX`_1XYvMpn&y$E00jsJ{5gC~DmT%O?`!YvT^9~I>-JMvjHeZRy z-T|Fh?rgc!_4ESC?=R;Beqvgpms|QEv_iDu{1c(wbOo#2ul?4xHF~9lV=g=iFUXLW zdyd;nSb92v8~%kaCqnv!x)HFSx9_|x=Za@=rI4zv7n!u1>?Zod(2u}H(Nm0zi0kj$ zZDbo&jvZ+)*M4~=`Yj)TUSqRVThPD9XE{qDI6~Y}#J1Qd$)Gmoc*CdvwBd)J&8x=I z7%hGVBKJC35QGD--o%3qlaV*(uL6}Nm8Ij53AUOz(wnaa@nzWMy^l+Z!o6RR1z$kj z(SmQoz}kN9&eCzuDY1&ZIH+DpdFx^675!~FoehOfCA;~r#+W)1QM;x z+Pdb1nC|B?;p3ZBjnVA_e z35i?2MNlWU37E|Ya1^~nff1rql>iC+P#a8N2bm;u@$F>%dI*hHUL}Y zCwRYH4S~w_+LC~)<3Vp~WaG_4o&rt8KcPJBm1rlJKNxIy@Nl(5K}CgziuwyB0C-uo z&$An#02FZ50TyazM)eH2Fuy&V`Dep@_Ap4W*YJ4kg3}jI5Pd=DMC_vHw{x;94D6S+qc4=!99v#i>xOinl6FNe#S_~3W zRz~yhO4+LANT1?9#}wHFNJj@4~Ow6 zhm;)jBe2GUs831SR3CQZ6^6&gc7m|=L6eS0B^FZ^uvz zEs=(jgBAa=-zC6X;!v%)oxzas@U)7pfD2@>_s6-NX{!SWZ9dVEc$KMljOX7!TXe8cC_&J#`s>%`+>dilG)izloX z(-huqB%?yaQi!&pboTKnXcN8XPvWKY|i424?erb-9X&tWla*J^wtrP%Yki#F-nsr;MNKzE5(2699UR z%XbZZj?a$Q69%?6tq5+`SUmcvKz+#wi=Z)o%nuMAEmF=^miyIDW}-syr2VP;nH`xC z8fRkCBfv)g4+A~|W!-(ycoCRku52QN2~ASH4mkpZ^4Bs$LR=LZMnF8Ci-cx$gcE%=f~oSjg3;i-pBcwI4$z_CPL@ zPngX5Eb0J(4(zkz-SM0+Q@!-N_u!+f)Rixa2M!nW_wRTpD!F`V0FTW-7G-5+fCG+5 zB{g=(VXp@~LC&FdmmX`_;$HfY1x?PD8^+T(PO@tJw=URrClped@2}H#S&U4L;jr zbVu5zNw>+N-(bBVJxHH1WpeJB&TiDLRdDk{XL_~%sCQMg) zM|M5=+TR}usC+pt>LC_$#i;mPc6=9{oB*|*ramX_)c*7#@j_WT&E;CnzIMr~@y^Sg zu|XH2yys=g@!?q`*sRZT}acm!gOiabal^pYfI<53_Az{gz-SrLkLaEdHv956^Z6C2%H-`_? zcq}&Y%m~ui$DmV(Tcu$>k+pKP4519Z?+O7REu!Q}r6rxM4pptmUY17(j6D=XZgQHY zNSFsNv;9rHzxR2K{_T-t{IKgm?2gm(&!heq*}R|kgxos~U-~FIwF%N2DU%;Yn-O{d zX#wTHb82F;|2J_L6oJhwaJFIBRzr!r;fkOi9c7s2i&j?J8~=VZiX5@XVtcMU%UX-` zxSp(9fg>6*==#BKdXhyp(|1=ssr&`~5($*qWOOU@M>>%R4qB(slE_aPfNf7Nt}|t0 zuDh)_^0lG9C(c+M<2N2hZeR}T{_X~TYr=8Z7k`|2jw0@H{QtOerTFB^+(Ex!(`a4tu-5_MdI(>2@`np zX7}Hj$tS?*%BW<5f;e*}T6^VY9d6#3amUmwp4Yp|T9d;kceO4@%DH4BxXTxI>}N0f zQf2ffGw+?wW1Qr_($sb&OS8Hc2!ASJpgPpFTBf!09SVR-PGEw02_i88?t&^J=6q5S zcY6AXw?|P`4VAb{pjZ-9a{h(;>T^SB)}6pPA96J0ycYoMT5WE&CCVnGfqq#pukJ40 z332#UmR?cDcmbIiReN2??tSc2uS;LRyRAuK9vwVgFO5tj*o$+;Xa~r**Vp&|7;_C& zt&>Loa_5N3-gsaNt^RyQeAB%Cv#a>AjO*o-P=hpPxLD!-V>$tk`?+o@#$zPc`j3$~ z%Eua4^ZbOlaAvQ^iv_t8wu7Cm|Jp-9;jrvc#9kI2_g9kd8<^rOXC2trg4S68xeryG zmzEhO< zuv1o4mHRF47>|8N!6zJc7_fLd`^rOxVH1?i@TIul4(ynMOj%h+)^+#FS7jfV7kYC zUm$CWYp5meN1jxB^>NCwjak;sPhEL6CE(^7h%Bzz=%H|Nl&b9fVaiKD12lx~q>-JE z1rBclce9KJi zBaH3{KnVbFgk-e5t)kke^uk;k=`b7ei4oVE-Ow<9`_JSx^4>zs5g9DGf&x3+nmS36 zz9S4?Hm78Fhcj*y2%XX1$31mSxM$1m-~28F6pKUDCux~DlRJS%IYE|U<&YlFQ>seW>t1Eb5}Fy zl1QCuCZ7;Q!to;DNmF<&DK^X6urM*jt*nm4FZI3om4~7TANSMkK`Bq`C<)%Z9d|X+ z4~%$=Ii~SE1MHxJA5E6uPB{a96Xctl-K+&{Xtns_iw^n9Cx-+>cODHrW<`<>TQZ}s zXmw>=D!Fd2GU(p+h)+X-jfpCJ06ggMx;7OP z8!K#M!vHRn%QK(K9I%^#uT0L!kc+@#d^lm=u<1c~Jueilzyr*CIklyZDUD>G&EHLi zI0pugVqjHvHN&23#Fy$_8DJ{A`PQo*JCQd3s(XDCjv-Io=<$Zs-onhhOw*jcs`U9JAbAoH5A3%{(>v`Y?8-s7DSdk}x6+P=W6N*Et zokyFsV;-Cak-KKByDfk@AfSTxe#_}+Xn45M{&*_z>7ZyS1z&H`zef?|ST9!k+oQ$~ z<*BHn>IlRElZ<5Qfnq{v$uIe983`BKM9fcFYyj5&xmv+hpKsS&;{4fUZx^ejb|jU- z4jAD(J)X5B_}5_aNBAMDzrjZ)tIduC-yE`s7qvUQI8=({P5VQWQAIAt*`_w{yjqTy z&0en7KI)%ttaL$NY@BoYuc){{w4}rO?2KO$E*`9+>=FF{Vfz}!RH|Mf4b%}SSy{fV zzW}nEEmfnBgAf}Y>cm6Sk?yv*4U0Z+h&seTgZb9S%*tF$vjuM`J;9~g{DUm_1fOt# zhSBQYeqYZ_K|drO@-vIq(l8VyKu*xdd*M&X!S(g;-vsU7+`_wB5rpZuyoScf)EAZw^)ph_NVb&Ay$u}8?`0%=SnBEHa}9d25mBxaRzVL(g| zMH3%{&{ipt^3;yEoC^@DHvjClwpne|3Gm_Ys8mkCk!2eo^SbJ_3;14dr=11)ek-_h zt1Z3k$g}#qDwX8W_kw(NEK$?MK+l^z6w)zd0DQ&scj!%n`{WeEVH1T)dD5TIP6ok8 zPf7I_x-fcNz#xO^DZn#)wE5JQwcov^dVaEysbg>9DG|5A9ytQ`GrFIm$K~^2vG2HB zfcqW#pK%JHjW?5&qEXi_w=-=321uNxsXc7KFlQ)MRWfMZ6^F7c-{SOliqgWOwo8w$ zmN7)=uX15c8Wgw~5E5ecFdIY(oLr5m+ixejcXcNoP}1{ahpY_}Z^+T0Qr_*!X~4Si zNKTFC>Y9ARP330L?TiAjiHly5&k0qEGGJI^tCH(Vj||$5ta5p_`bP&R-GP@~*?{PH;=5^l|N996Yr0aeO=Z+(t<_c6b1%`v z!~_Ku)zPYol0M?{(xFr>-1NMNdNU8-Pa5*D@wLTLy7T~>EGA)gJn7)S;eB|=9dIf(ff&M6y8v93-R9l# zf7jU>G4UR?r(z7WKR~528;xyNo4*21D&V`UZ%Ae4ZyFljUTkD_z(m)+E5e&%rY^NG zr14O_r_(w+6*AA?5sFDPHihaF&}f{O{r;4d{L%?k7aE}kLpMEgtQVF14$Uz zQ!w9uMn7L1c5jTpwEWz(I4Am+=9u*~`>n}FIU1K3$@t72U9wm|3=lDYbI{fPH9L|6 zg=McO%a^A@7a?4r^P8KrP?e)#`Y9qfA98kf!>?;^EKUoNkQn>`R6v0;eY<+gLVml4HX)cAGy~I=p@{sD zj_*Nsh2RS&TVHztr~3KuDbu?E=|Y`kwWrE^_{QEhe9exRe5p+1-ZW{+{lTJ}ZawvF zp}DeZ;W>5HiS#3f)!ZhK(BXruIv4SuFX-4a)+M#G$f`IQG~vTrTTH~neAdtsW2W-x zcvcRCHHft@|4#~X-TMYNq`y&79M0i-A*lC9zCQSwvNpOLcs5s>8W+lPKg%itDVK+* zld6&7;co@yMBbOe07AVy_DZE{Mfo5Oo9Wfu_TKdOuWgpL7<1z{ek@ux9eU|N!Kter za?6*4rJDLvPXDQQ2m)!3{Ap)Lf9H6~qjZbW**+`xdl^0z;>m+sms~pMS$#%ELY&pS zw@j$@eCYrJb9?uADjP0`6^8q|C$)yInoC!KTn>#=6+R20 zmZe2t;k?jde9ekA_0dz#x{w^$MGwl0{F3rZu}&R4rqQUQUlV?b^4Byscm7B@uqMB` zcd9BNV#!N(^4O(q0EKKl=}}%b1h0+sb53DY7?`aOBD&SD_=<)UWl z=xJsq`PDfQ9-)95dh^Q00J)rb4vGSIF!s4azheTZKyqAmGG+tBI=g-Dt{6h8Zd^eq zb8^Ll#C|V5g>vZ@)7d?=Bdq|A>l$$XXY0~-gjcE>o^x}jp~OUX8kpgN<^A}H_+)KB z!9{PXm6c-G&dI5>wf%0-$Bg~$N6f@A0qy=lz*C) zUFUe`N6VS^>%^mDzt7337YQ#tx5A;7d+|G!)jlY4FxEV!N)i#R!}-U=xFv}*+s#!m zFV%_<^V(VVMZ8|n=E2j>uqOhXWU?{i=L}-}*xVyVtO&js0+gUA?c$q)r4#u@HqDe&Zfdd!P1lGS-`4IkHCB?E!`Dp z@|t|kE!Qpy$Z!)zY7^v0G{iYvpn3Wf{p%0GJLbluPFz=o$k=B#_AdNy^H<8!v~Q0@ z+>{jgOXN#ST^>e8`lOV5;t_`j&}tRImPAN#v+-?K_Z~KBRxSBh;SJEPd!80+wj>}R z3^G@&^gAH|0}UPh=wA)FTB+*R{fhmN-Fs1tq_i~re@nJhYnoEne`G^&;Z~)91lN-E z_isV+sVCElYjki8wpzvc*FXFO0$zWt66rOUEps#(y{f^#CJMLij`Ir&wp=nh`n`Z? z3jhi}Z{~y$8O`QPwb?cvyE;21*|jB1Icp`yaQxv9Mj;(rPh*E3OVXi%`*L=G|NaO# zsZ)=u3IdNGi@>xU>wSKD#|O=)*5U}LkG*k;en7)aQrD(&TXoW713ld{YIlSLw0p0= z=q0+ZI)?c3VH9|~0+QI@X;1qNKBdxm7;M%fqGSkW?-ljY`L$-}9;^EXa4?*9=12L2K@BkVPO+t}hH^hRZzl=hGqA#YX zsPcupqhhGe+OZ{+CCQhqQ5K7`TG2_f-3eMD>H!3Rb6{YTl9bF=uh9O_u`a7@9qkIq z-hBV_=SyyGZhql_?A%?#5YwZk=#LJhmCu({@;>gcuIQ!O^m_~#S!R}ah&+5Qqh0fr zdOA@A+{)iFrQ z)Z2>!VL-|yagdN$d=XKV!{xVOpqtWs`w(JZ2K;)6aFq&8=@eG)y&&xxBsu9GX3jgI zl34RYV;7h0%Ea=7AM^rjd(if;)GRc-ZkB7jzAc~N*thmvRUd@gRyepSZjxG=y;0-^ zC~{e8$Scx!Q2=+rT9JtD#)D*h-_gZ2Z;r9TVU$Nj*m(5WE3^@d>TnBN2>mm7vmio) ztI#l1_RQY^D>@!XSqZZ$7mmX)dM+Ky&6>$IXwh)yJ{K;*cLELvqa7q|tnd}e{2HSG zJ{*nDb!F10SL54MK#-Bcnp`|dNZw`{$n(Z@Afo#x>GRi#ankI|iPeDxX>Npp4?scU zG0=G^(g8ji{1_4IZn~!oEFxTO{hUZmws6I9kgjLb1esS!^{G}BA%D_H(Z-vFmMg+Q zfV##4GeJWhO=6jj7&GR%`ZSD6;X4ImnO)8|fDVxMOp2)UzgmUl6$0VVu<2=e8tF(< zm}mlYAkk7=-Wp_diB{m}j6l-U44h!{f3G<`^~4!W`r_dIJX8Nz>!4uM)BBiB(!uFp zS}G#_Y6Z0MPm1%Su!iqO?>QJ(XYB<^YE2Hmu-5u5A(1_wU|^tGd&#_L{S67aw>+!_ zVAr2aczT5Ydkxf+NgBmm@fRU=b*vw`rEnZf2zl6t%-}-kMJ;E@qiM%#oqHAy#tiCTb_+U{ws@8-Ih*H-D<0|_M zv5U$xOU1U&@*y3nm_f2qypxd~S&U+Dn?DQ2U%Ql<--R?-lC8CdQMkkQW0HA~MOgJKg?s-`zfBweW zs+%bNDQAUhOo!C~&gl1GX9jXG_A{MZk>PHV*JCmqG3U2tD5k|Xm zs|~Gt>eJ3XU3O|O?-@|tJMQn>NsRvK;MCb00`c%a1Q_%%=n~kh)nJndzJ8@fxmVql zla%}cSOEW}k<%ySfqd|tf~}r(N@2c{O^b-F22%v;I%|XB$_f7^=|9P_;W*Ql%BO+g zgt*<;kf|A`r*%0%)Eyli<(ryZ9Y2GaIuIB>O5Ih_+}e0~MjRHPkdn$7gB({x`&i0n zd$A)4xLfR0)%dHN36Wp`oNBb}9w9w&GuM`@opW!ws42#5YB6g<%FRu$qSkOO2ih3d zv8uTw8#pL?UyU-v8PDK_wDSd|+qJ^cQbK>1ZQdo-_`MwDUgP;2*gLG{I_~_OIx=5& zsAYYi-07Nc8wRDs2T>Kph*Gq0sx-akL~5<3|8}{K_~&Ei9QHw>Mu2WaUr@& zsD?p|UY~#u%_?t@dePf854$!C{uEw{(B8e(VBk>F;qW@Knm(u>W;vAST=n(5~We5sT`ZxK8>ijUuao zUWwI}N#IB!mW7C)_aq@h`mrG@vy5g~@tD{m*|0sQSxI$2v+S+Tg7NLLzef}O7oBNt z{)WeCBiZ3~=W*Esqg87%VhOj=;%pAMuA0?9pwPksWvpl9;`_beg0lW)raYvI-_CwX zuMh}FyA#eFBIglc2_!E$N;2&N!IDY>Tk8|_V#2NRAaNm`hEa&eyB*dK1JB{U_MWgqW1Q3^K151 zpJD!1#h2P+$6CFNrt{qfqlF21!7I(VX}65iChsD~adqYFGm!pbo-0$!c+Bb)vGT&= z1Y+$Ju+c*imeOCq6vLM0hbdDJW|>pD)Kpa01K0*YBnY;9t1qNPvxY3342SE~ak;@t zmu^AuZ*$8)h_0R9cO>43?g#izMCA~DfIV$t0wBK%U+3j;-gY}o%np)DDaW>Qdgj{iJ3r)Je5z{&4m}pM z0kb~ppYnVpNjD^}BSQDVr7s(ZfjwT%3$xpLdtJxZ+InGA7qy!05d|>B<@0zrE=+xbQ`4976fX*>To^B$-m3=-*?)u3L+x%TXHkUEtK5NxKL#-^WC9Jb3%y;hXcM@li@PBd zIjsHeWIVG4^16fAIFS=rys#+2hSxV$C*^$3Sl4~LLG?RYkDq&1jer|`8V><&iiCiA z_lYFS^Nf5fR|n+%i57`S?j}|eZWOplsijM?0!jIrh6IR5^66JmVj$oIOL_W9msGC- zr|*3D#7V-h0p6DQUj-4h27zvVjq}?Gucjj~HH;s^k2{6=NmYv%Af zi1CwS!i0@i^jVt<{Dh)nUJD}W)}X>cD}_K6VIYbmW~S#~r2`sz9eE<&QZo?V+f(s!O=k_$RohQ&$> zQA0cP_&5$H8YRS{&jno^a}!#Tk^}18wC^;HjETBMz!k}h;ep$!5wGriG|RU%Z5`^8 z{t-GB;%2EqB{A)Og4gSzs(0={nW-fHo*L2nnJKhRrjC%c<(DWzzG4w)t8iwq7h=Kp zm8Z|Y36Br5zyk-=4Ao4TLi0{mJfG*dk`#&bY`$DUqibij%r&T5rbWJgG<>=hm>{7) zh|FrDeu&Zf^;?*eKe8UXz2Hovr20Yj=4U2*2&Lt+fZOB~o%XwTLFYwn!xYco3*M5& zZggvmh)eptQk0sebHFQD1^5bhWrR%}GBV8c;A*%%zyjm$G=fxMuMb6jwgOYhHNRK) z&UxLK2%B}?Hp-eJ{Q4gJKO#;+e>b>j$I3B1LWwvjeJcXN7|*G2%BGP+ORbfSONAXH zqQhJ}OD1kNSRHLTLE0{-o-~{xTsPRS7;MMFBi( zNd!WGmajGf9yQb>*3Hx#7tn>GbPn(X1UOP-pLvW5@oyhU0YmeTHiqZV?xo*_HjI33ckuY^4J?|%<_%a z!a2Dg&IzTW-1sG}+5>g!2AaLWmv2U|q?3lT2vu-yV+SiAi^6>p1+vrptv#TCrz!@;qli3>=kFlNsSc(M-HPcb`HJ z^WeC$lBouqAM3|>eFH!1_-GK!vM$9cPgGuB-eb2#rutQ06`{P7nJ({%d;tqOki0DP zcV3|zRm!TGV&ssMChmNV-%;h*8#%bP3<}yhK{zu$^!lP?>oM9rgfk_dqpyEveh4f! z3W2O0qvL+`F!N;ywSbz$`iduBsc{J~Vv( zV6uvc#&|2WJ&jUI%3G-cB4y!UwT7ZM`H4}3ip+EoiF4Q5e^}Ys!zPpLK~f6|GEGJU z$HUymqzL%QDOgjb=V!`9O(Qv&CG@qizp=OM4i-D7-Ro-t$c=Q?e|`{#pY4e*bzlQR z7VcOzm?2{<+e)RjD|il^}jZ{N)RXnp+vS6&C2i@#ZvgXn0( zoW6kp_2NA7o@*wI3Sd(b(xZlYBu`bZ88twBbH-k_*;d^L_5wnG(p^BooMUg&TJd`i zWbn~CzUow9R=m7*&Ivr>F8*x2n@SF9`Eb{>%8NzKkWl63YbI5D?)J@#ldTD9&tEOE zzi~V3pcdb}$^rKBx1oGmsySn8P;8qv=CQDRd&@2qBwG~k|53+gh1NbFjbISYJi_g_ z5Ar@pS`28un!Le6C@7qM=0eX!n(`i9+f{%SwTkekiD0i}B+7ib<%x9wDEA7_W3f{8 z;nr9sR4sK)5JoqxuTO|t)zf=>dlM27Re{VAre{agvQ}=Xxtr!0Soy$&tl;hR1H{Q3 zHH1DapprB%WW^Y40syX^Q`Ab)P!N8Hgz2vIk1vceR#&DM9}s#vIy_M51>a{eP}}Ll z;KvAW@{u+5YLa>X?_~e@(zRC_V~b~AcP;K#j&owpYQOHB8oCIE0$`WNq?i|W<>+9e zyd+l!(jGex!r83leYMn5xN{u|a(zvuxm-kwIbK z;~91qn$04Vy0;f@Xu-{NBog${8@wujwCLZx07zomNCVRsb9IkqrQLW|d=Nj1{{daf zxYGx!TpCd_Hv891D3cIYE#);R$FL4PKZoE#`Tg?CFEqTGUZ5JZ#%oCp1hc`V>OmnF z5EW%@J-XRa@3&cUGLVq4Q9z}WeYF|Af7c<$IhE1eyipqBGYj%GZkM2yi6kC$RMj8B z&qTzwE*OO7f28u-7PxpPZ^O56`Meq%XGUAYuW-Zp`L`OMya$h6o}JV4TO7lC`XIC= zxm~!_c=W}AvWVtkOyaLcNzOldc4_IkHT=i~lhMjk+vBC)xvQ&mfu-MjCf7Gc$1Fld zLDo_}(yGJCb82k3zqa~Ex{#J22^fysqT83bTJ?w=Ci?WCsKL5D)okYE%E$R~3xN+L zHe}Zu=Ruy^v1z|Zd(#Gh; zd*2D@#K}*>C9C z(1jBbf?kcmNVE2J?f1;cFU+myQKgZW%ye|!AV90`<0ASyb8Oa!i@>STA3{-D?C)58Nhu&AiIM_~{6b^rUsM6aqVm9yP zPp50g1i_^Hg*{~sp(+NnMylQGb}eem)wm(T^Zf^ zpy9_xoQ{%u$Vw-fokYTJ=vPTo_%Jb!ofh;F#9t!2PhluNEk@ z4efJ2eO7GGzWTOTeUy9DJPiGvcQl_C5rK|2E@`}7v*C?EicG#}7KKD^4t2T~xCx05 z>7Vj!jUDc+v&;Eh>V0xDCrZ-HZY(&I^nlrgi^ylYL9XU|g0Q5KLG1vxtrcrKA8 zpE@QKRxq-*LM590NTEKRWRSFGhvpN#gdh9;iuNeS{XF$StjZgILvC7`FXs1*Oss^1 zU~ggV#`3kEi7VvpqJIZoKej$3vya+!5muo2FO{|%kFH`z`OR0^9E29bWbC4UbZU(Z z_4DQ)r5ITI(fS8Xn<^KZP#iH<@Y6uGk$qIjBj@Bi0gOLI)?CF(U)AI1|p#-eB*VmkR{j#Xm?wfQb=Do~S4B=4N z!hWmUURWW_B0%MsvQpZrd~1CTYyWI8@r5(0o82GSC|eu+HanrxvRywQWaKbTzT8Fp zvZeOO&Tmhj^F(QsJ2FswR26y#VZ7S=;bVE~m^ty15GX3S6Zds@?On#|>lZhHulhG& zs-$>>^-I%~e)@@@OByx93#mIYlEhk`giwbo&iv{3n7aGzP4Ui7yW;Ly_^aW=>J1Ek z4K~nIZl@iXz6H>SzaXhsJd+ZLr=9yF7>QsZU+Rk4ot_wp4Sd+38Qm@PYyQG*NaxQL z_5nft3tqeE5x;7p4DktlFV{yW1lhJk=m6JQMe|7_k5I<2zjn;FU4Pbor(fadV&d>` z0krtb4JPg1#=c*0@vzAUkTQtx#XlXa%36`DBI~SC3CDjFzJI$4^Wf7pMJxBjzIkC9`xwY0B^xIGPbayT$EiEmX z^$|o`R<^LT6w+bd`bU5Gl0KPH>{{S4ZtLVW`(D>C4qk)sp7Xvhwpn^nAs!F9g+l>#s(5@S>3Xn z`UN+igzAkU(Ssn4ZzCgEwjnhq!pBsS7<$5ygZiCfEU z-tGOyi2D?&J9RLO4tKm64IK44Ryw92Pp$}Onj1%=TpmStx9W?TnQ}3=&@WCpj%Euk z`-HJ{+UbhhEl5d70Li_+y7q-g85tR5V3m`=5O(>#D!7$}+#XzM8*w#S5`NS5 ziAOh$@wFD(a&vH+FamXEmiyj?%}l1#9D%ooCMf%?5#<8$ziACO&gYxvF0;fdmgOzT zkJ=YclyitW1VuzX^)Jg&LX*_vk<`GLbjIG`!;<51zMKrjw>&dJwBi%uMYv!t@3La0 zMck^Vu2xX&?N}-KqsQ6#*IiklJJd!ic$f^x-S7&nK0ZCA1&9Id&4ur&Pv6PGrjBX=0~qXky5vPrKVBgb z^W2+m2|c#dk60R(ueTS<%F5pUTpvAaT<{>KCSjq`P;WM)1T2!8S6#cEsAq4I+i`@MHdxS)38^C;laLT0rk8degW-UV%8h&)#_=9_w-ulbd#Hg{vy1p2 D=Pi;N diff --git a/testdata/a/test.asset b/testdata/in/a/test.asset similarity index 100% rename from testdata/a/test.asset rename to testdata/in/a/test.asset diff --git a/testdata/b/test.asset b/testdata/in/b/test.asset similarity index 100% rename from testdata/b/test.asset rename to testdata/in/b/test.asset diff --git a/testdata/in/c/test.asset b/testdata/in/c/test.asset new file mode 100644 index 0000000..ab2a2d9 --- /dev/null +++ b/testdata/in/c/test.asset @@ -0,0 +1 @@ +// sample file diff --git a/testdata/out/bindata_debug.go b/testdata/out/bindata_debug.go new file mode 100644 index 0000000..c72c02b --- /dev/null +++ b/testdata/out/bindata_debug.go @@ -0,0 +1,51 @@ +// +build !release + +package main + +import ( + "bytes" + "io" + "log" + "os" +) + +// bindata_read reads the given file from disk. +// It panics if anything went wrong. +func bindata_read(path, name string) []byte { + fd, err := os.Open(path) + if err != nil { + log.Fatalf("Read %s: %v", name, err) + } + + defer fd.Close() + + var buf bytes.Buffer + _, err = io.Copy(&buf, fd) + if err != nil { + log.Fatalf("Read %s: %v", name, err) + } + + return buf.Bytes() +} + +func testdata_in_b_test_asset() []byte { + return bindata_read( + "/a/code/go/src/github.com/jteeuwen/go-bindata/testdata/in/b/test.asset", + "../testdata/in/b/test.asset", + ) +} + +func testdata_in_a_test_asset() []byte { + return bindata_read( + "/a/code/go/src/github.com/jteeuwen/go-bindata/testdata/in/a/test.asset", + "../testdata/in/a/test.asset", + ) +} + +func testdata_in_c_test_asset() []byte { + return bindata_read( + "/a/code/go/src/github.com/jteeuwen/go-bindata/testdata/in/c/test.asset", + "../testdata/in/c/test.asset", + ) +} + diff --git a/testdata/out/bindata_release.go b/testdata/out/bindata_release.go new file mode 100644 index 0000000..61aa67f --- /dev/null +++ b/testdata/out/bindata_release.go @@ -0,0 +1,24 @@ +// +build release + +package main + +func testdata_in_b_test_asset() []byte { + return []byte{ +0x2f,0x2f,0x20,0x73,0x61,0x6d,0x70,0x6c,0x65,0x20,0x66,0x69, +0x6c,0x65,0x0a, + } +} + +func testdata_in_a_test_asset() []byte { + return []byte{ +0x73,0x61,0x6d,0x70,0x6c,0x65,0x20,0x66,0x69,0x6c,0x65,0x0a, + } +} + +func testdata_in_c_test_asset() []byte { + return []byte{ +0x2f,0x2f,0x20,0x73,0x61,0x6d,0x70,0x6c,0x65,0x20,0x66,0x69, +0x6c,0x65,0x0a, + } +} +